diff --git a/DFTFringe.pro b/DFTFringe.pro
index bb981d82..5805fee4 100644
--- a/DFTFringe.pro
+++ b/DFTFringe.pro
@@ -148,6 +148,7 @@ SOURCES += SingleApplication/singleapplication.cpp \
annulushelpdlg.cpp \
arbitrarywavefronthelp.cpp \
arbitrarywavwidget.cpp \
+ astigpolargraph.cpp \
astigscatterplot.cpp \
astigstatsdlg.cpp \
astigzoomer.cpp \
@@ -181,6 +182,7 @@ SOURCES += SingleApplication/singleapplication.cpp \
gplus.cpp \
graphicsutilities.cpp \
helpdlg.cpp \
+ hotkeysdlg.cpp \
igramarea.cpp \
igramintensity.cpp \
imagehisto.cpp \
@@ -204,9 +206,11 @@ SOURCES += SingleApplication/singleapplication.cpp \
outlineplots.cpp \
outlinestatsdlg.cpp \
pdfcalibrationdlg.cpp \
+ percentcorrectiondlg.cpp \
pixelstats.cpp \
plotcolor.cpp \
profileplot.cpp \
+ profileplotpicker.cpp \
psfplot.cpp \
psi_dlg.cpp \
psiphasedisplay.cpp \
@@ -226,6 +230,7 @@ SOURCES += SingleApplication/singleapplication.cpp \
settingsdft.cpp \
settingsGeneral2.cpp \
settingsigram.cpp \
+ settingsigramimportconfig.cpp \
settingsprofile.cpp \
showaliasdlg.cpp \
showallcontoursdlg.cpp \
@@ -266,6 +271,7 @@ HEADERS += bezier/bezier.h \
SingleApplication/singleapplication.h \
annulushelpdlg.h \
arbitrarywavefronthelp.h \
+ astigpolargraph.h \
arbitrarywavwidget.h \
astigscatterplot.h \
astigstatsdlg.h \
@@ -302,6 +308,7 @@ HEADERS += bezier/bezier.h \
gplus.h \
graphicsutilities.h \
helpdlg.h \
+ hotkeysdlg.h \
IgramArea.h \
igramintensity.h \
imagehisto.h \
@@ -324,9 +331,12 @@ HEADERS += bezier/bezier.h \
outlineplots.h \
outlinestatsdlg.h \
pdfcalibrationdlg.h \
+ percentcorrectiondlg.h \
+ percentCorrectionSurface.h \
pixelstats.h \
plotcolor.h \
profileplot.h \
+ profileplotpicker.h \
psfplot.h \
psi_dlg.h \
psiphasedisplay.h \
@@ -346,6 +356,7 @@ HEADERS += bezier/bezier.h \
settingsdft.h \
settingsGeneral2.h \
settingsigram.h \
+ settingsigramimportconfig.h \
settingsprofile.h \
showaliasdlg.h \
showallcontoursdlg.h \
@@ -384,6 +395,7 @@ HEADERS += bezier/bezier.h \
FORMS += arbitrarywavefronthelp.ui \
annulushelpdlg.ui \
+ astigpolargraph.ui \
astigstatsdlg.ui \
averagewavefrontfilesdlg.ui \
batchigramwizard.ui \
@@ -407,6 +419,7 @@ FORMS += arbitrarywavefronthelp.ui \
foucaultview.ui \
generatetargetdlg.ui \
helpdlg.ui \
+ hotkeysdlg.ui \
igramintensity.ui \
jitteroutlinedlg.ui \
lensdialog.ui \
@@ -421,6 +434,7 @@ FORMS += arbitrarywavefronthelp.ui \
outlineplots.ui \
outlinestatsdlg.ui \
pdfcalibrationdlg.ui \
+ percentcorrectiondlg.ui \
pixelstats.ui \
profilearea.ui \
profileplot.ui \
@@ -441,6 +455,7 @@ FORMS += arbitrarywavefronthelp.ui \
settingsdft.ui \
settingsGeneral2.ui \
settingsigram.ui \
+ settingsigramimportconfig.ui \
settingsprofile.ui \
showaliasdlg.ui \
showallcontoursdlg.ui \
diff --git a/DFTFringe_Dale.pro b/DFTFringe_Dale.pro
index 45155013..b0208d0f 100644
--- a/DFTFringe_Dale.pro
+++ b/DFTFringe_Dale.pro
@@ -30,9 +30,11 @@ SOURCES += main.cpp \
annulushelpdlg.cpp \
arbitrarywavefronthelp.cpp \
arbitrarywavwidget.cpp \
+ astigpolargraph.cpp \
cpoint.cpp \
defocusdlg.cpp \
edgeplot.cpp \
+ hotkeysdlg.cpp \
mainwindow.cpp \
igramarea.cpp \
circleoutline.cpp \
@@ -42,8 +44,11 @@ SOURCES += main.cpp \
dftarea.cpp \
oglrendered.cpp \
pdfcalibrationdlg.cpp \
+ percentcorrectiondlg.cpp \
profileplot.cpp \
+ profileplotpicker.cpp \
psiresizeimagesdlg.cpp \
+ settingsigramimportconfig.cpp \
surface3dcontrolsdlg.cpp \
surfacegraph.cpp \
surfacelightingproxy.cpp \
@@ -148,6 +153,7 @@ HEADERS += mainwindow.h \
annulushelpdlg.h \
arbitrarywavefronthelp.h \
arbitrarywavwidget.h \
+ astigpolargraph.h \
cpoint.h \
defocusdlg.h \
edgeplot.h \
@@ -157,10 +163,15 @@ HEADERS += mainwindow.h \
graphicsutilities.h \
dfttools.h \
dftarea.h \
+ hotkeysdlg.h \
oglrendered.h \
pdfcalibrationdlg.h \
+ percentCorrectionSurface.h \
+ percentcorrectiondlg.h \
profileplot.h \
+ profileplotpicker.h \
psiresizeimagesdlg.h \
+ settingsigramimportconfig.h \
surface3dcontrolsdlg.h \
surfacegraph.h \
surfacelightingproxy.h \
@@ -270,16 +281,20 @@ INCLUDEPATH += ./bezier ./SingleApplication
FORMS += mainwindow.ui \
annulushelpdlg.ui \
arbitrarywavefronthelp.ui \
+ astigpolargraph.ui \
defocusdlg.ui \
dfttools.ui \
dftarea.ui \
edgeplot.ui \
+ hotkeysdlg.ui \
oglrendered.ui \
pdfcalibrationdlg.ui \
+ percentcorrectiondlg.ui \
profilearea.ui \
profileplot.ui \
contourtools.ui \
psiresizeimagesdlg.ui \
+ settingsigramimportconfig.ui \
surface3dcontrolsdlg.ui \
surfaceanalysistools.ui \
metricsdisplay.ui \
@@ -408,12 +423,12 @@ RC_FILE = DFTFringe.rc
QMAKE_CXXFLAGS += -std=c++11
# The application version
-VERSION = 6.2
+VERSION = Dale7.3.0
# Define the preprocessor macro to get the application version in our application.
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
DEFINES += QAPPLICATION_CLASS=QApplication
-
+DEFINES += DALE_DO_NOT_LOG
DISTFILES += \
buildingDFTFringe64.txt \
helptext.txt \
diff --git a/RevisionHistory.html b/RevisionHistory.html
index b3a2682c..d233c235 100644
--- a/RevisionHistory.html
+++ b/RevisionHistory.html
@@ -418,3 +418,16 @@
Improved saving speed when working on network drives
+
+- Version 7.3.0
+
+- Added zonal percent completion graph to profile options
+- Added polar plot of the astig of selected wave fronts under View menu.
+- Changed create movie feature to add user provided prefix to each from created.
+- Added hot keys to import interferogram
+- Added hot key to help
+- User can move mouse cursor over any profile shown, click and drag it up or down. Useful for comparing two work sessions results so that they match at zero height.
+- If mouse is over the profile plot the scroll wheel can increase or decrease the y axis range.
+- Added auto collimation setting to Ronchi and Foucault feature
+- Remembered last ROC offset value in Ronchi and Foucault feature to remember last setting when wave front is changed to a different value
+
diff --git a/astigpolargraph.cpp b/astigpolargraph.cpp
new file mode 100644
index 00000000..ce49c900
--- /dev/null
+++ b/astigpolargraph.cpp
@@ -0,0 +1,101 @@
+#include "astigpolargraph.h"
+#include "ui_astigpolargraph.h"
+#include "surfacemanager.h"
+
+void astigPolargraph::makeChart(){
+
+
+ QPolarChart *chart = new QPolarChart();
+
+ // process each wave front and place astig on the chart
+ ui->waveFrontTable->setRowCount(m_list.size());
+
+ QValueAxis *angularAxis = new QValueAxis();
+ angularAxis->setTickCount(9); // First and last ticks are co-located on 0/360 angle.
+ angularAxis->setLabelFormat("%.0f");
+ angularAxis->setShadesVisible(true);
+ angularAxis->setShadesBrush(QBrush(QColor(249, 249, 255)));
+ chart->addAxis(angularAxis, QPolarChart::PolarOrientationAngular);
+
+ QValueAxis *radialAxis = new QValueAxis();
+ radialAxis->setTickCount(5);
+ radialAxis->setLabelFormat("%.1f");
+ chart->addAxis(radialAxis, QPolarChart::PolarOrientationRadial);
+ double maxAstig = 1.;
+
+ QVector wavefronts =SurfaceManager::get_instance()->m_wavefronts;
+
+ for(int ndx = 0; ndx < m_list.length(); ++ndx){
+ wavefront *wf = wavefronts[m_list[ndx]];
+ QString name = wf->name;
+ int slashndx = name.lastIndexOf('/');
+ QString shortName = name.mid(name.lastIndexOf('/',slashndx-1));
+ QTableWidgetItem *item = new QTableWidgetItem(shortName, 0);
+ ui->waveFrontTable->setItem(ndx,0,item);
+ double xastig = wf->InputZerns[4];
+ double yastig = wf->InputZerns[5];
+ double mag = sqrt(xastig * xastig + yastig * yastig);
+ if (mag > maxAstig) maxAstig = mag;
+
+ double angle = (atan2(yastig,xastig)/2.) * 180./M_PI;
+ angle = 90 - angle;
+ QScatterSeries *series = new QScatterSeries();
+
+ int lastndx = name.lastIndexOf('/');
+ if (lastndx != -1)
+ name = name.mid(lastndx);
+ series->setName(name);
+ series->append(angle,mag);
+ series->append(angle+180,mag);
+ chart->addSeries(series);
+ series->attachAxis(radialAxis);
+ series->attachAxis(angularAxis);
+
+ QLineSeries *line = new QLineSeries();
+ line->append(angle,mag);
+ line->append(angle+180,mag);
+ chart->addSeries(line);
+ line->attachAxis(radialAxis);
+ line->attachAxis(angularAxis);
+ chart->legend()->markers(line)[0]->setVisible(false);
+
+ line->setPen(QPen(series->brush(),5));
+
+ QTableWidgetItem *pv = new QTableWidgetItem(QString().number(mag), 0);
+ item->setForeground(series->brush());
+ ui->waveFrontTable->setItem(ndx, 1, pv);
+ QTableWidgetItem *anglewidget = new QTableWidgetItem(QString().number(angle,'f',1), 0);
+ ui->waveFrontTable->setItem(ndx, 2, anglewidget);
+ }
+
+ chart->setTitle("Magnitude and axis of high edge");
+ if (m_list.length() > 4)
+ chart->legend()->setAlignment(Qt::AlignRight);
+ else chart->legend()->setAlignment(Qt::AlignBottom);
+
+ maxAstig = ceil(maxAstig);
+ radialAxis->setRange(0, maxAstig);
+ angularAxis->setRange(0, 360);
+
+ ui->polarChart->setChart(chart);
+
+
+
+}
+astigPolargraph::astigPolargraph( QListlist, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::astigPolargraph), m_list(list)
+{
+ ui->setupUi(this);
+ //For some reason the original starter code of makeChart was in this function but it caused a crash.
+ // I could never figure out why because that code was taken from a working Qt example. When
+ // moved to inside another function it worked. So there you go. Exact same code with no changes worked there but not here.
+ makeChart();
+
+
+}
+
+astigPolargraph::~astigPolargraph()
+{
+ delete ui;
+}
diff --git a/astigpolargraph.h b/astigpolargraph.h
new file mode 100644
index 00000000..e8d3dbcb
--- /dev/null
+++ b/astigpolargraph.h
@@ -0,0 +1,31 @@
+#ifndef ASTIGPOLARGRAPH_H
+#define ASTIGPOLARGRAPH_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "wavefront.h"
+
+namespace Ui {
+class astigPolargraph;
+}
+
+class astigPolargraph : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit astigPolargraph(QList list,QWidget *parent = nullptr);
+ ~astigPolargraph();
+
+private:
+ Ui::astigPolargraph *ui;
+ QList m_list; // list index of selected wave fronts in surface manager's list.
+ void makeChart();
+};
+
+#endif // ASTIGPOLARGRAPH_H
diff --git a/astigpolargraph.ui b/astigpolargraph.ui
new file mode 100644
index 00000000..566f4f73
--- /dev/null
+++ b/astigpolargraph.ui
@@ -0,0 +1,106 @@
+
+
+ astigPolargraph
+
+
+
+ 0
+ 0
+ 640
+ 480
+
+
+
+ Astig polar plot
+
+
+ -
+
+
-
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+ true
+
+
+
+ Wave Front
+
+
+
+
+ Surface astig PV
+
+
+
+
+ Angle
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+ QChartView
+ QGraphicsView
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ astigPolargraph
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ astigPolargraph
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/astigstatsdlg.cpp b/astigstatsdlg.cpp
index 028a64d6..d5f2931c 100644
--- a/astigstatsdlg.cpp
+++ b/astigstatsdlg.cpp
@@ -166,8 +166,8 @@ astigStatsDlg::astigStatsDlg(QVector wavefronts, QWidget *parent) :
Qt::RightButton );
ui->mPlot->setPalette( Qt::white );
-
- ui->bestFitCB->hide();
+qDebug() << "what the heck";
+ //ui->bestFitCB->hide();
plot();
}
diff --git a/contourtools.h b/contourtools.h
index 668865cd..09dedfd2 100644
--- a/contourtools.h
+++ b/contourtools.h
@@ -48,9 +48,11 @@ class ContourTools : public QDockWidget
void newDisplayErrorRange(double, double);
void lineColorChanged(QColor);
void fillChanged(int );
+public slots:
+ void setMinMaxValues(double min,double max);
private slots:
void updateMinMax();
- void setMinMaxValues(double min,double max);
+
void setWaveRange(double val);
void on_ColorMapCB_activated(int index);
diff --git a/defocusdlg.cpp b/defocusdlg.cpp
index 4c5af6c1..0bbd223c 100644
--- a/defocusdlg.cpp
+++ b/defocusdlg.cpp
@@ -1,11 +1,18 @@
#include "defocusdlg.h"
#include "ui_defocusdlg.h"
#include
+#include
defocusDlg::defocusDlg(QWidget *parent) :
QDialog(parent),
ui(new Ui::defocusDlg)
{
ui->setupUi(this);
+ QSettings set;
+
+ if (set.contains("defocus dialogGeometry")) {
+ setGeometry(set.value("defocus dialogGeometry").toRect());
+
+ }
}
defocusDlg::~defocusDlg()
@@ -16,41 +23,57 @@ defocusDlg::~defocusDlg()
-void defocusDlg::on_multiplier_valueChanged(int /*arg1*/)
+void defocusDlg::on_multiplier_valueChanged(int arg1)
{
- on_defocusSlider_valueChanged(ui->defocusSlider->value());
+ double s = ui->defocusSlider->value()/100.;
+ ui->defocusVal->blockSignals(true);
+ ui->defocusVal->setValue( arg1 * s);
+ ui->defocusVal->blockSignals(false);
+ emit defocus(arg1 * s);
}
-#include
+
#include "math.h"
void defocusDlg::on_defocusVal_valueChanged(double arg1)
{
- if (fabs(arg1) > 1) {
+ if (ui->multiplier->value() * ui->defocusSlider->value()/100. != arg1) {
int mul = fabs(arg1/.5);
double slid = arg1/mul;
ui->multiplier->blockSignals(true);
+ ui->spinValue->blockSignals(true);
ui->spinValue->setValue(slid);
-
- ui->multiplier->blockSignals(false);
ui->multiplier->setValue(mul);
+ ui->multiplier->blockSignals(false);
+ ui->spinValue->blockSignals(false);
+
}
else {
-
+ ui->spinValue->blockSignals(true);
ui->spinValue->setValue(arg1);
ui->multiplier->blockSignals(true);
ui->multiplier->setValue(1.);
ui->multiplier->blockSignals(false);
+ ui->spinValue->blockSignals(false);
}
+
emit defocus(arg1);
}
void defocusDlg::on_spinValue_valueChanged(double arg1)
{
+ ui->defocusSlider->blockSignals(true);
ui->defocusSlider->setValue(arg1 * 100);
+ double val = ui->multiplier->value() * arg1;
+ ui->defocusVal->blockSignals(true);
+ ui->defocusVal->setValue(val);
+ ui->defocusVal->blockSignals(false);
+ ui->defocusSlider->blockSignals(false);
+ emit defocus(val);
}
#include "mirrordlg.h"
+#include
void defocusDlg::on_defocusSlider_valueChanged(int value)
{
double val = value/100.;
@@ -58,12 +81,17 @@ void defocusDlg::on_defocusSlider_valueChanged(int value)
ui->spinValue->setValue(val);
ui->spinValue->blockSignals(false);
val *= ui->multiplier->value();
+ ui->defocusVal->blockSignals(true);
+ val *= ui->multiplier->value();
ui->defocusVal->setValue(val);
+ ui->defocusVal->blockSignals(false);
double f = mirrorDlg::get_Instance()->FNumber;
double mm = f * f * 8. * value * .00055; //mmeters
- qDebug() << "mm" << mm;
+ m_defocusInmm = mm;
+ qDebug() << "defocus offset" << mm;
ui->Focusoffset->setText(QString("%1mm").arg(mm, 6,'f',3));
+ emit defocus(val);
}
@@ -77,3 +105,14 @@ void defocusDlg::on_pushButton_clicked()
"The resulting focal length offset is displayed in mm at the lower right.
");
}
+void defocusDlg::moveEvent(QMoveEvent *event) {
+ QSettings set;
+ set.setValue("defocus dialogGeometry", geometry());
+ QDialog::moveEvent(event);
+
+}
+void defocusDlg::closeEvent(QCloseEvent *event) {
+ QSettings set;
+ set.setValue("defocus dialogGeometry", geometry());
+ QDialog::closeEvent(event);
+}
diff --git a/defocusdlg.h b/defocusdlg.h
index 5a69edcf..e68a8b11 100644
--- a/defocusdlg.h
+++ b/defocusdlg.h
@@ -10,10 +10,14 @@ class defocusDlg;
class defocusDlg : public QDialog
{
Q_OBJECT
+ double m_defocusInmm;
public:
explicit defocusDlg(QWidget *parent = nullptr);
~defocusDlg();
+protected:
+ void closeEvent(QCloseEvent *event);
+ void moveEvent(QMoveEvent *event);
signals:
void defocus(double def);
private slots:
diff --git a/foucaultview.cpp b/foucaultview.cpp
index c636f61f..0b917774 100644
--- a/foucaultview.cpp
+++ b/foucaultview.cpp
@@ -101,6 +101,8 @@ void foucaultView::saveFoucaultImage(){
}
void foucaultView::setSurface(wavefront *wf){
+ QSettings set;
+ double offset = set.value("foucault roc offset", 0.).toDouble();
m_wf = wf;
mirrorDlg *md = mirrorDlg::get_Instance();
double rad = md->diameter/2.;
@@ -108,12 +110,8 @@ void foucaultView::setSurface(wavefront *wf){
double mul = (ui->useMM->isChecked()) ? 1. : 1/25.4;
m_sag = mul * (rad * rad) /( 4 * FL);
m_sag = round(100 * m_sag)/100.;
- m_temp_sag = m_sag;
- ui->rocOffsetSlider->blockSignals(true);
- ui->rocOffsetSlider->setValue((m_sag/2.)/getStep());
- ui->rocOffsetSlider->blockSignals(false);
- double step = getStep();
- double offset = (ui->rocOffsetSlider->value()) * step;
+ m_temp_sag = m_sag; // used to set the zernike slider step size to make it appropriate to a faction of the sagitta.
+
ui->rocOffsetSb->blockSignals(true);
ui->rocOffsetSb->setValue(offset);
ui->rocOffsetSb->blockSignals(false);
@@ -197,7 +195,9 @@ void foucaultView::on_makePb_clicked()
double z3 = pv / ( moving_constant);
bool oldDoNull = md->doNull;
- md->doNull = false;
+ if (!ui->autocollimation->isChecked()){
+ md->doNull = false;
+ }
cv::Mat surf_fft;
SimulationsView *sv = SimulationsView::getInstance(0);
@@ -469,7 +469,9 @@ void foucaultView::on_rocOffsetSb_editingFinished()
ui->rocOffsetSlider->blockSignals(true);
ui->rocOffsetSlider->setValue(pos);
ui->rocOffsetSlider->blockSignals(false);
-qDebug() << "slider" << val << step << pos;
+ QSettings set;
+ set.setValue("foucault roc offset", val);
+
m_guiTimer.start(500);
}
@@ -589,9 +591,11 @@ void foucaultView::on_rocOffsetSlider_valueChanged(int value)
double step = getStep();
double offset = (value) * step;
+ QSettings set;
- ui->rocOffsetSb->setValue(offset);
+ set.setValue("foucault roc offset", offset);
+ ui->rocOffsetSb->setValue(offset);
m_guiTimer.start(1000);
}
@@ -693,8 +697,9 @@ void foucaultView::on_pushButton_clicked()
ui->rocOffsetSlider->blockSignals(true);
ui->rocOffsetSlider->setValue((m_sag/2.)/getStep());
ui->rocOffsetSlider->blockSignals(false);
- double step = getStep();
- double offset = (ui->rocOffsetSlider->value()) * step;
+ double offset = (m_sag/2);
+ QSettings set;
+ set.setValue("foucault roc offset", offset);
ui->rocOffsetSb->blockSignals(true);
ui->rocOffsetSb->setValue(offset);
ui->rocOffsetSb->blockSignals(false);
@@ -703,3 +708,16 @@ void foucaultView::on_pushButton_clicked()
on_makePb_clicked();
}
+
+
+
+
+void foucaultView::on_autocollimation_clicked(bool checked)
+{
+ if (checked)
+ ui->h2x->setChecked(true);
+ else
+ ui->h1x->setChecked(true);
+ on_makePb_clicked();
+}
+
diff --git a/foucaultview.h b/foucaultview.h
index 591196df..c52afe92 100644
--- a/foucaultview.h
+++ b/foucaultview.h
@@ -80,6 +80,8 @@ private slots:
void on_pushButton_clicked();
+ void on_autocollimation_clicked(bool checked);
+
private:
Ui::foucaultView *ui;
SurfaceManager *m_sm;
diff --git a/foucaultview.ui b/foucaultview.ui
index c16a2f8f..9d5c24e4 100644
--- a/foucaultview.ui
+++ b/foucaultview.ui
@@ -230,53 +230,48 @@
-
-
-
- Surface Height
-
-
-
-
- 10
- 20
- 82
- 17
-
-
-
- 1X
-
-
- true
-
-
-
-
-
- 10
- 40
- 82
- 17
-
-
-
- 2X
-
-
-
-
-
- 10
- 60
- 82
- 17
-
-
-
- 4x
-
-
-
+
+
-
+
+
+ auto collimation
+
+
+
+ -
+
+
+ Surface Height
+
+
+
-
+
+
+ 1X
+
+
+ true
+
+
+
+ -
+
+
+ 2X
+
+
+
+ -
+
+
+ 4x
+
+
+
+
+
+
+
-
diff --git a/graphmodifier.cpp b/graphmodifier.cpp
new file mode 100644
index 00000000..05772685
--- /dev/null
+++ b/graphmodifier.cpp
@@ -0,0 +1,419 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Data Visualization module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphmodifier.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace QtDataVisualization;
+
+
+
+//! [0]
+GraphModifier::GraphModifier(Q3DBars *bargraph)
+ : m_graph(bargraph),
+ m_xRotation(0.0f),
+ m_yRotation(0.0f),
+ m_fontSize(30),
+ m_segments(4),
+ m_subSegments(3),
+ m_minval(0),
+ m_maxval(120),
+ //! [1]
+ m_temperatureAxis(new QValue3DAxis),
+ m_yearAxis(new QCategory3DAxis),
+ m_monthAxis(new QCategory3DAxis),
+ m_primarySeries(new QBar3DSeries),
+ m_secondarySeries(new QBar3DSeries),
+ //! [1]
+ m_barMesh(QAbstract3DSeries::MeshBevelBar),
+ m_smooth(false)
+{
+ //! [2]
+ m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftMedium);
+ m_graph->activeTheme()->setBackgroundEnabled(false);
+ m_graph->activeTheme()->setFont(QFont("Times New Roman", m_fontSize));
+ m_graph->activeTheme()->setLabelBackgroundEnabled(true);
+ m_graph->setMultiSeriesUniform(true);
+ //! [2]
+
+
+
+ //! [3]
+ m_temperatureAxis->setTitle("Percent Correction");
+ m_temperatureAxis->setSegmentCount(m_segments);
+ m_temperatureAxis->setSubSegmentCount(m_subSegments);
+ m_temperatureAxis->setRange(m_minval, m_maxval);
+
+ m_temperatureAxis->setLabelAutoRotation(30.0f);
+ m_temperatureAxis->setTitleVisible(true);
+
+ m_yearAxis->setTitle("Surface");
+ m_yearAxis->setLabelAutoRotation(30.0f);
+ m_yearAxis->setTitleVisible(true);
+ m_monthAxis->setTitle("Zone");
+ m_monthAxis->setLabelAutoRotation(30.0f);
+ m_monthAxis->setTitleVisible(true);
+
+ m_graph->setValueAxis(m_temperatureAxis);
+ m_graph->setRowAxis(m_yearAxis);
+ m_graph->setColumnAxis(m_monthAxis);
+ //! [3]
+
+ //! [8]
+ m_primarySeries->setItemLabelFormat(QStringLiteral("Oulu - @colLabel @rowLabel: @valueLabel"));
+ m_primarySeries->setMesh(QAbstract3DSeries::MeshBevelBar);
+ m_primarySeries->setMeshSmooth(false);
+
+ m_secondarySeries->setItemLabelFormat(QStringLiteral("Helsinki - @colLabel @rowLabel: @valueLabel"));
+ m_secondarySeries->setMesh(QAbstract3DSeries::MeshBevelBar);
+ m_secondarySeries->setMeshSmooth(false);
+ m_secondarySeries->setVisible(false);
+ //! [8]
+
+ //! [4]
+ m_graph->addSeries(m_primarySeries);
+ m_graph->addSeries(m_secondarySeries);
+ //! [4]
+
+ //! [6]
+ changePresetCamera();
+ //! [6]
+
+ //! [9]
+ //resetData();
+ //! [9]
+
+ // Set up property animations for zooming to the selected bar
+ //! [12]
+ Q3DCamera *camera = m_graph->scene()->activeCamera();
+ m_defaultAngleX = camera->xRotation();
+ m_defaultAngleY = camera->yRotation();
+ m_defaultZoom = camera->zoomLevel();
+ m_defaultTarget = camera->target();
+
+ m_animationCameraX.setTargetObject(camera);
+ m_animationCameraY.setTargetObject(camera);
+ m_animationCameraZoom.setTargetObject(camera);
+ m_animationCameraTarget.setTargetObject(camera);
+
+ m_animationCameraX.setPropertyName("xRotation");
+ m_animationCameraY.setPropertyName("yRotation");
+ m_animationCameraZoom.setPropertyName("zoomLevel");
+ m_animationCameraTarget.setPropertyName("target");
+
+ int duration = 1700;
+ m_animationCameraX.setDuration(duration);
+ m_animationCameraY.setDuration(duration);
+ m_animationCameraZoom.setDuration(duration);
+ m_animationCameraTarget.setDuration(duration);
+
+ // The zoom always first zooms out above the graph and then zooms in
+ qreal zoomOutFraction = 0.3;
+ m_animationCameraX.setKeyValueAt(zoomOutFraction, QVariant::fromValue(0.0f));
+ m_animationCameraY.setKeyValueAt(zoomOutFraction, QVariant::fromValue(90.0f));
+ m_animationCameraZoom.setKeyValueAt(zoomOutFraction, QVariant::fromValue(50.0f));
+ m_animationCameraTarget.setKeyValueAt(zoomOutFraction,
+ QVariant::fromValue(QVector3D(0.0f, 0.0f, 0.0f)));
+ //! [12]
+}
+//! [0]
+
+GraphModifier::~GraphModifier()
+{
+ delete m_graph;
+}
+
+void GraphModifier::resetData(QList > data, QStringList names)
+{
+ //! [5]
+ // Set up data
+
+
+ // Create data arrays
+ QBarDataArray *dataSet = new QBarDataArray;
+
+
+
+ dataSet->reserve(data.size());
+ for (int i = 0; i < data.size(); i++) {
+ // Create a data row
+ QBarDataRow *dataRow = new QBarDataRow(data[i].size());
+
+ for (int s = 0; s < data[i].size(); s++) {
+ // Add data to the row
+ (*dataRow)[s].setValue(data[i][s]);
+
+ }
+ // Add the row to the set
+ dataSet->append(dataRow);
+
+ }
+ m_months.clear();
+ for (int i = 0; i <= data[0].length(); ++i) {
+ m_months << QString::number(i+1);
+ }
+ // Add data to the data proxy (the data proxy assumes ownership of it)
+ m_primarySeries->dataProxy()->resetArray(dataSet, names, m_months);
+
+ //! [5]
+}
+
+void GraphModifier::changeRange(int range)
+{
+ if (range >= m_years.count())
+ m_yearAxis->setRange(0, m_years.count() - 1);
+ else
+ m_yearAxis->setRange(range, range);
+}
+
+void GraphModifier::changeStyle(int style)
+{
+ QComboBox *comboBox = qobject_cast(sender());
+ if (comboBox) {
+ m_barMesh = QAbstract3DSeries::Mesh(comboBox->itemData(style).toInt());
+ m_primarySeries->setMesh(m_barMesh);
+ m_secondarySeries->setMesh(m_barMesh);
+ }
+}
+
+void GraphModifier::changePresetCamera()
+{
+ m_animationCameraX.stop();
+ m_animationCameraY.stop();
+ m_animationCameraZoom.stop();
+ m_animationCameraTarget.stop();
+
+ // Restore camera target in case animation has changed it
+ m_graph->scene()->activeCamera()->setTarget(QVector3D(0.0f, 0.0f, 0.0f));
+
+ //! [10]
+ static int preset = Q3DCamera::CameraPresetFront;
+
+ m_graph->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset);
+
+ if (++preset > Q3DCamera::CameraPresetDirectlyBelow)
+ preset = Q3DCamera::CameraPresetFrontLow;
+ //! [10]
+}
+
+void GraphModifier::changeTheme(int theme)
+{
+ Q3DTheme *currentTheme = m_graph->activeTheme();
+ currentTheme->setType(Q3DTheme::Theme(theme));
+ emit backgroundEnabledChanged(currentTheme->isBackgroundEnabled());
+ emit gridEnabledChanged(currentTheme->isGridEnabled());
+ emit fontChanged(currentTheme->font());
+ emit fontSizeChanged(currentTheme->font().pointSize());
+}
+
+void GraphModifier::changeLabelBackground()
+{
+ m_graph->activeTheme()->setLabelBackgroundEnabled(!m_graph->activeTheme()->isLabelBackgroundEnabled());
+}
+
+void GraphModifier::changeSelectionMode(int selectionMode)
+{
+ QComboBox *comboBox = qobject_cast(sender());
+ if (comboBox) {
+ int flags = comboBox->itemData(selectionMode).toInt();
+ m_graph->setSelectionMode(QAbstract3DGraph::SelectionFlags(flags));
+ }
+}
+
+void GraphModifier::changeFont(const QFont &font)
+{
+ QFont newFont = font;
+ m_graph->activeTheme()->setFont(newFont);
+}
+
+void GraphModifier::changeFontSize(int fontsize)
+{
+ m_fontSize = fontsize;
+ QFont font = m_graph->activeTheme()->font();
+ font.setPointSize(m_fontSize);
+ m_graph->activeTheme()->setFont(font);
+}
+
+void GraphModifier::shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality sq)
+{
+ int quality = int(sq);
+ // Updates the UI component to show correct shadow quality
+ emit shadowQualityChanged(quality);
+}
+
+void GraphModifier::changeLabelRotation(int rotation)
+{
+ m_temperatureAxis->setLabelAutoRotation(float(rotation));
+ m_monthAxis->setLabelAutoRotation(float(rotation));
+ m_yearAxis->setLabelAutoRotation(float(rotation));
+}
+
+void GraphModifier::setAxisTitleVisibility(bool enabled)
+{
+ m_temperatureAxis->setTitleVisible(enabled);
+ m_monthAxis->setTitleVisible(enabled);
+ m_yearAxis->setTitleVisible(enabled);
+}
+
+void GraphModifier::setAxisTitleFixed(bool enabled)
+{
+ m_temperatureAxis->setTitleFixed(enabled);
+ m_monthAxis->setTitleFixed(enabled);
+ m_yearAxis->setTitleFixed(enabled);
+}
+
+//! [11]
+void GraphModifier::zoomToSelectedBar()
+{
+ m_animationCameraX.stop();
+ m_animationCameraY.stop();
+ m_animationCameraZoom.stop();
+ m_animationCameraTarget.stop();
+
+ Q3DCamera *camera = m_graph->scene()->activeCamera();
+ float currentX = camera->xRotation();
+ float currentY = camera->yRotation();
+ float currentZoom = camera->zoomLevel();
+ QVector3D currentTarget = camera->target();
+
+ m_animationCameraX.setStartValue(QVariant::fromValue(currentX));
+ m_animationCameraY.setStartValue(QVariant::fromValue(currentY));
+ m_animationCameraZoom.setStartValue(QVariant::fromValue(currentZoom));
+ m_animationCameraTarget.setStartValue(QVariant::fromValue(currentTarget));
+
+ QPoint selectedBar = m_graph->selectedSeries()
+ ? m_graph->selectedSeries()->selectedBar()
+ : QBar3DSeries::invalidSelectionPosition();
+
+ if (selectedBar != QBar3DSeries::invalidSelectionPosition()) {
+ // Normalize selected bar position within axis range to determine target coordinates
+ //! [13]
+ QVector3D endTarget;
+ float xMin = m_graph->columnAxis()->min();
+ float xRange = m_graph->columnAxis()->max() - xMin;
+ float zMin = m_graph->rowAxis()->min();
+ float zRange = m_graph->rowAxis()->max() - zMin;
+ endTarget.setX((selectedBar.y() - xMin) / xRange * 2.0f - 1.0f);
+ endTarget.setZ((selectedBar.x() - zMin) / zRange * 2.0f - 1.0f);
+ //! [13]
+
+ // Rotate the camera so that it always points approximately to the graph center
+ //! [15]
+ qreal endAngleX = 90.0 - qRadiansToDegrees(qAtan(qreal(endTarget.z() / endTarget.x())));
+ if (endTarget.x() > 0.0f)
+ endAngleX -= 180.0f;
+ float barValue = m_graph->selectedSeries()->dataProxy()->itemAt(selectedBar.x(),
+ selectedBar.y())->value();
+ float endAngleY = barValue >= 0.0f ? 30.0f : -30.0f;
+ if (m_graph->valueAxis()->reversed())
+ endAngleY *= -1.0f;
+ //! [15]
+
+ m_animationCameraX.setEndValue(QVariant::fromValue(float(endAngleX)));
+ m_animationCameraY.setEndValue(QVariant::fromValue(endAngleY));
+ m_animationCameraZoom.setEndValue(QVariant::fromValue(250));
+ //! [14]
+ m_animationCameraTarget.setEndValue(QVariant::fromValue(endTarget));
+ //! [14]
+ } else {
+ // No selected bar, so return to the default view
+ m_animationCameraX.setEndValue(QVariant::fromValue(m_defaultAngleX));
+ m_animationCameraY.setEndValue(QVariant::fromValue(m_defaultAngleY));
+ m_animationCameraZoom.setEndValue(QVariant::fromValue(m_defaultZoom));
+ m_animationCameraTarget.setEndValue(QVariant::fromValue(m_defaultTarget));
+ }
+
+ m_animationCameraX.start();
+ m_animationCameraY.start();
+ m_animationCameraZoom.start();
+ m_animationCameraTarget.start();
+}
+//! [11]
+
+void GraphModifier::changeShadowQuality(int quality)
+{
+ QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality);
+ m_graph->setShadowQuality(sq);
+ emit shadowQualityChanged(quality);
+}
+
+//! [7]
+void GraphModifier::rotateX(int rotation)
+{
+ m_xRotation = rotation;
+ m_graph->scene()->activeCamera()->setCameraPosition(m_xRotation, m_yRotation);
+}
+
+void GraphModifier::rotateY(int rotation)
+{
+ m_yRotation = rotation;
+ m_graph->scene()->activeCamera()->setCameraPosition(m_xRotation, m_yRotation);
+}
+//! [7]
+
+void GraphModifier::setBackgroundEnabled(int enabled)
+{
+ m_graph->activeTheme()->setBackgroundEnabled(bool(enabled));
+}
+
+void GraphModifier::setGridEnabled(int enabled)
+{
+ m_graph->activeTheme()->setGridEnabled(bool(enabled));
+}
+
+void GraphModifier::setSmoothBars(int smooth)
+{
+ m_smooth = bool(smooth);
+ m_primarySeries->setMeshSmooth(m_smooth);
+ m_secondarySeries->setMeshSmooth(m_smooth);
+}
+
+void GraphModifier::setSeriesVisibility(int enabled)
+{
+ m_secondarySeries->setVisible(bool(enabled));
+}
+
+void GraphModifier::setReverseValueAxis(int enabled)
+{
+ m_graph->valueAxis()->setReversed(enabled);
+}
+
+void GraphModifier::setReflection(bool enabled)
+{
+ m_graph->setReflection(enabled);
+}
diff --git a/graphmodifier.h b/graphmodifier.h
new file mode 100644
index 00000000..0d9a526f
--- /dev/null
+++ b/graphmodifier.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Data Visualization module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRAPHMODIFIER_H
+#define GRAPHMODIFIER_H
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include "percentCorrectionSurface.h"
+using namespace QtDataVisualization;
+
+class GraphModifier : public QObject
+{
+ Q_OBJECT
+public:
+ explicit GraphModifier(Q3DBars *bargraph);
+ ~GraphModifier();
+
+ void resetData(QList >data, QStringList names);
+ void changePresetCamera();
+ void changeLabelBackground();
+ void changeFont(const QFont &font);
+ void changeFontSize(int fontsize);
+ void rotateX(int rotation);
+ void rotateY(int rotation);
+ void setBackgroundEnabled(int enabled);
+ void setGridEnabled(int enabled);
+ void setSmoothBars(int smooth);
+ void setSeriesVisibility(int enabled);
+ void setReverseValueAxis(int enabled);
+ void setReflection(bool enabled);
+
+public Q_SLOTS:
+ void changeRange(int range);
+ void changeStyle(int style);
+ void changeSelectionMode(int selectionMode);
+ void changeTheme(int theme);
+ void changeShadowQuality(int quality);
+ void shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality shadowQuality);
+ void changeLabelRotation(int rotation);
+ void setAxisTitleVisibility(bool enabled);
+ void setAxisTitleFixed(bool enabled);
+ void zoomToSelectedBar();
+
+Q_SIGNALS:
+ void shadowQualityChanged(int quality);
+ void backgroundEnabledChanged(bool enabled);
+ void gridEnabledChanged(bool enabled);
+ void fontChanged(QFont font);
+ void fontSizeChanged(int size);
+
+private:
+ Q3DBars *m_graph;
+ float m_xRotation;
+ float m_yRotation;
+ int m_fontSize;
+ int m_segments;
+ int m_subSegments;
+ float m_minval;
+ float m_maxval;
+ QStringList m_months;
+ QStringList m_years;
+ QValue3DAxis *m_temperatureAxis;
+ QCategory3DAxis *m_yearAxis;
+ QCategory3DAxis *m_monthAxis;
+ QBar3DSeries *m_primarySeries;
+ QBar3DSeries *m_secondarySeries;
+ QAbstract3DSeries::Mesh m_barMesh;
+ bool m_smooth;
+ QPropertyAnimation m_animationCameraX;
+ QPropertyAnimation m_animationCameraY;
+ QPropertyAnimation m_animationCameraZoom;
+ QPropertyAnimation m_animationCameraTarget;
+ float m_defaultAngleX;
+ float m_defaultAngleY;
+ float m_defaultZoom;
+ QVector3D m_defaultTarget;
+};
+
+#endif
diff --git a/hotkeysdlg.cpp b/hotkeysdlg.cpp
new file mode 100644
index 00000000..a1f45b3c
--- /dev/null
+++ b/hotkeysdlg.cpp
@@ -0,0 +1,14 @@
+#include "hotkeysdlg.h"
+#include "ui_hotkeysdlg.h"
+
+HotKeysDlg::HotKeysDlg(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::HotKeysDlg)
+{
+ ui->setupUi(this);
+}
+
+HotKeysDlg::~HotKeysDlg()
+{
+ delete ui;
+}
diff --git a/hotkeysdlg.h b/hotkeysdlg.h
new file mode 100644
index 00000000..9524cda5
--- /dev/null
+++ b/hotkeysdlg.h
@@ -0,0 +1,22 @@
+#ifndef HOTKEYSDLG_H
+#define HOTKEYSDLG_H
+
+#include
+
+namespace Ui {
+class HotKeysDlg;
+}
+
+class HotKeysDlg : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit HotKeysDlg(QWidget *parent = nullptr);
+ ~HotKeysDlg();
+
+private:
+ Ui::HotKeysDlg *ui;
+};
+
+#endif // HOTKEYSDLG_H
diff --git a/hotkeysdlg.ui b/hotkeysdlg.ui
new file mode 100644
index 00000000..51fa64a9
--- /dev/null
+++ b/hotkeysdlg.ui
@@ -0,0 +1,71 @@
+
+
+ HotKeysDlg
+
+
+
+ 0
+ 0
+ 640
+ 480
+
+
+
+ -----------------------------Hot keys used in DFtfringe -----------------------------------------
+
+
+
-
+
+
+ TextLabel
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ HotKeysDlg
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ HotKeysDlg
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/igramarea.cpp b/igramarea.cpp
index 28054d03..aa546a93 100644
--- a/igramarea.cpp
+++ b/igramarea.cpp
@@ -119,8 +119,6 @@ IgramArea::IgramArea(QWidget *parent, void *mw)
needToConvertBGR = false;
QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_Down), this);
QObject::connect(shortcut, SIGNAL(activated()), this, SLOT(shiftDown()));
- shortcut = new QShortcut(QKeySequence("d"), this);
- QObject::connect(shortcut, SIGNAL(activated()), this, SLOT(shiftDown()));
shortcut = new QShortcut(QKeySequence(Qt::Key_Up), this);
QObject::connect(shortcut, SIGNAL(activated()), this, SLOT(shiftUp()));
shortcut = new QShortcut(QKeySequence(Qt::Key_Left), this);
@@ -2269,6 +2267,7 @@ void IgramArea::readOutlines(){
return;
deleteRegions();
loadOutlineFileOldV6(fileName);
+ drawBoundary();
}
QString IgramArea::makeOutlineName(){
QSettings settings;
diff --git a/main.cpp b/main.cpp
index 899d146c..e4df488b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -26,6 +26,7 @@
#include "spdlog/sinks/stdout_color_sinks.h"
#include "boost/stacktrace.hpp"
+
static void my_terminate_handler() {
try {
spdlog::get("logger")->critical("Unexpected issue. Stacktrace:\n" + boost::stacktrace::to_string((boost::stacktrace::stacktrace())));
@@ -101,7 +102,7 @@ int main(int argc, char *argv[])
spdlog::flush_every(std::chrono::seconds(3));
// Set the logging format
- spdlog::get("logger")->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");
+ //spdlog::get("logger")->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");
// Set logger level
settingsDebug::setLogLevel(settingsDebug::getLogLevel());
@@ -118,12 +119,13 @@ int main(int argc, char *argv[])
// from here, any problematic application exit (for example uncatched exceptions) should call my_terminate_handler
std::set_terminate(&my_terminate_handler);
-
+#ifndef DALE_DO_NOT_LOG
// override QT message handler because qFatal() and qCritical() would exit cleanly without crashlog
qInstallMessageHandler(myQtMessageOutput); // replace with nullptr if you want to use original bahavior for debug purpose
// override CV error handler to get crashlog to execute instead of clean exit
- cv::redirectError(myCvErrorCallback); // replace with nullptr if you want to use original bahavior for debug purpose
+ cv::redirectError(myCvErrorCallback); // replace with nullptr if you want to use original bahavior for debug purpose
+#endif
spdlog::get("logger")->critical("This is a demo stacktrace:\n" + boost::stacktrace::to_string((boost::stacktrace::stacktrace())));
MainWindow *w = new MainWindow;
diff --git a/mainwindow.cpp b/mainwindow.cpp
index b9ca8746..758e184a 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -48,7 +48,7 @@
#include "colorchannel.h"
#include "opencv2/opencv.hpp"
#include "spdlog/spdlog.h"
-
+#include
using namespace QtConcurrent;
std::vector g_wavefronts;
@@ -63,6 +63,10 @@ MainWindow::MainWindow(QWidget *parent) :
{
ui->setupUi(this);
ui->useAnnulust->hide();
+ QList acts = ui->menuBar->actions();
+ foreach(QAction* a, acts){
+ a->menu()->setToolTipsVisible(true);
+ }
spdlog::get("logger")->info("DFTFringe {} started", APP_VERSION);
//const QString toolButtonStyle("QToolButton {"
@@ -199,6 +203,14 @@ MainWindow::MainWindow(QWidget *parent) :
connect(m_igramArea, SIGNAL(doDFT()), m_dftArea, SLOT(doDFT()));
enableShiftButtons(true);
+ QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_I), this);
+ QObject::connect(shortcut, SIGNAL(activated()), this, SLOT(importIgram()));
+
+ QShortcut *shortcutl = new QShortcut(QKeySequence(Qt::Key_L), this);
+ QObject::connect(shortcutl, SIGNAL(activated()), this, SLOT(on_actionLoad_Interferogram_triggered()));
+
+ QShortcut *shortcut1 = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_O), this);
+ QObject::connect(shortcut1, SIGNAL(activated()), this, SLOT(on_actionLoad_Interferogram_triggered()));
connect(m_dftTools,SIGNAL(doDFT()),m_dftArea,SLOT(doDFT()));
settingsDlg = Settings2::getInstance();
@@ -260,6 +272,28 @@ MainWindow::MainWindow(QWidget *parent) :
openWaveFrontonInit(args);
}
+void MainWindow::importIgram() {
+ QSettings set;
+
+ if (set.value("importIgramOpenMostRecent", true).toBool()){
+ QString dirPath = set.value("importIgramPath",".").toString();
+ QDir dir(dirPath);
+ QStringList filters;
+ filters << "*.png" << "*.jpg" << "*.jpeg" << "*.bmp" << "*.gif"; // Add more image formats if needed
+
+ dir.setNameFilters(filters);
+ dir.setFilter(QDir::Files | QDir::Readable);
+ QFileInfoList fileList = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Time | QDir::Reversed);
+
+ if (fileList.isEmpty())
+ return;
+
+ loadFile( fileList.last().filePath());
+ }
+ else on_actionLoad_Interferogram_triggered();
+
+}
+
int showmem(QString t);
void MainWindow::openWaveFrontonInit(QStringList args){
QProgressDialog pd(" Loading wavefronts in progress.", "Cancel", 0, 100);
@@ -700,13 +734,6 @@ void MainWindow::on_actionDelete_wave_front_triggered()
}
-
-void MainWindow::on_actionWrite_WaveFront_triggered()
-{
-
-}
-
-
void MainWindow::on_actionSave_Wavefront_triggered()
{
m_surfaceManager->SaveWavefronts(false);
@@ -837,7 +864,7 @@ void MainWindow::on_actionSave_interferogram_triggered()
void MainWindow::on_actionSave_screen_triggered()
{
QSettings set;
- QString path = set.value("mirrorConfigFile").toString();
+ QString path = set.value("saveImagePath").toString();
QFile fn(path);
QFileInfo info(fn.fileName());
QString dd = info.dir().absolutePath();
@@ -864,7 +891,7 @@ void MainWindow::on_actionSave_screen_triggered()
if (fName.isEmpty())
return;
-
+ set.setValue("saveImagePath", fName);
QImage image( this->size(), QImage::Format_ARGB32 );
@@ -875,8 +902,15 @@ void MainWindow::on_actionSave_screen_triggered()
this->render( &painter);
painter.setPen(QPen(Qt::red,5));
+ // want to place the ogl widget back into the main window.
+ // get the topleft of the ogl but it's parent is not the main window
+ QPoint ml = this->mapToGlobal(QPoint (0,0));
QRect widgetRect = m_ogl->m_container->geometry();
- widgetRect.moveTopLeft(m_ogl->mapToGlobal(QPoint(0,20)));
+ QPoint tl = m_ogl->m_container->mapToGlobal(QPoint(0,0));
+ QPoint offset = tl-ml;
+
+
+ widgetRect.moveTopLeft(offset);
painter.drawImage(widgetRect, SurfaceImage);
@@ -1108,7 +1142,7 @@ void MainWindow::batchProcess(QStringList fileList){
}
QApplication::processEvents();
- QObject().thread()->msleep(1000);
+ //QObject().thread()->msleep(1000);
ui->SelectOutSideOutline->setChecked(true);
if (!batchIgramWizard::autoCb->isChecked()){
while (m_inBatch && !m_OutlineDoneInBatch && !m_skipItem) {
@@ -1125,7 +1159,7 @@ void MainWindow::batchProcess(QStringList fileList){
m_igramArea->nextStep();
QApplication::processEvents();
- QObject().thread()->msleep(1000);
+ //QObject().thread()->msleep(1000);
m_batchMakeSurfaceReady = false;
if (!batchIgramWizard::autoCb->isChecked() && !m_skipItem){
@@ -1610,80 +1644,195 @@ void MainWindow::on_useLastOutline_clicked()
void MainWindow::on_actionCreate_Movie_of_wavefronts_triggered()
{
-// QStringList fileNames = SelectWaveFrontFiles();
-// this->setCursor(Qt::WaitCursor);
-// QProgressDialog pd(" Loading wavefronts in PRogress.", "Cancel", 0, 100);
-// pd.setRange(0, fileNames.size());
-// if (fileNames.length()> 0)
-// pd.show();
-// int cnt = 0;
-// QSettings set;
-// QString lastPath = set.value("lastPath",".").toString();
-// int memThreshold = set.value("lowMemoryThreshold",300).toInt();
-// QImage img = m_ogl->m_gl->grabFrameBuffer();
-
-// int width = img.width();
-// int height = img.height();
-
-// try {
-// QString fileName = QFileDialog::getSaveFileName(0, "Save AVI video as:", lastPath,"*.avi" );
-// if (fileName.length() > 0){
-// if (!(fileName.toUpper().endsWith(".AVI")))
-// fileName.append(".avi");
-// cv::VideoWriter video(fileName.toStdString().c_str(),-1,4,cv::Size(width,height),true);
-// if (!video.isOpened()){
-// QString msg = QString("could not open %1 %2x%3 for writing.").arg(fileName).arg(
-// width).arg(height);
-// QMessageBox::warning(0,"warning", msg);
-// return;
-// }
-// foreach (QString name, fileNames){
-// int mem = showmem("loading");
-// statusBar()->showMessage(QString("memory %1 MB").arg(mem));
-// if (mem< memThreshold + 50){
-// while (m_surfaceManager->m_wavefronts.size() > 1){
-// m_surfaceManager->deleteCurrent();
-// }
-// }
-// QApplication::processEvents();
-
-// if (pd.wasCanceled())
-// break;
-
-
-// pd.setLabelText(name);
-// QApplication::processEvents();
-// wavefront *wf = m_surfaceManager->readWaveFront(name);
-
-// m_surfaceManager->makeMask(wf);
-// m_surfaceManager->generateSurfacefromWavefront(wf);
-// m_surfaceManager->computeMetrics(wf);
-
-// pd.setValue(++cnt);
-
-// m_ogl->m_gl->setSurface(wf);
-// delete wf;
-// QApplication::processEvents();
-
-// QImage img = m_ogl->m_gl->grabFrameBuffer();
-// QPainter painter(&img);
-// painter.setPen(Qt::yellow);
-// painter.setBrush(Qt::yellow);
-// QFileInfo info(name);
-// painter.drawText(20,50, info.baseName());
-// cv::Mat frame = cv::Mat(img.height(), img.width(),CV_8UC4, img.bits(), img.bytesPerLine()).clone();
-// cv::Mat resized;
-// cv::resize(frame, resized, cv::Size(width,height));
-// video.write(resized);
-// }
-// }
-// }
-// catch(std::exception& e) {
-// qDebug() << "Exception writing video " << e.what();
-// }
+ if (QMessageBox::No == QMessageBox::question(0,"---------- 3D wave front Video maker -------------","This will create an 3D image of each wave front file selected and save it as an image.\n"
+ " So a video app can turn them into a movie. Select Yes if you want to continue."))
+ {
+ return;
+ }
+ QStringList fileNames = SelectWaveFrontFiles();
+ this->setCursor(Qt::WaitCursor);
+ QProgressDialog pd(" Loading wavefronts in PRogress.", "Cancel", 0, 100);
+ pd.setRange(0, fileNames.size());
+ if (fileNames.length()> 0)
+ pd.show();
+
+ //ask which sets to make (asig and/or wavefronts)
+ bool dowavefront = false;
+ bool doastig = false;
+ astigScatterPlot *astigPlot = NULL;
+ QWidget *astigWindow = NULL;
+ QString waveprefix("f");
+ QString astigprefix("astig");
+ if (QMessageBox::Yes == QMessageBox::question(0,"3D","Make image of 3D model of each wave front?"))
+ {
+ dowavefront = true;
+ bool ok{};
+ QString text = QInputDialog::getText(this, tr("QInputDialog::getText()"),
+ tr("File prefix"), QLineEdit::Normal,
+ waveprefix, &ok);
+ if (ok && !text.isEmpty())
+ waveprefix = text;
+ }
+ if (!dowavefront) {
+ if (QMessageBox::Yes == QMessageBox::question(0,"astig","Make plot of astig for each wave front?"))
+ {
+ doastig = true;
+ bool ok{};
+ QString text = QInputDialog::getText(this, tr("QInputDialog::getText()"),
+ tr("file prefix"), QLineEdit::Normal,
+ astigprefix, &ok);
+ if (ok && !text.isEmpty())
+ astigprefix = text;
+ astigPlot = new astigScatterPlot;
+ QVBoxLayout *layout = new QVBoxLayout();
+ astigWindow = new QWidget();
+ layout->addWidget(astigPlot);
+ astigWindow->setLayout(layout);
+ astigWindow->resize(1000,1000);
+ astigWindow->show();
+
+ }
+ }
+ if (!doastig and !dowavefront)
+ return;
+ int cnt = 0;
+ QSettings set;
+ QString lastPath = set.value("lastPath",".").toString();
+ int memThreshold = set.value("lowMemoryThreshold",300).toInt();
+ QImage img = m_ogl->m_surface->render(1000,1000);
+
+ int width = img.width();
+ int height = img.height();
+
+ try {
+
+ QString dir = QFileDialog::getExistingDirectory(0, "Select directory where images will be saved.", lastPath,
+ QFileDialog::ShowDirsOnly
+ | QFileDialog::DontResolveSymlinks);
+ int framecnt = 0;
+ int astigCnt = 0;
+ if (dir.length() > 0){
+
+
+ foreach (QString name, fileNames){
+
+ QApplication::processEvents();
+
+ if (pd.wasCanceled())
+ break;
+
+
+ pd.setLabelText(name);
+ QApplication::processEvents();
+ wavefront *wf = m_surfaceManager->readWaveFront(name);
-// this->setCursor(Qt::ArrowCursor);
+ m_surfaceManager->makeMask(wf);
+ m_surfaceManager->generateSurfacefromWavefront(wf);
+ m_surfaceManager->computeMetrics(wf);
+ pd.setValue(++cnt);
+
+ m_ogl->m_surface->setSurface(wf);
+ QPointF astig(wf->InputZerns[4], wf->InputZerns[5]);
+ delete wf;
+ QApplication::processEvents();
+ if (dowavefront){
+ QImage img = m_ogl->m_surface->render(1000,1000);
+ QPainter painter(&img);
+ painter.setPen(Qt::yellow);
+ painter.setBrush(Qt::yellow);
+ QFileInfo info(name);
+ painter.drawText(20,50, info.baseName());
+ cv::Mat frame = cv::Mat(img.height(), img.width(),CV_8UC4, img.bits(), img.bytesPerLine()).clone();
+ cv::Mat resized;
+ cv::resize(frame, resized, cv::Size(width,height));
+ // write frame
+ QString filename = dir + "//" + QString("%1%2.jpg").arg(waveprefix).arg(framecnt++,3,10, QChar('0'));
+ img.save ( filename );
+ }
+ if (doastig){
+
+ astigPlot->addValue("", astig);
+
+ // write frame
+ QString filename = dir + "//" + QString("%1%2.jpg").arg(astigprefix).arg(astigCnt++,3,10, QChar('0'));
+ astigWindow->grab().save ( filename );
+
+ }
+ }
+ }
+ if (QMessageBox::Yes == QMessageBox::question(0,"---------- 3D wave front Video maker -------------","Do you have FFMpeg and want it to make a video from these images?"))
+
+ {
+ QString cmd = QString("ffmpeg -framerate 1 -i %1%03d.jpg -c:v libx264 -vf format=yuv420p -y -r 25 %2").arg(dowavefront? waveprefix:astigprefix). \
+ arg(dowavefront? "waveFronts.mp4": "astig.mp4");
+
+ bool ok = false;
+ QString text = QInputDialog::getText(this,
+ "------------------ FFmpeg command to create video from images.----------------",
+ "-------------------- Command to make 2 fps. Copy to command line app. -----------------",
+ QLineEdit::Normal,
+ QString(cmd) ,&ok);
+ if (ok) {
+ QDialog *dialog = new QDialog;
+ dialog->setWindowTitle("ffmpeg output");
+ dialog->resize(1000,1000);
+ QTextEdit *textEdit = new QTextEdit();
+
+ QPushButton *closeButton = new QPushButton("Close");
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(textEdit);
+ layout->addWidget(closeButton);
+
+ dialog->setLayout(layout);
+
+ QObject::connect(closeButton, &QPushButton::clicked, dialog, &QDialog::close);
+
+ dialog->show();
+
+ cmd = textEdit->toPlainText();
+ qDebug() << "plain text"<< text;
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ QProcess *proc = new QProcess;
+ connect(proc, QOverload::of(&QProcess::finished),
+ [=](int exitCode, QProcess::ExitStatus exitStatus){ qDebug() << "what" << exitStatus; });
+
+ proc->setProcessChannelMode(QProcess::MergedChannels);
+ proc->setWorkingDirectory(dir);
+ QStringList args = text.split(" ");
+ qDebug() << "args" << args.mid(1);
+ proc->start("ffmpeg",args.mid(1));
+
+
+ while (!proc->waitForFinished(200)){
+ QString q = proc->readAll();
+ if (q != "")
+ textEdit->append(q);
+ QApplication::processEvents();
+ }
+
+ qDebug() << "done" ;
+
+ proc->waitForFinished();
+ QString out = proc->readAll() ;
+ QApplication::restoreOverrideCursor();
+
+ QString fn = dir + "/" + args[args.length()-1];
+ QDesktopServices::openUrl(fn);
+
+ }
+ }
+
+ }
+ catch(std::exception& e) {
+
+ qDebug() << "Exception writing video " << e.what();
+ }
+ if (astigWindow != NULL)
+ delete astigWindow;
+ this->setCursor(Qt::ArrowCursor);
+ QApplication::restoreOverrideCursor();
}
arma::mat zapm(const arma::vec& rho, const arma::vec& theta,
const double& eps, const int& maxorder=12) ;
@@ -1840,3 +1989,93 @@ void MainWindow::on_useAnnulust_clicked()
m_igramArea->useAnnulusforCenterOutine();
}
+
+
+
+void MainWindow::on_actionHot_Keys_triggered()
+{
+ QString msgtext =
+ QString("hot keys (interferogram or results tab>
")+
+ ""
+ "- I, ctrl-o
"
+ "- Import interferogram
"
+ "(see preferences igram settings for path setup)"
+ "
"
+ "- L
"
+ "Open interferogram (manually select interferogram from directory)"
+ ""
+ "outline hot keys
"
+ ""
+ "- h
- toggle outline (hide) on or off
"
+ "- space bar
- toggle edge zoom on or off
"
+ "- f
- zoom to full image
"
+ "- scroll wheel
- zoom image
"
+ "- ctrl scroll wheel
- increase/decrease diameter of outline.
"
+ "- +/-
- expand or contract outline.
"
+ "- arrow keys
- move outline.
"
+ ""
+
+ "";
+
+ QMessageBox msg;
+ msg.setIconPixmap(QPixmap(":/error.svg"));
+ msg.setText(msgtext);
+ msg.setStandardButtons(QMessageBox::Ok);
+ msg.setDefaultButton(QMessageBox::Ok);
+ QSpacerItem* horizontalSpacer = new QSpacerItem(800, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
+ QGridLayout* layout = (QGridLayout*)msg.layout();
+ layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
+ msg.exec();
+}
+
+
+void MainWindow::on_actionLoad_wave_fronts_from_multiple_directories_triggered()
+{
+ QSettings set;
+ QString lastPath = set.value("lastPath",".").toString();
+ QFileDialog dialog;
+ QStringList files;
+ dialog.setFileMode(QFileDialog::Directory);
+ dialog.setOption(QFileDialog::DontUseNativeDialog, true);
+ dialog.setDirectory(lastPath);
+
+ QListView *listView = dialog.findChild("listView");
+ if (listView) {
+ listView->setSelectionMode(QAbstractItemView::MultiSelection);
+ }
+
+ QTreeView *treeView = dialog.findChild();
+ if (treeView) {
+ treeView->setSelectionMode(QAbstractItemView::MultiSelection);
+ }
+
+ QStringList selectedDirectories;
+ if (dialog.exec()) {
+ selectedDirectories = dialog.selectedFiles();
+ foreach (QString fn,selectedDirectories){
+ QFileDialog dialog(this, "load wave front file", fn, tr("wft(*.wft)"));
+ dialog.setFileMode(QFileDialog::ExistingFiles);
+ dialog.setNameFilter(tr("wft (*.wft)"));
+
+ if (dialog.exec()) {
+ QStringList fileNames = dialog.selectedFiles();
+ if (fileNames.size() > 0){
+ files << dialog.selectedFiles();
+ }
+ }
+ }
+ openWaveFrontonInit(files);
+ }
+
+}
+
+#include "astigpolargraph.h"
+void MainWindow::on_actionastig_in_polar_triggered()
+{
+ surfaceAnalysisTools *saTools = surfaceAnalysisTools::get_Instance();
+ QList list = saTools->SelectedWaveFronts();
+ astigPolargraph * graph = new astigPolargraph( list);
+ graph->resize(2000,1000);
+ graph->exec();
+}
+
diff --git a/mainwindow.h b/mainwindow.h
index ff293490..f9a5db32 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -128,6 +128,7 @@ private slots:
void on_saveOutline_clicked();
+ void importIgram();
//void on_actionSimulated_interferogram_triggered();
void on_actionPrevious_Wave_front_triggered();
@@ -136,8 +137,6 @@ private slots:
void on_actionDelete_wave_front_triggered();
- void on_actionWrite_WaveFront_triggered();
-
void on_actionSave_Wavefront_triggered();
void on_SelectOutSideOutline_clicked(bool checked);
@@ -268,6 +267,12 @@ private slots:
void on_useAnnulust_clicked();
+ void on_actionHot_Keys_triggered();
+
+ void on_actionLoad_wave_fronts_from_multiple_directories_triggered();
+
+ void on_actionastig_in_polar_triggered();
+
private:
Ui::MainWindow *ui;
diff --git a/mainwindow.ui b/mainwindow.ui
index 7e781dc0..3f1218c0 100644
--- a/mainwindow.ui
+++ b/mainwindow.ui
@@ -68,6 +68,7 @@
+
@@ -93,6 +94,7 @@
+
diff --git a/mirrordlg.cpp b/mirrordlg.cpp
index 8d6d8b63..192d42af 100644
--- a/mirrordlg.cpp
+++ b/mirrordlg.cpp
@@ -190,7 +190,7 @@ void mirrorDlg:: on_saveBtn_clicked()
}
QString extensionTypes(tr((m_useAnnular)? "config file (*.json)" : "config file (*.ini *.json)"));
QString fileName = QFileDialog::getSaveFileName(0,
- tr("Save stats file"), path,
+ tr("Save config file"), path,
extensionTypes);
if (fileName.isEmpty())
return;
diff --git a/oglview.cpp b/oglview.cpp
index aa5eaaf3..a894978f 100644
--- a/oglview.cpp
+++ b/oglview.cpp
@@ -177,7 +177,7 @@ void OGLView::showSelected() // show all selected wavefronts as 3D plots
QVector m_wavefronts =SurfaceManager::get_instance()->m_wavefronts;
surfaceAnalysisTools *saTools = surfaceAnalysisTools::get_Instance();
QList list = saTools->SelectedWaveFronts();
- int cols = 4;
+ int cols = 3;
if (list.size() %3 == 0) cols = 3;
int rows = ceil((double)list.size()/cols);
int columns = cols;//min(m_wavefronts.size(),int(ceil((double)m_wavefronts.size()/rows)));
diff --git a/outlinedialog.cpp b/outlinedialog.cpp
index a5a75356..ba29f37b 100644
--- a/outlinedialog.cpp
+++ b/outlinedialog.cpp
@@ -44,7 +44,7 @@ outlineDialog::outlineDialog(double x, double y, double rad, QWidget *parent) :
hideSearchcontrole(true);
QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_Down), this);
QObject::connect(shortcut, SIGNAL(activated()), this, SLOT(shiftDown()));
- shortcut = new QShortcut(QKeySequence("d"), this);
+ shortcut = new QShortcut(QKeySequence(Qt::Key_Up), this);
QObject::connect(shortcut, SIGNAL(activated()), this, SLOT(shiftUp()));
shortcut = new QShortcut(QKeySequence(Qt::Key_Left), this);
QObject::connect(shortcut, SIGNAL(activated()), this, SLOT(shiftLeft()));
diff --git a/percentCorrectionSurface.h b/percentCorrectionSurface.h
new file mode 100644
index 00000000..6b62d489
--- /dev/null
+++ b/percentCorrectionSurface.h
@@ -0,0 +1,16 @@
+#ifndef PERCENTCORRECTIONSURFACE_H
+#include
+#define PERCENTCORRECTIONSURFACE_H
+class surfaceData {
+ public:
+
+ double igramlambda;
+ QColor penColor;
+ // set of zernike values at each zone (rho)
+ std::vector zernvalues;
+ QString m_name;
+
+ surfaceData( double igramlambda, QColor pen, std::vector zernvalues, QString name): igramlambda(igramlambda),
+ penColor(pen), zernvalues(zernvalues){ m_name = name;};
+} ;
+#endif // PERCENTCORRECTIONSURFACE_H
diff --git a/percentcorrectiondlg.cpp b/percentcorrectiondlg.cpp
new file mode 100644
index 00000000..6cfce724
--- /dev/null
+++ b/percentcorrectiondlg.cpp
@@ -0,0 +1,756 @@
+#include "percentcorrectiondlg.h"
+#include "ui_percentcorrectiondlg.h"
+#include "qwt_plot_grid.h"
+#include "qwt_scale_div.h"
+#include "qwt_plot_barchart.h"
+#include
+#include "qwt_plot_marker.h"
+#include
+#include "surfaceanalysistools.h"
+#include "mirrordlg.h"
+#include
+#include
+#include
+#include "surfacemanager.h"
+#include
+#include
+#include
+#include
+#include "zernikeprocess.h"
+#include
+
+
+percentCorrectionDlg::percentCorrectionDlg( QWidget *parent) :
+ QDialog(parent),m_showZones(false),
+ ui(new Ui::percentCorrectionDlg)
+{
+ ui->setupUi(this);
+
+ resize(1000,800);
+
+
+ mirrorDlg &md = *mirrorDlg::get_Instance();
+ m_radius = md.m_clearAperature/2.;
+ QSettings set;
+ ui->minvalue->blockSignals(true);
+ ui->maxvalue->blockSignals(true);
+ ui->minvalue->setValue(set.value("percent_correction_min",-10).toDouble());
+ ui->maxvalue->setValue(set.value("percent_correction_max", 120).toDouble());
+ ui->minvalue->blockSignals(false);
+ ui->maxvalue->blockSignals(false);
+ ui->maxOrder->blockSignals(true);
+ m_maxOrder = set.value("percentMaxOrder",18).toUInt();
+ ui->maxOrder->setValue(m_maxOrder);
+ int mmax = m_maxOrder/2;
+ int nzerns = (mmax+1)*(mmax+1);
+ ui->noOfTerms->setText(QString::number(nzerns));
+ ui->maxOrder->blockSignals(false);
+ ui->percentTable->setStyleSheet("background-color: lightgray;");
+ QList sizes;
+ sizes << 500 << 100;
+ ui->splitter->setSizes(sizes);
+ m_number_of_zones = set.value("percent number of zones", 5).toInt();
+
+ ui->numberOfZones->blockSignals(true);
+ ui->numberOfZones->setValue(m_number_of_zones);
+ ui->numberOfZones->blockSignals(false);
+ if (set.contains("percent_Correction_dialogGeometry")) {
+ setGeometry(set.value("percent_Correction_dialogGeometry").toRect());
+ }
+
+ makeZones();
+
+
+}
+
+
+
+double g_laserLambda = 550.; // a global so a none member function can access it.
+
+void percentCorrectionDlg::saveSettings(){
+ QJsonObject myJsonObject;
+ myJsonObject["ROC"] = m_roc;
+ myJsonObject["mirror radius"] = m_radius;
+
+ QJsonArray jzones;
+ for (const auto &item : zoneCenter) {
+ jzones.append((double)item/m_radius); // zone centers are saved as a percentage.
+ }
+ myJsonObject["zones"] = jzones;
+ QSettings set;
+ QJsonDocument jsonDoc(myJsonObject);
+ set.setValue("correctionZones", jsonDoc.toJson(QJsonDocument::Compact));
+ set.setValue("percentMaxOrder",m_maxOrder);
+}
+
+
+
+/****************************************************
+ * zone data. If none to begin with use 5 zones.
+ * if last zones then use those.
+ * allow loading and saveing of zones
+ * allways save current accpeted zones in settings probalby in json format.
+*/
+QList generateZoneCenters(double radius, int number_of_zones){
+ double exc_pct = 100. * pow(16.75,2.)/pow(radius,2.);
+ QList zoneCenters;
+ QList zoneedge;
+ // create the zones and the zone centers
+ for (int i = 0; i < number_of_zones+1; ++i){
+ zoneedge << radius * sqrt((1. -.01 * exc_pct) * i/number_of_zones + .01 * exc_pct);
+ }
+
+ double lastzone = 0.;
+ for (int i = 0; i < number_of_zones; ++i){
+ double zoneCenter = (lastzone + zoneedge[i])/2.;
+ lastzone = zoneedge[i];
+ zoneCenters << QString::number(zoneCenter,'f',0).toDouble();
+ }
+ return zoneCenters;
+}
+void percentCorrectionDlg::updateZoneTable(){
+
+ QStringList vertLabels;
+
+ QStringList hLabels;
+
+ ui->percentTable->clear();
+ ui->percentTable->setColumnCount(zoneCenter.size());
+ ui->percentTable->setRowCount(2);
+ ui->percentTable->blockSignals(true);
+
+
+ for (int i = 0; i < zoneCenter.size(); ++i) {
+
+ QTableWidgetItem *item = new QTableWidgetItem(QString("%1mm").arg(zoneCenter[i],0,'f',0));
+ item->setTextAlignment(Qt::AlignCenter);
+ ui->percentTable->setItem(0, i, item);
+ item->setTextAlignment(Qt::AlignCenter);
+ vertLabels<< QString().number(i);
+ hLabels << QString().number(i+1);
+ }
+
+
+ ui->percentTable->setHorizontalHeaderLabels(hLabels);
+
+ ui->percentTable->setColumnCount(zoneCenter.size());
+ ui->percentTable->blockSignals(false);
+}
+QJsonDocument percentCorrectionDlg::loadZonesFromJson(QString str){
+ QJsonParseError jsonError;
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(str.toUtf8(), &jsonError);
+ QJsonObject jsonData=jsonDoc.object();
+ QJsonArray zones = jsonData["zones"].toArray();
+
+
+ zoneCenter.clear();
+ ui->percentTable->clearContents();
+ ui->percentTable->setColumnCount(zones.size());
+
+ for (int i = 0; i < zones.size(); ++i) {
+ double d = zones[i].toDouble()* m_radius;
+
+ zoneCenter.append(QString::number(d,'f',0).toDouble() );
+ }
+ return jsonDoc;
+}
+
+arma::mat percentCorrectionDlg::makeZoneZerns(QList centers){
+ std::vector rhovec, thetavec;
+
+ // creaate rowvec or rho and theta. Theta will only be 0.
+ for (int i = 0; i < centers.length(); ++i){
+
+ double rho = centers[i];
+ rhovec.push_back(rho);
+ thetavec.push_back(0.);
+ }
+
+ arma::rowvec rhov(rhovec), thetav(thetavec);
+
+ zernikeProcess zp;
+ zp.setMaxOrder(m_maxOrder);
+
+ arma::mat theZs = zp.zpmC(rhov, thetav, m_maxOrder);
+ return theZs;
+}
+
+void percentCorrectionDlg::makeZones(){
+
+ QSettings set;
+ if (!set.contains("correctionZones")){
+ generateZoneCenters(m_radius, m_number_of_zones);
+
+ saveSettings();
+ }
+ else { // read zones from settings
+ // if mirror is different now than last then make the same number of zones but with new radius values
+ QString jsonString = set.value("correctionZones").toString();
+
+ QJsonDocument doc = loadZonesFromJson(jsonString);
+ // if number of zones has changed then generate new zones.
+ if ((zoneCenter.size() != m_number_of_zones) || (m_radius != doc.object()["mirror radius"].toDouble())){
+ zoneCenter = generateZoneCenters(m_radius, m_number_of_zones);
+ saveSettings();
+ }
+
+ }
+ updateZoneTable();
+ zoneZerns = makeZoneZerns(zoneCenter);
+}
+
+// the profile version needs the null removed and is in output lambda (usually 550);
+// zernike based does not need the null removed but needs to use laser wave length
+double percentCorrectionDlg::getZernSurface( double RoC, double MirrorRad, std::vector Zernikes, double x, double null = 0.,
+ bool useavg = false){
+
+ double num1 = x / MirrorRad;
+ arma::rowvec rhov(1), thetav(1);
+ rhov[0] = x/m_radius; thetav[0] = 0.;
+ zernikeProcess zp;
+ zp.setMaxOrder(m_maxOrder);
+
+ arma::mat theZs = zp.zpmC(rhov, thetav, m_maxOrder);
+
+ double val = 0;
+ if (useavg) {
+
+ // find x location in profile
+ val = m_avg[m_avg.length()-1].y();
+ for (int i = 0; i < m_avg.length(); ++i){
+ if (m_avg[i].x() == x){
+ val = m_avg[i].y();
+ break;
+ }
+ if (m_avg[i].x() > x){
+ double dx = m_avg[i].x() - m_avg[i-1].x();
+ double dy = m_avg[i].y() - m_avg[i-1].y();
+ val = m_avg[i-1].y() + (x - m_avg[i-1].x())*(dy/dx);
+ break;
+
+ }
+
+ }
+ val += (null) * theZs(0,8);
+ double spherey = RoC - sqrt(pow(RoC, 2.0) - pow(x, 2.0));
+ double zerny = val * m_outputLambda * .5E-6;
+ double surf = spherey + zerny;
+ return surf;
+ }
+ else {
+
+ // for each spherical term
+ int z = 8;
+ for(unsigned int j = 6; z < theZs.n_cols; j+=2){
+
+ val += Zernikes[z] * theZs(0,z);
+ z = j * j /4 + j;
+ }
+ double spherey = RoC - sqrt(pow(RoC, 2.0) - pow(x, 2.0));
+ double zerny = val * m_lambda_nm * .5E-6;
+ double surf = spherey + zerny;
+ return surf;
+ }
+
+
+
+}
+
+// profile from profile plot with null removed
+void percentCorrectionDlg::setProfile(QPolygonF profile){
+ m_avg = profile;
+
+}
+// will use zernike values to compute two surface points x+- .01x away from x
+// then compute normal slope from that.
+double percentCorrectionDlg::getnormalSlope(double RoC, double radius, std::vector Zernikes, double x, double null = 0, bool useAvg = false){
+
+ double num1 = x / 100.0;
+ double surface1 = getZernSurface(RoC, radius, Zernikes, x - num1, null,useAvg); // problem with zonendx (the delta is not same as zonendx)
+ double surface2 = getZernSurface(RoC, radius, Zernikes, x + num1, null,useAvg);
+ double slope = (surface2 - surface1)/ (2 * num1);
+ slope = -1.0 / slope;
+
+ return slope;
+}
+// b == knife y value
+// y = mx + b
+// b = y - mx
+
+double percentCorrectionDlg::GetActualKE(double RoC, double MirrorRad, std::vector Zernikes, double x, double null, bool use_avg)
+{
+
+ double slope = getnormalSlope(RoC, MirrorRad, Zernikes, x, null, use_avg);
+ double surface = getZernSurface(RoC, MirrorRad, Zernikes, x, null, use_avg);
+
+ double actualKe = surface - x * slope - RoC;
+
+ return actualKe;
+}
+// 5.3 = x/slope + 5.3 - roc x/slope = roc slope = x/roc
+double getIdealKE(double RoC, double Z_Radius)
+{
+ return pow(Z_Radius, 2.0) / (2.0 * RoC);
+}
+QPolygonF percentCorrectionDlg::makePercentages(surfaceData *surf){
+
+ auto knifeDeltas = [](QPolygonF &knives){
+ double last = knives[0].y();
+ QPolygonF deltas;
+ for (int i = 1; i < knives.length(); ++i ){
+ deltas << QPointF( knives[i].x(),knives[i].y() - last);
+ last = knives[i].y();
+ }
+ return deltas;
+
+ };
+ auto getZoneCorrection = [] (QPolygonF &ideal, QPolygonF test){
+ QPolygonF percent;
+ for (int i = 0; i < ideal.length(); ++i){
+ percent << QPointF( test[i].x(), 100. * test[i].y()/ideal[i].y());
+ }
+ return percent;
+ };
+
+ QPolygonF percentage;
+ // start at the mirrors middle
+
+ QVector IdealzoneKnife;
+ QVector ActualZoneKnife;
+ QVector idealDelta;
+ QVector actualDelta;
+ IdealzoneKnife << 0.;
+ ActualZoneKnife << 0.0;
+
+ mirrorDlg *md = mirrorDlg::get_Instance();
+ double nullval = md->z8 * md->cc; // null value was computed at the igram wavevlength
+ nullval *= m_lambda_nm/m_outputLambda; // only data from the profile needs the null but it's data is at the output wavelength;
+ // process each zone center
+
+ QPolygonF idealknives;
+ QPolygonF actualknives;
+ QPolygonF zernKnives;
+ QPolygonF zernSurf;
+
+ double idealoffset = 0.;
+ double zernOffset = 0.;
+
+ for (int zone = 0; zone < zoneCenter.length(); ++zone){
+ double x = zoneCenter[zone];
+
+ //idealSurface << QPointF(x, normIdealSlope);
+ double idealknife = getIdealKE(m_roc, x);
+
+ // when using average profile as the profile we need to remove the artificial
+ // null from the profile thus the nullval being passed.
+ double zernKnife = GetActualKE(m_roc, m_radius, surf->zernvalues, x, nullval ,false);
+
+ if (zone == 0){
+ idealoffset = idealknife;
+ zernOffset = zernKnife;
+ }
+ idealknives << QPointF(x,idealknife - idealoffset);
+ zernKnives << QPointF(x,zernKnife - zernOffset);
+
+
+ // plot knives
+
+ }
+
+ QPolygonF idealDeltas = knifeDeltas(idealknives);
+ QPolygonF zernDeltas = knifeDeltas(zernKnives);
+
+ QPolygonF correction = getZoneCorrection(idealDeltas, zernDeltas);
+
+ return correction;
+}
+
+
+void percentCorrectionDlg::plotProfile(){
+
+ mirrorDlg *md = mirrorDlg::get_Instance();
+ double nullval = md->z8 * md->cc;
+ for (int i = 0; i < surfs.length(); ++ i) {
+
+ QwtPlotCurve *Curve = new QwtPlotCurve();
+ QPolygonF profile;
+ for(double r = -m_radius; r <= m_radius; r += 1. ){
+ double y = getZernSurface(m_roc, m_radius, surfs[i]->zernvalues, fabs(r), nullval, false);
+
+ double sphery = m_roc - sqrt(pow(m_roc, 2.0) - pow(r, 2.0));
+ y -= sphery;
+ y /= m_lambda_nm * .5E-6;
+ profile << QPointF(r, y);
+ }
+
+ Curve->setSamples(profile);
+ Curve->attach(ui->plot);
+ Curve->setPen(Qt::green,5);
+ Curve->attach(ui->plot);
+ }
+ QPolygonF profile2;
+ // now plot the m_avg surface
+ int i = 0;
+ for(double r = 0; r < m_avg.length(); r += 1. ){
+
+ // qDebug() << "r" << r << m_avg[i];
+ double y = m_avg[r].y();//getZernSurface(m_roc, m_radius, surfs[i]->zernvalues, fabs(r), true);
+
+ double sphery = m_roc - sqrt(pow(m_roc, 2.0) - pow(r, 2.0));
+ //y -= sphery;
+ //y /= m_lambda_nm * .5E-6;
+ profile2 << QPointF(m_avg[r].x(), y);
+
+ }
+ QwtPlotCurve *Curve2 = new QwtPlotCurve();
+ Curve2->setSamples(profile2);
+ Curve2->attach(ui->plot);
+ Curve2->setPen(Qt::blue,5);
+ Curve2->attach(ui->plot);
+
+ ui->plot->setAxisScale(QwtPlot::xBottom, -m_radius, m_radius);
+ ui->plot->setAxisAutoScale(QwtPlot::yLeft);
+
+ ui->plot->setAxisTitle( ui->plot->yLeft, "Error in waves at 550 nm" );
+ ui->plot->replot();
+}
+void percentCorrectionDlg::plot(){
+ QPolygonF expectedslope;
+ QPolygonF actualslope;
+ QPolygonF percentplot;
+ QPolygonF franzPrecentPlot;
+ QPolygonF actualSurface;
+ QPolygonF idealSurface;
+ QPolygonF correction;
+
+ QPolygonF data;
+
+ std::vector zernikes;
+
+ // first get the zernike poly spherical terms at each zone center.
+ for (int c = 0; c < zoneCenter.length(); ++c){
+
+ }
+
+ ui->plot->detachItems(QwtPlotItem::Rtti_PlotItem);
+
+ QwtPlotGrid *grid = new QwtPlotGrid();
+ grid->setZ(1);
+
+ grid->enableXMin(true);
+ grid->enableYMin(true);
+
+ grid->setPen( Qt::gray, 0, Qt::DotLine );
+ grid->setMajorPen( Qt::blue, 2.0,Qt::DotLine);
+ grid->setMinorPen(Qt::black, 1.0, Qt::DotLine);
+ grid->attach( ui->plot);
+
+
+// if (!ui->correction->isChecked()){
+// plotProfile();
+// return;
+// }
+
+ ui->percentTable->blockSignals(true);
+ ui->percentTable->setRowCount(surfs.length() + 1);
+ QTableWidgetItem *item = new QTableWidgetItem("Zone Center");
+ ui->percentTable->setVerticalHeaderItem(0, item);
+ // for each surface draw the percent plot
+ for (int i = 0; i < surfs.length(); ++ i) {
+ // make percentages
+ QPolygonF percent = makePercentages( surfs[i]);
+
+ // Create 3D bar data
+ QVector row;
+
+ for(int j = 0; j < percent.length(); ++j){
+ QTableWidgetItem *item = new QTableWidgetItem(QString::number(percent[j].y(),'f',0) + "%");
+ item->setTextAlignment(Qt::AlignCenter);
+ item->setFlags(item->flags() & ~Qt::ItemIsEditable);
+ ui->percentTable->setItem(i+1,j+1,item);
+
+ row << percent[j].y();
+ }
+ QTableWidgetItem *item = new QTableWidgetItem(surfs[i]->m_name);
+ item->setForeground(surfs[i]->penColor);
+ item->setFlags(item->flags() & ~Qt::ItemIsEditable);
+
+ ui->percentTable->setVerticalHeaderItem(i+1, item);
+ m_seriesName << surfs[i]->m_name;
+
+
+ QPolygonF bars;
+
+ if (surfs.length() < 2) {
+ // draw zone rectangles
+
+ double width;
+ for(int i = 0; i < percent.length(); ++i){
+
+ double y = percent[i].y();
+
+ if (i < percent.length()-1)
+ width= .80 * (percent[i+1].x() - percent[i].x()) ;
+
+ QwtPlotShapeItem *rectangleItem = new QwtPlotShapeItem();
+
+ rectangleItem->setRect(QRectF(percent[i].x() - width/2. ,0,width,y));
+
+ QPen pen(Qt::black);
+ pen.setWidth(3);
+ rectangleItem->setPen(pen);
+ rectangleItem->setBrush(QBrush(Qt::lightGray));
+ rectangleItem->attach(ui->plot);
+ rectangleItem->setZ(0);
+ QwtPlotMarker *label = new QwtPlotMarker();
+ label->setLineStyle(QwtPlotMarker::NoLine);
+ label->setLabel(QString("%1\%").arg(y, 0, 'f',1)) ;
+ label->setValue(percent[i].x(), y-10);
+ label->attach(ui->plot);
+ }
+
+ }
+
+
+
+ if (surfs.length() == 1) {
+ // draw markers
+ for (int i = 0; i < zoneCenter.size(); ++i) {
+ double center= zoneCenter[i];
+ QwtPlotMarker *marker = new QwtPlotMarker();
+ marker->setLineStyle(QwtPlotMarker::VLine); // Set the line style to vertical
+ marker->setLinePen(Qt::red,2,Qt::DashLine);
+ marker->setLabelAlignment(Qt::AlignLeft);
+ marker->setXValue(center);
+ marker->attach(ui->plot);
+
+ QwtPlotMarker *label = new QwtPlotMarker();
+ label->setLineStyle(QwtPlotMarker::NoLine);
+ label->setLabel(QString("%1\n%2\%").arg(center, 0, 'f',1).arg(100. * center/m_radius,0,'f',1 )) ;
+ label->setLabelAlignment(Qt::AlignCenter);
+ label->setXValue(center);
+ label->setYValue(-23);
+ label->attach(ui->plot);
+
+ // draw zone number
+ QwtPlotMarker *marker2 = new QwtPlotMarker();
+ marker2->setLineStyle(QwtPlotMarker::NoLine);
+ marker2->setLabel(QString().number(i+1));
+ marker2->setLabelAlignment(Qt::AlignCenter);
+ marker2->setYValue(-5);
+ marker2->setXValue(center);
+ marker2->attach(ui->plot);
+ }
+ }
+
+
+
+ QwtPlotCurve *slopeCurve3 = new QwtPlotCurve();
+
+ slopeCurve3->setSamples(percent);
+ slopeCurve3->attach(ui->plot);
+ slopeCurve3->setPen(surfs[i]->penColor,5);
+
+ ui->plot->setAxisTitle( ui->plot->yLeft, "Percent correction" );
+ ui->plot->setAxisScale(ui->plot->yRight, -10, 20, 1);
+ ui->plot->setAxisTitle( ui->plot->xBottom, "Mirror Radius mm" );
+ slopeCurve3->setZ(1);
+ ui->plot->setAxisScale(QwtPlot::yLeft, ui->minvalue->value(), ui->maxvalue->value());
+ ui->plot->setAxisScale(QwtPlot::xBottom, 0, m_radius);
+ }
+ ui->percentTable->blockSignals(false);
+ // Add the series to the graph
+ ui->plot->replot();
+}
+
+bool compare(QVector< surfaceData *> data1, QVector< surfaceData *> data2){
+ if (data1.length() != data2.length()){
+ return false;
+ }
+ for (int ndx = 0; ndx < data1.length(); ++ ndx){
+ if (data1[ndx]->igramlambda != data2[ndx]->igramlambda ||
+ data1[ndx]->m_name != data2[ndx]->m_name ||
+ data1[ndx]->penColor != data2[ndx]->penColor ||
+ data1[ndx]->zernvalues != data2[ndx]->zernvalues)
+
+ return false;
+
+ }
+ return true;
+}
+
+void percentCorrectionDlg::setData( QVector< surfaceData *> data) {
+
+ bool different = !compare(data,surfs);
+ qDebug() << "true if different" << different;
+ mirrorDlg &md = *mirrorDlg::get_Instance();
+ m_roc = md.roc;
+ m_lambda_nm = md.lambda;
+ QSettings set;
+ m_outputLambda = set.value("outputLambda").toDouble();
+
+ m_radius = md.m_clearAperature/2.;
+ surfs = data;
+ ui->percentTable->setRowCount(data.length());
+
+ QStringList labels;
+ labels << "Zone\ncenter";
+ foreach(auto t, data){
+ labels << t->m_name;
+
+ }
+ ui->percentTable->setVerticalHeaderLabels(labels);
+ ui->percentTable->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
+
+ makeZones();
+
+ plot();
+ //if (different)
+ //emit make_percent_correction(m_maxOrder);
+}
+
+percentCorrectionDlg::~percentCorrectionDlg()
+{
+ delete ui;
+}
+
+
+void percentCorrectionDlg::on_minvalue_valueChanged(double arg1)
+{
+ QSettings set;
+ set.setValue("percent_correction_min",arg1);
+ plot();
+}
+
+
+void percentCorrectionDlg::on_maxvalue_valueChanged(double arg1)
+{
+ QSettings set;
+ set.setValue("percent_correction_max", arg1);
+ plot();
+}
+
+void percentCorrectionDlg::closeEvent(QCloseEvent *event) {
+ QSettings set;
+ set.setValue("percent_Correction_dialogGeometry", geometry());
+ QDialog::closeEvent(event);
+}
+void percentCorrectionDlg::moveEvent(QMoveEvent *event) {
+ QSettings set;
+ set.setValue("percent_Correction_dialogGeometry", geometry());
+ QDialog::moveEvent(event);
+}
+
+void percentCorrectionDlg::on_numberOfZones_valueChanged(int arg1)
+{
+ m_number_of_zones = arg1;
+ QSettings set;
+ set.setValue("percent number of zones", arg1);
+
+ makeZones();
+ plot();
+
+}
+
+
+void percentCorrectionDlg::on_help_clicked()
+{
+ QToolTip::showText(ui->help->mapToGlobal(QPoint()),ui->help->toolTip(),ui->help);
+}
+
+
+
+void percentCorrectionDlg::on_loadZones_clicked()
+{
+ QSettings set;
+ QString path = set.value("projectPath").toString();
+ QString extensionTypes(tr( "zone file (*.zones)"));
+ QString fileName = QFileDialog::getOpenFileName(0,
+ tr("Read zone file"), path,
+ extensionTypes);
+ if (fileName.isEmpty())
+ return;
+ QFile file(fileName);
+
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qDebug() << "Failed to open file";
+ return;
+ }
+
+ QTextStream in(&file);
+ QString line = in.readLine();
+
+ file.close();
+
+ QJsonDocument doc = loadZonesFromJson(line);
+ QJsonObject jsonData=doc.object();
+ if (jsonData.contains("aborted"))
+ return;
+ QJsonArray zones = jsonData["zones"].toArray();
+ m_number_of_zones = zones.size();
+ ui->numberOfZones->blockSignals(true);
+ ui->numberOfZones->setValue(m_number_of_zones);
+ ui->numberOfZones->blockSignals(false);
+ saveSettings();
+ plot();
+
+}
+
+
+void percentCorrectionDlg::on_saveZones_clicked()
+{
+ QSettings set;
+ QString path = set.value("projectPath").toString();
+ QString extensionTypes(tr( "zone file (*.zones)"));
+ QString fileName = QFileDialog::getSaveFileName(0,
+ tr("Save zone file"), path,
+ extensionTypes);
+ if (fileName.isEmpty())
+ return;
+ if (QFileInfo(fileName).suffix().isEmpty()) { fileName.append(".zones"); }
+ QString jsonString = set.value("correctionZones").toString();
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qDebug() << " failed to read zones file.";
+ }
+
+ QTextStream out(&file);
+ out << jsonString;
+
+ file.close();
+ set.setValue("projectPath", QFileInfo(fileName).absolutePath());
+}
+
+
+
+
+void percentCorrectionDlg::on_Generate_clicked()
+{
+ emit make_percent_correction();
+}
+
+
+void percentCorrectionDlg::on_maxOrder_valueChanged(int arg1)
+{
+ m_maxOrder = arg1;
+
+ int mmax = arg1/2;
+ int ncol = (mmax+1)*(mmax+1);
+ ui->noOfTerms->setText(QString::number(ncol));
+ saveSettings();
+}
+
+
+void percentCorrectionDlg::on_percentTable_itemChanged(QTableWidgetItem *item)
+{
+
+ zoneCenter[item->column()] = item->text().toDouble();
+
+ saveSettings();
+ plot();
+}
+
+
+
+
+
diff --git a/percentcorrectiondlg.h b/percentcorrectiondlg.h
new file mode 100644
index 00000000..7f65a3d7
--- /dev/null
+++ b/percentcorrectiondlg.h
@@ -0,0 +1,112 @@
+#ifndef PERCENTCORRECTIONDLG_H
+#define PERCENTCORRECTIONDLG_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "graphmodifier.h"
+#include "percentCorrectionSurface.h"
+using namespace QtDataVisualization;
+
+namespace Ui {
+class percentCorrectionDlg;
+}
+
+
+class percentCorrectionDlg : public QDialog
+{
+ Q_OBJECT
+ int m_number_of_zones = 5;
+ int m_size;
+ double m_radius;
+ double m_z8;
+ double m_desiredZ8;
+ double m_lambda_nm;
+ double m_outputLambda;
+ bool m_showZones;
+ double m_roc;
+ double m_roc_offset = 0.;
+ arma::mat zoneZerns;
+ QList zoneCenter;
+ QList zoneedge;
+ QList > m_barData;
+ QStringList m_seriesName;
+
+ QPolygonF m_avg; // from profile plot
+ int m_currentprofileIndex = 0;
+ int m_currentSelectedZone = -1;
+
+ QVector surfs;
+ QPolygonF makePercentages(surfaceData *);
+
+ double getnormalSlope(double RoC, double radius, std::vector Zernikes, double x, double null, bool use_avg);
+ double getZernSurface( double RoC, double MirrorRad, std::vector Zernikes, double x,
+ double null, bool useavg);
+ double GetActualKE(double RoC, double MirrorRad, std::vector Zernikes, double x);
+ void make_3DBarControls(QWidget *widget, QVBoxLayout *vlayout);
+ Q3DBars *m_barGraph;
+ GraphModifier *modifier;
+ QBar3DSeries *m_series;
+ QBarDataProxy *m_proxy;
+public:
+ int m_maxOrder = 12;
+
+signals:
+ void percent_plot_changed();
+ void make_percent_correction();
+protected:
+ void closeEvent(QCloseEvent *event);
+ void moveEvent(QMoveEvent *event);
+public:
+ explicit percentCorrectionDlg( QWidget *parent = nullptr);
+ ~percentCorrectionDlg();
+ std::vector m_zerns;
+ void setData(QVector< surfaceData *> );
+ void setProfile(QPolygonF profile);
+ void plot();
+ void plotProfile();
+ void plotSlope();
+ void updateZoneTable();
+ QJsonDocument loadZonesFromJson(QString str);
+ double GetActualKE(double RoC, double MirrorRad, std::vector Zernikes, double x, double nulll, bool use_avg);
+
+private slots:
+ void on_percentTable_itemChanged(QTableWidgetItem *item);
+
+private slots:
+
+ void on_minvalue_valueChanged(double arg1);
+
+ void on_maxvalue_valueChanged(double arg1);
+
+ void on_numberOfZones_valueChanged(int arg1);
+
+ void on_help_clicked();
+
+ void on_loadZones_clicked();
+
+ void on_saveZones_clicked();
+
+ void on_Generate_clicked();
+
+ void on_maxOrder_valueChanged(int arg1);
+
+ arma::mat makeZoneZerns(QList centers);
+
+
+private:
+ Ui::percentCorrectionDlg *ui;
+
+ void makeZones();
+ void saveSettings();
+
+};
+
+#endif // PERCENTCORRECTIONDLG_H
diff --git a/percentcorrectiondlg.ui b/percentcorrectiondlg.ui
new file mode 100644
index 00000000..17245cff
--- /dev/null
+++ b/percentcorrectiondlg.ui
@@ -0,0 +1,275 @@
+
+
+ percentCorrectionDlg
+
+
+
+ 0
+ 0
+ 528
+ 300
+
+
+
+ percent correction
+
+
+ -
+
+
-
+
+
+ Load Zone File
+
+
+
+ -
+
+
+ Save Zones
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Max Order
+
+
+
+ -
+
+
+ 10
+
+
+ 100
+
+
+ 2
+
+
+ 12
+
+
+
+ -
+
+
+ Zernike Terms
+
+
+
+ -
+
+
+ 35
+
+
+
+ -
+
+
+ <html><head/><body><p>This assumes the surface is a figure of revolution that matches the average profile.</p><p>It computes the slope of the average profile and compares it to the ideal slope for the conic desired. If the slope matches the expected value the percentage will be 100 percent. </p><p>This is only good for desired conics of -1. </p><p>The first 5% radius of the surface is ignored because the desired slope there is 0 to very small which creates invalid data.</p><p>It uses the sperical zernike polynomials to derive the profile. If the surface is slightly irregular with zones then using more Zernike terms is more accurate. If the surface is very smooth then you can use fewer Zernike terms. The default value of 22 is a resonalbe number. Use Max Order to change the number of zones.</p><p>This code is a Beta version and tested as best as possible but it may not be correct. Use at your own risk. Best to check with other methods before relying on it to figure a mirror. Use it first on a known mirror to see if it agrees with that.</p><p>You can change the number of zones and the position of the center of a zone. Use the table at the bottom to change the position of the center of a zone by editing the numbers in the zone center row. Default zone centers are computed the same as Carl Zambuto's spread sheed does.</p><p>You can save or load zone position files.</p></body></html>
+
+
+ ?
+
+
+
+
+
+ -
+
+
-
+
+
+ percent min:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ 5
+
+
+ -500.000000000000000
+
+
+ 500.000000000000000
+
+
+ 10.000000000000000
+
+
+ -10.000000000000000
+
+
+
+ -
+
+
+ percent max
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ 5
+
+
+ -500.000000000000000
+
+
+ 500.000000000000000
+
+
+ 10.000000000000000
+
+
+ 120.000000000000000
+
+
+
+ -
+
+
+ Zones:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ 0
+
+
+ 1000
+
+
+ 5
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Generate
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::NoButton
+
+
+ true
+
+
+
+
+
+
+
+ QwtPlot
+ QWidget
+
+ 1
+
+
+
+
+
+ buttonBox
+ accepted()
+ percentCorrectionDlg
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ percentCorrectionDlg
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/profileplot.cpp b/profileplot.cpp
index d2ace222..39ef886e 100644
--- a/profileplot.cpp
+++ b/profileplot.cpp
@@ -16,6 +16,7 @@
****************************************************************************/
#include "profileplot.h"
+#include "simigramdlg.h"
#include "ui_profileplot.h"
#include
#include
@@ -45,53 +46,36 @@
#include "mirrordlg.h"
#include
#include "surfaceanalysistools.h"
+#include "surfacemanager.h"
+#include "zernikeprocess.h"
+#include
+#include "plotcolor.h"
+#include "profileplotpicker.h"
extern double outputLambda;
+#include
+#include
+#include
+#include
+#include "percentcorrectiondlg.h"
#define PITORAD M_PI/180.;
double g_angle = 270. * PITORAD; //start at 90 deg (pointing east)
double y_offset = 0.;
-bool ProfilePlot::eventFilter( QObject *object, QEvent *event )
-{
- if ( event->type() == QEvent::MouseButtonPress )
- {
- QMouseEvent *mouseEvent = static_cast( event );
- if (mouseEvent->button() == Qt::RightButton){
- showContextMenu(mouseEvent->pos());
- return false;
- }
- startPos = mouseEvent->pos();
- dragging = true;
- return true;
-
- }
- else if (dragging && event->type() == QEvent::MouseMove){
- QMouseEvent *mouseEvent = static_cast( event );
- QPoint p = mouseEvent->pos();
- y_offset = .005 * (startPos.y() - p.y());
- populate();
- m_plot->replot();
- return true;
- }
- else if (dragging && event->type() == QEvent::MouseButtonRelease){
- dragging = false;
- return true;
- }
-
- return QObject::eventFilter( object, event );
-}
ProfilePlot::ProfilePlot(QWidget *parent , ContourTools *tools):
- QWidget( parent ),
- m_wf(0), m_tools(tools),
- m_showSurface(1.), m_showNm(1.), dragging(false),
- offsetType("Middle"),
- m_defocusValue(0.), ui(new Ui::ProfilePlot)
+ QWidget( parent ), m_wf(0), m_tools(tools),
+ m_showSurface(1.),m_showNm(1.),dragging(false),
+ offsetType("Middle"), m_defocusValue(0.),ui(new Ui::ProfilePlot)
{
+
+ m_pcdlg = new percentCorrectionDlg;
+ QObject::connect(m_pcdlg, SIGNAL(make_percent_correction()), this, SLOT(make_correction_graph()));
zoomed = false;
m_defocus_mode = false;
m_plot = new QwtPlot(this);
+ profilePlotPicker *picker = new profilePlotPicker(m_plot);
type = 0;
QHBoxLayout * l1 = new QHBoxLayout();
QVBoxLayout *v1 = new QVBoxLayout();
@@ -106,6 +90,8 @@ ProfilePlot::ProfilePlot(QWidget *parent , ContourTools *tools):
connect(ShowAll, SIGNAL(clicked()), this, SLOT(showAll()));
l1->addStretch();
showSlopeError = new QCheckBox("Show Slope: ");
+ showPercentCorrection = new QPushButton("Show Correction");
+ showPercentCorrection->setToolTip("Show % correction of zone areas used in the Zambuto method of mirror figuring.");
slopeLimitSB = new QDoubleSpinBox();
@@ -128,7 +114,8 @@ ProfilePlot::ProfilePlot(QWidget *parent , ContourTools *tools):
showSlopeError->setChecked(m_showSlopeError);
connect(slopeLimitSB, SIGNAL(valueChanged(double)), this, SLOT(slopeLimit(double)));
connect(showSlopeError,SIGNAL(clicked(bool)), this, SLOT(showSlope(bool)));
-
+ connect(showPercentCorrection,SIGNAL(clicked()), this, SLOT(showCorrection()));
+ l1->addWidget(showPercentCorrection);
l1->addWidget(showSlopeError);
l1->addWidget(slopeLimitSB);
l1->addWidget(showNmCB);
@@ -215,9 +202,9 @@ ProfilePlot::ProfilePlot(QWidget *parent , ContourTools *tools):
ui->setupUi(this);
populate();
}
-
ProfilePlot::~ProfilePlot(){
delete ui;
+ delete m_pcdlg;
}
void ProfilePlot::showSlope(bool val){
@@ -251,6 +238,7 @@ void ProfilePlot::showSurface(bool flag){
void ProfilePlot::showOne(){
type = 0;
+ m_pcdlg->close();
populate();
m_plot->replot();
}
@@ -261,6 +249,7 @@ void ProfilePlot::show16(){
}
void ProfilePlot::showAll(){
type = 2;
+ m_pcdlg->close();
populate();
m_plot->replot();
}
@@ -300,7 +289,14 @@ void ProfilePlot::angleChanged(double a){
m_plot->replot();
emit profileAngleChanged(M_2_PI - g_angle +M_PI/4.);
}
+void ProfilePlot::wheelEvent(QWheelEvent *event)
+{
+ double factor = 1/1.55;
+ if( event->angleDelta().y() < 0) factor = 1.5;
+
+ m_tools->setMinMaxValues(m_tools->m_min * factor, m_tools->m_max * factor);
+}
void ProfilePlot::setSurface(wavefront * wf){
m_wf = wf;
@@ -336,24 +332,76 @@ void ProfilePlot::setDefocusValue(double val){
m_plot->replot();
}
}
+QPolygonF ProfilePlot::createAverageProfile(double umnits, wavefront *wf, bool removeNull = false){
+ surfaceAnalysisTools *saTools = surfaceAnalysisTools::get_Instance();
+ QList list = saTools->SelectedWaveFronts();
+ QPolygonF avg;
+ for (int indx = 0; indx < list.size(); ++indx){
-QPolygonF ProfilePlot::createProfile(double units, wavefront *wf){
- QPolygonF points;
+ double startAngle = g_angle;
+ QPolygonF sum;
+ QMap count;
+ for (int i = 0; i < 720; ++i){
+ QPolygonF points;
+ g_angle = startAngle + i * M_PI/ 720;
- double steps = 1./wf->m_outside.m_radius;
- mirrorDlg &md = *mirrorDlg::get_Instance();
- double radius = md.m_clearAperature/2.;
- double obs_radius = md.obs/2.;
+ QwtPlotCurve *cprofile = new QwtPlotCurve( );
+ cprofile->setRenderHint( QwtPlotItem::RenderAntialiased );
+ cprofile->setLegendAttribute( QwtPlotCurve::LegendShowSymbol, false );
+ cprofile->setPen( Qt::black );
+
+ points = createProfile( m_showNm * m_showSurface,wfs->at(list[indx]));
+ if (i == 0) {
+ sum = points;
+ for (int j = 0; j < sum.length(); ++j)
+ count[j] = 1;
+ }
+ else {
+ for(int j = 0; j < fmin(sum.length(),points.length());++j){
+ sum[j].ry() += points[j].y();;
+
+ if (count.contains(j)) count[j] += 1 ;
+ else count[j] = 1;
+ }
+ }
- // If there is an annulus use it if it is a larger radius than the set obstruction
- if (md.m_useAnnular){
- double annularRadius = md.m_annularObsPercent * md.diameter/2.;
- if (annularRadius > obs_radius ){
- obs_radius = annularRadius;
}
+ // plot the average profile
+ int i = 0;
+ foreach(QPointF p, sum){
+ if (p.x() < 0) continue;
+ avg << QPointF(p.x(),p.y()/(count[i++]));
+ }
}
+// if (removeNull){
+// // Nulled y = (z8 - null)term8(rho) z8 * term8 - null * term8;
+// // remove artificial null effect.
+// mirrorDlg &md = *mirrorDlg::get_Instance();
+// QPolygonF avg2;
+// for (int i = 0; i < avg.length(); ++i){
+// if (avg[i].x() < 0)
+// continue;
+// double rho = avg[i].x() / md.diameter/2.;
+// double rho2 = rho * rho;
+// double y = avg[i].y();
+// y += md.z8 * md.cc * (1. + rho2 * (-6 + 6. * rho2));
+// avg2 << QPointF(avg[i].x(),y);
+// }
+// avg = avg2;
+// }
+qDebug() << "avg" << avg;
+ return avg;
+}
+QPolygonF ProfilePlot::createProfile(double units, wavefront *wf, bool allowOffset){
+ QPolygonF points;
+ mirrorDlg &md = *mirrorDlg::get_Instance();
+ double steps = 1./wf->m_outside.m_radius;
+ double offset = y_offset;
+ if (!allowOffset) offset = 0.;
+ double radius = md.m_clearAperature/2.;
+ double obs_radius = md.obs/2.;
for (double rad = -1.; rad < 1.; rad += steps){
int dx, dy;
@@ -376,24 +424,25 @@ QPolygonF ProfilePlot::createProfile(double units, wavefront *wf){
continue;
}
- if (wf->workMask.at(dy,dx)){
- double defocus = 0.;
+ if (wf->workMask.at(dy,dx)){
+ double defocus = 0.;
- if (m_defocus_mode){
- defocus = (m_defocusValue)* (-1. + 2. * rad * rad);
- points << QPointF(radx,(units * (m_defocus_wavefront((int)dy,(int)dx) + defocus ) *
- wf->lambda/outputLambda) +y_offset * units);
- }
- else {
+ if (m_defocus_mode){
+ defocus = (m_defocusValue)* (-1. + 2. * rad * rad);
+ points << QPointF(radx,(units * (m_defocus_wavefront((int)dy,(int)dx) + defocus ) *
+ wf->lambda/outputLambda) +offset * units);
+ }
+ else {
+
+ points << QPointF(radx,(units * (wf->workData((int)dy,(int)dx) ) *
+ wf->lambda/outputLambda) +offset * units);
- points << QPointF(radx,(units * (wf->workData((int)dy,(int)dx) ) *
- wf->lambda/outputLambda) +y_offset * units);
+ }
}
- }
- //else points << QPointF(radx,0.0);
+ //else points << QPointF(radx,0.0);
}
- if (m_showSlopeError){
+ if (m_showSlopeError && ((type==1) || (type == 0) || (type == 2))){
double arcsecLimit = (slopeLimitArcSec/3600) * M_PI/180;
double xDel = points[0].x() - points[1].x();
double hDelLimit =m_showNm * m_showSurface * ((outputLambda/m_wf->lambda)*fabs(xDel * tan(arcsecLimit)) /(outputLambda * 1.e-6));
@@ -420,14 +469,56 @@ QPolygonF ProfilePlot::createProfile(double units, wavefront *wf){
}
return points;
}
+// create a smoothed wave front with only spherical terms.
+// Use that to get zernike values to send to percent completion feature
+// display the profile and then send the zerns to percent completion
+// have to decide what is maxOrder
+
+zernikeProcess *zp = NULL;
+
+void ProfilePlot::make_correction_graph(){
+
+
+ int maxOrder = m_pcdlg->m_maxOrder;
+
+ // for each selected wave front
+ zernikeProcess zp;
+ zp.setMaxOrder(maxOrder);
+
+ surfaceAnalysisTools *saTools = surfaceAnalysisTools::get_Instance();
+ QList list = saTools->SelectedWaveFronts();
+ if (list.length() == 0)
+ list << 0;
+ QVector < surfaceData *> surfs;
+ for (int i = 0; i < list.size(); ++i){
+ QStringList path = wfs->at(list[i])->name.split("/");
+ QString name = path.last().replace(".wft","");
+
+ // compute zerns using the new maxorder zern set
+ zp.initGrid(*wfs->at(list[i]), maxOrder);
+ std::vector theZerns = zp.ZernFitWavefront(*wfs->at(list[i]));
+ if (theZerns.size() == 0) return;
+ // send zernike values to the correction dialog to have it plot correction based on them.
+
+ QColor penColor = Settings2::m_profile->getColor(i);
+ // give the plot routine new zernike values for each curve.
+ mirrorDlg *md = mirrorDlg::get_Instance();
+ surfs << new surfaceData( md->lambda, penColor, theZerns ,name);
+
+ }
+ QPolygonF avg = createAverageProfile(1., wfs->at(list[0]),true);
+ m_pcdlg->setProfile(avg);
+ m_pcdlg->setData(surfs);
+}
void ProfilePlot::populate()
{
+
m_plot->detachItems(QwtPlotItem::Rtti_PlotItem);
compass->setGeometry(QRect(80,80,70,70));
QString tmp("nanometers");
if (m_showNm == 1.)
- tmp = QString("waves of %1 nm").arg(outputLambda, 6, 'f', 1);
+ tmp = QString().sprintf("waves of %6.1lf nm",outputLambda);
m_plot->setAxisTitle( m_plot->yLeft, "Error in " + tmp );
m_plot->setAxisTitle( m_plot->xBottom, "Radius mm" );
@@ -445,7 +536,7 @@ void ProfilePlot::populate()
if (m_wf->m_outside.m_radius > 0 && settings.value("GBlur", false).toBool()){
double val = .01 * (m_wf->diameter) * smoothing;
- QString t = QString("Surface Smoothing diameter %1% of surface diameter %2 mm").arg(smoothing, 6, 'f', 2).arg( val, 6, 'f', 1 );
+ QString t = QString().sprintf("Surface Smoothing diameter %6.2lf%% of surface diameter %6.1lf mm", smoothing , val );
QwtText title(t);
title.setRenderFlags( Qt::AlignHCenter | Qt::AlignTop );
@@ -466,12 +557,10 @@ void ProfilePlot::populate()
m_plot->setAxisScaleDiv(QwtPlot::xBottom, sd1);
m_plot->detachItems( QwtPlotItem::Rtti_PlotCurve);
m_plot->detachItems( QwtPlotItem::Rtti_PlotMarker);
- //double b = 10. * ceil((m_wf->workData.cols/2.)/10.)+10;
- //m_plot->setAxisScale( QwtPlot::xBottom, -b, b,50);
- //m_plot->setAxisScaleDraw(m_plot->xBottom, new RadiusScaleDraw(m_wf->m_outside.m_radius,m_wf->diameter));
- // Insert new curves
- switch (type) {
+
+
+ switch (type) {
case 0:{ // show one
QStringList path = wfs->at(0)->name.split("/");
QString name;
@@ -493,58 +582,83 @@ void ProfilePlot::populate()
break;
}
- case 1: { // show 16 diameters
-
- if (true){
- QString t = "Average of all 16 diameters";
- QwtText title(t);
- title.setRenderFlags( Qt::AlignHCenter | Qt::AlignBottom );
-
- QFont font;
- font.setPointSize(12);
- title.setFont( font );
- title.setColor(Qt::blue);
- QwtPlotTextLabel *titleItem = new QwtPlotTextLabel();
- titleItem->setText( title );
- titleItem->attach( m_plot );
- }
- double startAngle = g_angle;
- QPolygonF sum;
-
- for (int i = 0; i < 16; ++i){
- QPolygonF points;
- g_angle = startAngle + i * M_PI/ 16;
-
- QwtPlotCurve *cprofile = new QwtPlotCurve( );
- cprofile->setRenderHint( QwtPlotItem::RenderAntialiased );
- cprofile->setLegendAttribute( QwtPlotCurve::LegendShowLine, false );
- cprofile->setPen( Qt::black );
- points = createProfile( m_showNm * m_showSurface,m_wf);
- if (i == 0) {
- sum = points;
- }
- else {
- for(int j = 0; j < fmin(sum.length(),points.length());++j){
- sum[j].ry() += points[j].y();
- }
- }
- cprofile->setSamples( points);
- cprofile->attach( m_plot );
- }
- QPolygonF avg;
- foreach(QPointF p, sum){
- avg << QPointF(p.x(),p.y()/16);
- }
- QwtPlotCurve *cprofileavg = new QwtPlotCurve( "average");
- cprofileavg->setRenderHint( QwtPlotItem::RenderAntialiased );
- cprofileavg->setLegendAttribute( QwtPlotCurve::LegendShowLine, false );
- cprofileavg->setPen( QPen(Qt::blue,5) );
- cprofileavg->setSamples( avg);
- cprofileavg->attach( m_plot );
- g_angle = startAngle;
- break;
- }
+ case 1: { // show 16 diameters
+
+ surfaceAnalysisTools *saTools = surfaceAnalysisTools::get_Instance();
+ QList list = saTools->SelectedWaveFronts();
+ bool firstPlot = true;
+ QColor penColor = QColor("blue");
+
+ for (int indx = 0; indx < list.size(); ++indx){
+ if (indx > 0) penColor = QColor(plotColors[indx % 10]);
+ QPolygonF avg;
+ QString t = "Average of all 16 diameters";
+ QwtText title(t);
+ title.setRenderFlags( Qt::AlignHCenter | Qt::AlignBottom );
+
+ QFont font;
+ font.setPointSize(12);
+ title.setFont( font );
+ title.setColor(Qt::blue);
+ QwtPlotTextLabel *titleItem = new QwtPlotTextLabel();
+ titleItem->setText( title );
+ titleItem->attach( m_plot );
+
+ double startAngle = g_angle;
+ QPolygonF sum;
+ QMap count;
+ for (int i = 0; i < 16; ++i){
+ QPolygonF points;
+ g_angle = startAngle + i * M_PI/ 16;
+
+ QwtPlotCurve *cprofile = new QwtPlotCurve( );
+ cprofile->setRenderHint( QwtPlotItem::RenderAntialiased );
+ cprofile->setLegendAttribute( QwtPlotCurve::LegendShowSymbol, false );
+ cprofile->setPen( Qt::black );
+
+ points = createProfile( m_showNm * m_showSurface,wfs->at(list[indx]));
+ if (i == 0) {
+ sum = points;
+ for (int j = 0; j < sum.length(); ++j)
+ count[j] = 1;
+ }
+ else {
+ for(int j = 0; j < fmin(sum.length(),points.length());++j){
+ sum[j].ry() += points[j].y();;
+
+ if (count.contains(j)) count[j] += 1 ;
+ else count[j] = 1;
+ }
+ }
+
+ cprofile->setSamples( points);
+ cprofile->attach( m_plot );
+
+ }
+
+ // plot the average profile
+ int i = 0;
+ foreach(QPointF p, sum){
+ avg << QPointF(p.x(),p.y()/(count[i++]));
+ }
+ QString name("average");
+
+ QwtPlotCurve *cprofileavg = new QwtPlotCurve( name);
+ cprofileavg->setRenderHint( QwtPlotItem::RenderAntialiased );
+ cprofileavg->setLegendAttribute( QwtPlotCurve::LegendShowSymbol, false );
+ cprofileavg->setLegendIconSize(QSize(50,20));
+ cprofileavg->setPen( QPen(penColor,5) );
+ cprofileavg->setSamples( avg);
+ cprofileavg->attach( m_plot );
+ g_angle = startAngle;
+
+
+ }
+
+
+ break;
+ }
case 2:{ // show each wave front
m_plot->insertLegend( new QwtLegend() , QwtPlot::BottomLegend);
@@ -564,13 +678,11 @@ void ProfilePlot::populate()
int width = Settings2::m_profile->lineWidth();
if (name == m_wf->name.split("/").last().replace(".wft",""))
width = Settings2::m_profile->selectedWidth();
-
+ cprofile->setLegendIconSize(QSize(50,20));
cprofile->setPen(QPen(Settings2::m_profile->getColor(i),width));
cprofile->setRenderHint( QwtPlotItem::RenderAntialiased );
- cprofile->setSamples( createProfile( m_showNm * m_showSurface,wfs->at(list[i])));
+ cprofile->setSamples( createProfile( m_showNm * m_showSurface,wfs->at(list[i]), i==0));
cprofile->attach( m_plot );
-
-
}
break;
@@ -579,8 +691,6 @@ void ProfilePlot::populate()
break;
}
-
-
// Insert markers
// ...a horizontal line at y = 0...
@@ -620,8 +730,12 @@ void ProfilePlot::populate()
mX->setXValue(0 );
mX->attach( m_plot );
+
}
+
+
+
void ProfilePlot::updateGradient()
{
@@ -675,6 +789,7 @@ void ProfilePlot::contourPointSelected(const QPointF &pos){
double dely = pos.y() - m_wf->data.cols/2;
double angle = atan2(delx,dely); // swaped x and y to rotate by 90 deg.
+ double angle2 = angle;
const double twopi = M_PI * 2.;
// force 0 to 360
if (angle < 0)
@@ -689,3 +804,13 @@ void ProfilePlot::contourPointSelected(const QPointF &pos){
compass->blockSignals(false);
}
+void ProfilePlot::showCorrection(){
+ if (m_wf == 0)
+ return;
+
+ m_pcdlg->show();
+ m_pcdlg->raise();
+ make_correction_graph();
+
+
+}
diff --git a/profileplot.h b/profileplot.h
index 9a37a9ff..f00aacbd 100644
--- a/profileplot.h
+++ b/profileplot.h
@@ -30,6 +30,7 @@
#include
#include
#include
+#include "percentcorrectiondlg.h"
namespace Ui {
class ProfilePlot;
}
@@ -39,6 +40,7 @@ class ProfilePlot : public QWidget
Q_OBJECT
public:
+ percentCorrectionDlg *m_pcdlg;
QwtPlot *m_plot;
wavefront* m_wf;
ProfilePlot( QWidget *parent = NULL, ContourTools* tools = 0 );
@@ -46,10 +48,10 @@ class ProfilePlot : public QWidget
QVector *wfs;
void setSurface(wavefront * wf);
virtual void resizeEvent( QResizeEvent * );
- QPolygonF createProfile(double units, wavefront *wf);
+ QPolygonF createProfile(double units, wavefront *wf, bool allowOffset = true);
+ QPolygonF createAverageProfile(double umnits, wavefront *wf, bool removeNull);
ContourTools *m_tools;
double m_waveRange;
- virtual bool eventFilter( QObject *, QEvent * );
QCheckBox *showNmCB;
QCheckBox *showSurfaceCB;
QRadioButton *OneOnly;
@@ -60,6 +62,7 @@ class ProfilePlot : public QWidget
double m_showNm;
bool zoomed;
bool m_showSlopeError;
+
double slopeLimitArcSec;
void setDefocusValue(double val);
void setDefocusWaveFront( cv::Mat_ wf);
@@ -68,6 +71,7 @@ class ProfilePlot : public QWidget
void profileAngleChanged(const double ang);
public slots:
+ void wheelEvent(QWheelEvent *event);
void setWavefronts(QVector *wf);
void angleChanged(double a);
void newDisplayErrorRange(double min, double max);
@@ -82,15 +86,19 @@ public slots:
void showSlope(bool);
void slopeLimit(double);
void contourPointSelected(const QPointF &pos);
-
-private:
void populate();
+ void showCorrection();
+ void make_correction_graph();
+ //QPolygonF createZernProfile(wavefront *wf);
+private:
+
void updateGradient();
bool dragging;
QPoint startPos;
QString offsetType;
QwtCompass *compass;
QCheckBox *showSlopeError;
+ QPushButton *showPercentCorrection;
QDoubleSpinBox *slopeLimitSB;
double m_defocusValue;
diff --git a/profileplotpicker.cpp b/profileplotpicker.cpp
new file mode 100644
index 00000000..ccd7b293
--- /dev/null
+++ b/profileplotpicker.cpp
@@ -0,0 +1,169 @@
+#include "profileplotpicker.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+profilePlotPicker::profilePlotPicker( QwtPlot *plot ):
+ QObject( plot ),
+ d_selectedCurve( NULL ),
+ d_selectedPoint( -1 )
+{
+ QwtPlotCanvas *canvas = qobject_cast( plot->canvas() );
+ canvas->installEventFilter( this );
+
+ // We want the focus, but no focus rect. The
+ canvas->setFocusPolicy( Qt::StrongFocus );
+#ifndef QT_NO_CURSOR
+ canvas->setCursor( Qt::PointingHandCursor );
+#endif
+ canvas->setFocusIndicator( QwtPlotCanvas::ItemFocusIndicator );
+ canvas->setFocus();
+
+}
+
+QwtPlot *profilePlotPicker::plot()
+{
+ return qobject_cast( parent() );
+}
+
+const QwtPlot *profilePlotPicker::plot() const
+{
+ return qobject_cast( parent() );
+}
+
+bool profilePlotPicker::event( QEvent *ev )
+{
+ if ( ev->type() == QEvent::User )
+ {
+
+ return true;
+ }
+ return QObject::event( ev );
+}
+
+bool profilePlotPicker::eventFilter( QObject *object, QEvent *event )
+{
+ if ( plot() == NULL || object != plot()->canvas() )
+ return false;
+
+ switch( event->type() )
+ {
+
+ case QEvent::FocusIn:
+ {
+
+ break;
+ }
+ case QEvent::FocusOut:
+ {
+
+ break;
+ }
+ case QEvent::Paint:
+ {
+ QApplication::postEvent( this, new QEvent( QEvent::User ) );
+ break;
+ }
+ case QEvent::MouseButtonPress:
+ {
+ const QMouseEvent *mouseEvent = static_cast( event );
+ m_lastMousePos = mouseEvent->pos();
+ select( mouseEvent->pos() );
+
+ return true;
+ }
+ case QEvent::MouseMove:
+ {
+
+ const QMouseEvent *mouseEvent = static_cast( event );
+ move( mouseEvent->pos() );
+ m_lastMousePos = mouseEvent->pos();
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ return QObject::eventFilter( object, event );
+}
+
+// Select the point at a position. If there is no point
+// deselect the selected point
+
+void profilePlotPicker::select( const QPoint &pos )
+{
+ QwtPlotCurve *curve = NULL;
+ double dist = 10e10;
+ int index = -1;
+
+ const QwtPlotItemList& itmList = plot()->itemList();
+ for ( QwtPlotItemIterator it = itmList.begin();
+ it != itmList.end(); ++it )
+ {
+ if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve )
+ {
+ QwtPlotCurve *c = static_cast( *it );
+
+ double d;
+ int idx = c->closestPoint( pos, &d );
+ if ( d < dist )
+ {
+ curve = c;
+ index = idx;
+ dist = d;
+
+ }
+ }
+ }
+
+ d_selectedCurve = curve;
+ d_selectedPoint = index;
+}
+
+
+// Move the selected point
+void profilePlotPicker::move( const QPoint &pos )
+{
+ qDebug() << "move pos" << pos;
+ if ( !d_selectedCurve )
+ return;
+qDebug() << "Move" << plot()->invTransform(d_selectedCurve->yAxis(), pos.y());
+ double last = plot()->invTransform( d_selectedCurve->yAxis(), m_lastMousePos.y() );
+ double current = plot()->invTransform( d_selectedCurve->yAxis(), pos.y() );
+ double delta = current - last;
+
+ QVector xData( d_selectedCurve->dataSize() );
+ QVector yData( d_selectedCurve->dataSize() );
+
+ for ( int i = 0;
+ i < static_cast( d_selectedCurve->dataSize() ); i++ )
+ {
+ xData[i] = d_selectedCurve->sample(i).x();
+ yData[i] = d_selectedCurve->sample(i).y() + delta;
+ }
+ d_selectedCurve->setSamples( xData, yData );
+
+ /*
+ Enable QwtPlotCanvas::ImmediatePaint, so that the canvas has been
+ updated before we paint the cursor on it.
+ */
+ QwtPlotCanvas *plotCanvas =
+ qobject_cast( plot()->canvas() );
+
+ plotCanvas->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, true );
+ plot()->replot();
+ plotCanvas->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, false );
+
+
+}
+
+
+
+
diff --git a/profileplotpicker.h b/profileplotpicker.h
new file mode 100644
index 00000000..4c9aa5ef
--- /dev/null
+++ b/profileplotpicker.h
@@ -0,0 +1,36 @@
+#ifndef PROFILEPLOTPICKER_H
+#define PROFILEPLOTPICKER_H
+#include
+#include
+
+
+class QCustomEvent;
+class QwtPlot;
+class QwtPlotCurve;
+
+class profilePlotPicker: public QObject
+{
+ Q_OBJECT
+ QPoint m_lastMousePos;
+public:
+ profilePlotPicker( QwtPlot *plot );
+ virtual bool eventFilter( QObject *, QEvent * );
+
+ virtual bool event( QEvent * );
+
+private:
+
+ void select( const QPoint & );
+ void move( const QPoint & );
+ void moveBy( int dx, int dy );
+
+ void release();
+
+
+ QwtPlot *plot();
+ const QwtPlot *plot() const;
+
+ QwtPlotCurve *d_selectedCurve;
+ int d_selectedPoint;
+};
+#endif
diff --git a/reportdlg.ui b/reportdlg.ui
index aa23eb2a..983f8382 100644
--- a/reportdlg.ui
+++ b/reportdlg.ui
@@ -65,7 +65,7 @@
-
- <html><head/><body><p>If images are cropped on the right size reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
+ <html><head/><body><p>If images are cropped on the right side reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
0.100000000000000
@@ -105,7 +105,7 @@
-
- <html><head/><body><p>If images are cropped on the right size reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
+ <html><head/><body><p>If images are cropped on the right side reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
0.100000000000000
@@ -146,7 +146,7 @@
-
- <html><head/><body><p>If images are cropped on the right size reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>d
+ <html><head/><body><p>If images are cropped on the right side reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p><p>d</p></body></html>
0.100000000000000
@@ -186,7 +186,7 @@
-
- <html><head/><body><p>If images are cropped on the right size reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
+ <html><head/><body><p>If images are cropped on the right side reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
0.100000000000000
@@ -230,7 +230,7 @@
-
- <html><head/><body><p>If images are cropped on the right size reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
+ <html><head/><body><p>If images are cropped on the right side reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
0.100000000000000
@@ -270,7 +270,7 @@
-
- <html><head/><body><p>If images are cropped on the right size reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
+ <html><head/><body><p>If images are cropped on the right side reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
0.100000000000000
@@ -312,7 +312,7 @@
-
- <html><head/><body><p>If images are cropped on the right size reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
+ <html><head/><body><p>If images are cropped on the right side reduce this number. <br/>If images are too small increase this number.</p><p>Usefull ranges are .8 - 1.1</p></body></html>
0.100000000000000
diff --git a/settingsGeneral2.h b/settingsGeneral2.h
index f35e4184..ad32a54f 100644
--- a/settingsGeneral2.h
+++ b/settingsGeneral2.h
@@ -25,23 +25,35 @@ class SettingsGeneral2 : public QDialog
bool shouldDownsize(){ return m_downsize;}
int wavefrontSize(){ return m_waveFrontSize;}
double getObs();
+
+public slots:
+ void updateContour();
signals:
void outputLambdaChanged(double val);
void updateContourPlot();
-public slots:
- void updateContour();
+
private slots:
void on_checkBox_clicked(bool checked);
+
void on_starTestMakeCb_clicked(bool checked);
+
void on_showConditionNumbersCb_clicked(bool checked);
+
void on_wavefrontSizeSb_valueChanged(int arg1);
+
void on_downSizeCB_clicked(bool checked);
+
void on_AstigDistGraphWidth_valueChanged(int val);
+
void on_applyOffsets_clicked(bool checked);
+
void on_outputLambda_valueChanged(double val);
+
void on_apply_clicked();
+
void on_rulerParms_clicked();
+
private:
Ui::SettingsGeneral2 *ui;
bool m_useSVD;
diff --git a/settingsgeneral2.cpp b/settingsgeneral2.cpp
index 4c2a18bd..a6c8e7f7 100644
--- a/settingsgeneral2.cpp
+++ b/settingsgeneral2.cpp
@@ -66,6 +66,8 @@ void SettingsGeneral2::on_rulerParms_clicked(){
}
+
+
void SettingsGeneral2::on_outputLambda_valueChanged(double val){
QSettings set;
set.setValue("outputLambda", val);
diff --git a/settingsigram.cpp b/settingsigram.cpp
index 3280a9b2..7f3d2925 100644
--- a/settingsigram.cpp
+++ b/settingsigram.cpp
@@ -23,7 +23,7 @@
#include
#include
#include "spdlog/spdlog.h"
-
+#include "settingsigramimportconfig.h"
static inline QString colorButtonStyleSheet(const QColor &bgColor)
{
if (bgColor.isValid()) {
@@ -271,3 +271,15 @@ void settingsIGram::on_holeY_valueChanged(int arg1)
QSettings set;
set.setValue("autoholeYOffset", arg1);
}
+
+void settingsIGram::on_importConfig_clicked()
+{
+ // set the path to igrams that "I key" should look at
+ // set select most recent
+ // set just open path
+ // set open camera stream
+
+ settingsIgramImportConfig dlg;
+ dlg.exec();
+}
+
diff --git a/settingsigram.h b/settingsigram.h
index 37511ae7..0e5557d8 100644
--- a/settingsigram.h
+++ b/settingsigram.h
@@ -86,6 +86,8 @@ private slots:
void on_holeY_valueChanged(int arg1);
+ void on_importConfig_clicked();
+
private:
Ui::settingsIGram *ui;
diff --git a/settingsigram.ui b/settingsigram.ui
index 189529b1..90d41eda 100644
--- a/settingsigram.ui
+++ b/settingsigram.ui
@@ -7,7 +7,7 @@
0
0
492
- 537
+ 563
@@ -358,6 +358,13 @@
+ -
+
+
+ Import interferogram configuration (what hot key "i" does)
+
+
+
-
diff --git a/settingsigramimportconfig.cpp b/settingsigramimportconfig.cpp
new file mode 100644
index 00000000..91081f12
--- /dev/null
+++ b/settingsigramimportconfig.cpp
@@ -0,0 +1,52 @@
+#include "settingsigramimportconfig.h"
+#include "ui_settingsigramimportconfig.h"
+#include
+#include
+settingsIgramImportConfig::settingsIgramImportConfig(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::settingsIgramImportConfig)
+{
+ ui->setupUi(this);
+ QSettings set;
+ ui->importPath->setText(set.value("importIgramPath",".").toString());
+
+ ui->openPath->setChecked(set.value("importIgramOpenOnly", false).toBool());
+ ui->openMostRecent->setChecked(set.value("importIgramOpenMostRecent", true).toBool());
+
+}
+
+settingsIgramImportConfig::~settingsIgramImportConfig()
+{
+ delete ui;
+}
+
+
+
+
+void settingsIgramImportConfig::on_browse_clicked()
+{
+ QSettings set;
+ QString defaultPath = set.value("lastPath",".").toString();
+ QString path = set.value("importIgramPath",defaultPath).toString();
+ QString directory = QFileDialog::getExistingDirectory(
+ 0, "Choose directory", "",
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+
+ ui->importPath->setText(directory);
+
+}
+
+
+
+#include
+
+void settingsIgramImportConfig::on_buttonBox_accepted()
+{
+ QSettings set;
+ set.setValue("importIgramPath",ui->importPath->text());
+
+
+ set.setValue("importIgramOpenOnly", ui->openPath->isChecked());
+ set.setValue("importIgramOpenMostRecent", ui->openMostRecent->isChecked());
+}
+
diff --git a/settingsigramimportconfig.h b/settingsigramimportconfig.h
new file mode 100644
index 00000000..7ea0cd06
--- /dev/null
+++ b/settingsigramimportconfig.h
@@ -0,0 +1,28 @@
+#ifndef SETTINGSIGRAMIMPORTCONFIG_H
+#define SETTINGSIGRAMIMPORTCONFIG_H
+
+#include
+
+namespace Ui {
+class settingsIgramImportConfig;
+}
+
+class settingsIgramImportConfig : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit settingsIgramImportConfig(QWidget *parent = nullptr);
+ ~settingsIgramImportConfig();
+
+private slots:
+
+ void on_browse_clicked();
+
+ void on_buttonBox_accepted();
+
+private:
+ Ui::settingsIgramImportConfig *ui;
+};
+
+#endif // SETTINGSIGRAMIMPORTCONFIG_H
diff --git a/settingsigramimportconfig.ui b/settingsigramimportconfig.ui
new file mode 100644
index 00000000..59280b00
--- /dev/null
+++ b/settingsigramimportconfig.ui
@@ -0,0 +1,139 @@
+
+
+ settingsIgramImportConfig
+
+
+
+ 0
+ 0
+ 640
+ 480
+
+
+
+ "I" hot key config
+
+
+
-
+
+
+ Choose what the hot key "I" does when pressed on the main window.
+
+
+
+ -
+
+
-
+
+
+ Path to igrams to import:
+
+
+
+ -
+
+
+ -
+
+
+ ...
+
+
+
+
+
+ -
+
+
-
+
+
+ Just Open Dir
+
+
+
+ -
+
+
+ Open most recent igram
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ settingsIgramImportConfig
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ settingsIgramImportConfig
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/simigramdlg.cpp b/simigramdlg.cpp
index 55bed9a1..fe7ef874 100644
--- a/simigramdlg.cpp
+++ b/simigramdlg.cpp
@@ -246,13 +246,17 @@ void simIgramDlg::on_buttonBox_accepted()
size = ui->sizeSB->value();
s.setValue("simSize", size);
}
-
+extern std::vector zernEnables;
void simIgramDlg::on_importPb_clicked()
{
SurfaceManager &sm = *SurfaceManager::get_instance();
if (sm.m_wavefronts.size() == 0)
return;
zernikes = sm.getCurrent()->InputZerns;
+ for (unsigned int z = 0; z < zernikes.size(); ++z){
+ if (!zernEnables[z])
+ zernikes[z] = 0.;
+ }
tableModel->setValues(&zernikes);
ui->correctionPb->setChecked(false);
ui->Z8Pb->setChecked(true);
diff --git a/simulationsview.cpp b/simulationsview.cpp
index 5ffac6e5..6aae6223 100644
--- a/simulationsview.cpp
+++ b/simulationsview.cpp
@@ -309,7 +309,7 @@ cv::Mat SimulationsView::computeStarTest(cv::Mat surface, int pupil_size, double
}
#endif
// create star test using pupil_size which is usually smaller than the wavefront being sampled.
-cv::Mat SimulationsView::computeStarTest(cv::Mat surface, int pupil_size, double pad , bool returnComplex){
+cv::Mat SimulationsView:: computeStarTest(cv::Mat surface, int pupil_size, double pad , bool returnComplex){
alias = false;
cv::Mat out;
@@ -709,8 +709,8 @@ void SimulationsView::on_MakePB_clicked()
cv::Mat focused = computeStarTest(nulledSurface(0), fftSize, ui->centerMagnifySB->value());
t = fitStarTest(zoomMat(focused,ui->centerMagnifySB->value()), wid ,gamma/2);
-
- cv::putText(t,"Focused",cv::Point(20,20),1,1,cv::Scalar(255, 255,255));
+ QString focusedtext = QString("Focused magnified by %1x").arg(ui->centerMagnifySB->value());
+ cv::putText(t,focusedtext.toStdString().c_str(),cv::Point(20,20),1,1,cv::Scalar(255, 255,255));
QImage focusDisplay ((uchar*)t.data, t.cols, t.rows, t.step, QImage::Format_RGB888);
ui->Focused->setPixmap(QPixmap::fromImage(focusDisplay.copy()));
diff --git a/simulationsview.ui b/simulationsview.ui
index b2a294fd..651b3553 100644
--- a/simulationsview.ui
+++ b/simulationsview.ui
@@ -145,7 +145,7 @@
-
- Imaage magnifiction (as with an eyepiece)
+ <html><head/><body><p>Image magnification (as with an eyepiece)</p></body></html>
1.000000000000000
diff --git a/standastigwizard.cpp b/standastigwizard.cpp
index f57f3d38..6c617378 100644
--- a/standastigwizard.cpp
+++ b/standastigwizard.cpp
@@ -126,15 +126,17 @@ makeAverages::makeAverages(QWidget *parent)
setLayout(layout);
}
void define_input::pdfNamesPressed(){
- QString fileName = QFileDialog::getSaveFileName((QWidget* )0, "Export PDF", QString(mirrorDlg::get_Instance()->getProjectPath() +
- "/stand.pdf"), "*.pdf");
+ QSettings set;
+ QString standReportPath = set.value("stand report path", mirrorDlg::get_Instance()->getProjectPath()).toString();
+ QString fileName = QFileDialog::getSaveFileName((QWidget* )0, "Export PDF", standReportPath + "/stand.pdf" ,
+ "*.pdf");
if (fileName.isEmpty())
return;
if (QFileInfo(fileName).suffix().isEmpty()) { fileName.append(".pdf"); }
AstigReportPdfName = fileName;
pdfName->setText(fileName);
- QSettings set;
- set.setValue("stand pdf file", fileName.split("/").last());
+
+ set.setValue("stand report path", QFileInfo(fileName).absolutePath());
}
void define_input::setBasePath(){
QString baseName = QFileDialog::getExistingDirectory(
@@ -250,11 +252,14 @@ define_input::define_input(QWidget *parent)
l->addWidget(listDisplay,8,0,10,-1);
l->addWidget(new QLabel("Report Title:"),18,0);
l->addWidget(title, 18,1);
- showWork = new QCheckBox("Show work Files");
+ showWork = new QCheckBox("Keep work Files");
l->addWidget(showWork, 18,2);
l->addWidget(new QLabel("Pdf File Name:"), 19,0);
l->addWidget(pdfName, 19,1,1,-1);
l->addWidget(runpb, 20,0,1,7);
+ m_log = new QTextEdit();
+ m_log->append("Ready to add wave fronts to process.");
+ l->addWidget(m_log,21,0,1,0);
setLayout(l);
}
diff --git a/standastigwizard.h b/standastigwizard.h
index 6bc7fc0e..7201e950 100644
--- a/standastigwizard.h
+++ b/standastigwizard.h
@@ -103,6 +103,7 @@ class define_input : public QWizardPage
QRadioButton *CCWRb;
QPushButton *runpb;
QCheckBox *showWork;
+ QTextEdit* m_log;
//int nextId() const;
diff --git a/surfaceanalysistools.h b/surfaceanalysistools.h
index fa8f4033..8b823c81 100644
--- a/surfaceanalysistools.h
+++ b/surfaceanalysistools.h
@@ -46,6 +46,7 @@ class surfaceAnalysisTools : public QDockWidget
QList SelectedWaveFronts();
bool m_useDefocus;
double m_defocus;
+ double m_defocusInmm;
void setBlurText(QString txt);
void nameChanged(int, QString);
void select(int item);
diff --git a/surfacemanager.cpp b/surfacemanager.cpp
index ca76cf8e..bfbf9eb6 100644
--- a/surfacemanager.cpp
+++ b/surfacemanager.cpp
@@ -865,7 +865,7 @@ void SurfaceManager::computeMetrics(wavefront *wf){
}
void SurfaceManager::defocusSetup(){
wavefront *wf = m_wavefronts[m_currentNdx];
- qDebug() << "wave" << wf->workData.rows;
+
m_profilePlot->setDefocusWaveFront(wf->workData);
}
@@ -1921,8 +1921,8 @@ textres SurfaceManager::Phase2(QList list, QList inp
QTextDocument *doc = editor->document();
textres results;
results.Edit = editor;
- const int Width = 400 * .9;
- const int Height = 300 * .9;
+ const int Width = 800 * .6;
+ const int Height = 600 * .6;
QImage contour(Width ,Height, QImage::Format_ARGB32 );
QPrinter printer(QPrinter::HighResolution);
@@ -1994,6 +1994,7 @@ textres SurfaceManager::Phase2(QList list, QList inp
maxYastig = std::max(maxYastig, mirrorY);
yastig.at(i,0) = mirrorY;
qDebug() << "Mirror astigs " << mirrorX << mirrorY;
+ QApplication::processEvents();
}
Circle fittedcircle1;
@@ -2095,7 +2096,7 @@ qDebug() << "circle fit"<< avgRadius << fittedcircle1.r << fittedcircle2.r;
"
| " + QString().number(yval,'f',3) + " | "
"" + QString().number(mag,'f',3) + " | "
"" + QString().number((180./ M_PI) * atan2(yval,xval)/2.,'f',1) + " | ");
-
+ QApplication::processEvents();
}
html.append("| MEAN | " + QString().number(fittedcircle.a,'f',3) + " | " +
QString().number(fittedcircle.b,'f',3) + " | " + QString().number(sqrt(fittedcircle.a * fittedcircle.a + fittedcircle.b * fittedcircle.b),'f',3) + " |
");
@@ -2178,6 +2179,7 @@ qDebug() << "circle fit"<< avgRadius << fittedcircle1.r << fittedcircle2.r;
cnt = 0;
imagesHtml.append("");
}
+ QApplication::processEvents();
}
mirrorAstigRadius /= list.size();
@@ -2446,6 +2448,8 @@ void SurfaceManager::computeStandAstig(define_input *wizPage, QListfname;
+ wizPage->m_log->append("Loading " + list[i]->fname);
+ QApplication::processEvents();
loadWavefront(list[i]->fname);
wavefront * wf = m_wavefronts[m_currentNdx];
inputs.append(wf);
@@ -2461,7 +2465,9 @@ void SurfaceManager::computeStandAstig(define_input *wizPage, QList  " + angle + " | ");
// counter rotate it
- wizPage->runpb->setText(QString("Counter Rotating ") + list[i]->fname.right(list[i]->fname.size() - list[i]->fname.lastIndexOf("/")-1));
+
+ wizPage->m_log->setText(QString("Counter Rotating ") + list[i]->fname.right(list[i]->fname.size() - list[i]->fname.lastIndexOf("/")-1));
+ QApplication::processEvents();
QList l;
l.append(ndx);
ndx = m_wavefronts.size();
@@ -2492,7 +2498,8 @@ void SurfaceManager::computeStandAstig(define_input *wizPage, QListsetDocument(doc);
//editor->show();
-
+ wizPage->m_log->append("averaging rotated wave fronts");
+ QApplication::processEvents();
// Now average all the rotated ones.
QList wlist;
for (int i = 0; i < rotated.size(); ++i){
@@ -2539,7 +2546,8 @@ void SurfaceManager::computeStandAstig(define_input *wizPage, QListrunpb->setText("computing stand astigs");
+ wizPage->m_log->setText("computing stand astigs");
+ QApplication::processEvents();
textres page3res = Phase2(list, inputs, avgNdx);
QTabWidget *tabw = new QTabWidget();
tabw->setTabShape(QTabWidget::Triangular);
diff --git a/zernikeprocess.cpp b/zernikeprocess.cpp
index f0a53d10..ecdba249 100644
--- a/zernikeprocess.cpp
+++ b/zernikeprocess.cpp
@@ -53,6 +53,8 @@ int Zw[] = { /* n */
// [[Rcpp::export]]
+
+
arma::mat zapm(const arma::vec& rho, const arma::vec& theta,
const double& eps, const int& maxorder=12) ;
cv::Mat zpmCx(QVector rho, QVector theta, int maxorder) {
@@ -1094,6 +1096,7 @@ void spectral_color(double &R,double &G,double &B,double wavelength)
cv::Mat zernikeProcess::makeSurfaceFromZerns(int border, bool doColor){
+
simIgramDlg &dlg = *simIgramDlg::get_instance();
double obs = .01 * dlg.getObs();
int wx = dlg.size + 2 * border;
@@ -1106,7 +1109,7 @@ cv::Mat zernikeProcess::makeSurfaceFromZerns(int border, bool doColor){
initGrid(wx, rad, (wx-1)/2, (wx-1)/2, m_maxOrder, 0);
double spacing = 1.;
mirrorDlg *md = mirrorDlg::get_Instance();
- qDebug() << "fringe spacing" << md->fringeSpacing;
+
double r,g,b;
spectral_color(r,g,b, md->lambda);
if (doColor) {
@@ -1118,7 +1121,6 @@ cv::Mat zernikeProcess::makeSurfaceFromZerns(int border, bool doColor){
if (dlg.m_doArbitrary)
dlg_arbitrary->prepare(dlg.size);
-
for (std::size_t i = 0; i < m_rhoTheta.n_cols; ++i)
{
@@ -1154,6 +1156,8 @@ cv::Mat zernikeProcess::makeSurfaceFromZerns(int border, bool doColor){
int x = m_col[i];
int y = m_row[i];
+
+
if (doColor){
if (rho < obs)
@@ -1174,82 +1178,6 @@ cv::Mat zernikeProcess::makeSurfaceFromZerns(int border, bool doColor){
return result;
}
-#define TSIZE 450 // number of points in zern generator
-void ZernikeSmooth(cv::Mat wf, cv::Mat mask)
-{
- // given a wavefront generate arbitrary number of zernikes from it. Then create wavefront from the zernikies.
- double *m = (double *)(wf.data);
-
-
- int size = wf.cols;
- int step = (double)size/200.; // 200 samples across the wavefront
- double delta = (double)TSIZE/size; // scale factor from wavefront to zernike generator
-
- double* tmp = new double[TSIZE * TSIZE];
- memset(tmp, 0,sizeof(double) * TSIZE * TSIZE);
-
- zern_generator zg(TSIZE);
- zg.set_spec(6);
- zg.zpoly_list();
-
-
-
- //'calculate LSF matrix elements
-
- int terms = zg.get_terms_cnt();
- int am_size = terms* terms;
- double* Am = new double[am_size];
- double* Bm = new double[terms];
- for (int i = 0; i < am_size; ++i)
- {
- Am[i] = 0.;
- }
- for (int i = 0; i < terms; ++i)
- Bm[i] = 0;
-
- //calculate LSF right hand side
- for(int y = 0; y < size; y += step) //for each point on the surface
- {
- for(int x = 0; x < size; x += step)
- {
- int xx = x* delta;
- int yy = y * delta;
- if (mask.at(x,y))
- {
- int sndx = x + y* size;
-
- tmp[xx+yy * TSIZE] = m[sndx];
- for (int i = 0; i < terms; ++i)
- {
- double ipoly = zg.get_zpoly(i,xx,yy);
- int dy = i * terms;
- for (int j = 0; j < terms; ++j)
- {
- int ndx = j + dy;
- Am[ndx] = Am[ndx] +
- ipoly * zg.get_zpoly(j, xx, yy);
- }
- Bm[i] = Bm[i] + m[sndx] * ipoly;
-
- }
-
- }
- }
-
- }
- // compute coefficients
- gauss_jordan (terms, Am, Bm);
-
- zg.set_zcoefs(Bm);
-
- for (int i = 0; i < terms; ++i){
- qDebug() << i << " " << Bm[i];
- }
- delete[] Am;
- delete[] Bm;
- delete[] tmp;
-}
-
arma::mat zernikeProcess::rhotheta( int width, double radius, double cx, double cy,
const wavefront *wf){
@@ -1277,8 +1205,8 @@ arma::mat zernikeProcess::rhotheta( int width, double radius, double cx, double
for (int y = 0; y < rows; ++y){
double uy = (y -cy)/radius;
- if (!m_bDontProcessEvents)
- QApplication::processEvents();
+// if (!m_bDontProcessEvents)
+// QApplication::processEvents();
for (int x = 0; x< rows; ++x){
double ux = (x -cx)/radius;
@@ -1351,6 +1279,7 @@ arma::mat zernikeProcess::zpmC(arma::rowvec rho, arma::rowvec theta, int maxorde
nm1mp1 = nm-2;
nm2m = (order-2)*(order-2)/4+order-2;
zm(i, nm) = 2.*rho[i]*zm(i, nm1mp1) - zm(i, nm2m);
+
}
// now multiply each column by normalizing factor and cos, sin
@@ -1433,60 +1362,12 @@ arma::mat zernikeProcess::zapmC(const arma::rowvec& rho, const arma::rowvec& the
return annzm;
}
-void dumpArma(arma::mat mm, QString title = "", QVector colHeading = QVector(0),
- QVector RowLable = QVector(0)){
- arma::mat theMat = mm;
- QString transposed(" ");
-
-
- QString log;
-
- QString s;
- QTextStream out(&s);
-
- out << "" << transposed << title <<" zern matrix size "<< mm.n_rows <<"X" << mm.n_cols << "
";
-
- log.append(s);
- if (!colHeading.empty()){
- log.append("");
- for (int c = 0; c < colHeading.size(); ++c){
- log.append("| "+colHeading[c] + " | ");
- }
- log.append("
\n");
- }
-
- for (arma::uword row =0; row < theMat.n_rows; ++row){
- if (row > 20) break;
- log.append(" | ");
- if (!RowLable.empty()){
-
- if (row < static_cast(RowLable.size())){
- log.append(QString("%1").arg(RowLable[row]));
- }
-
- }
- log.append(" | ");
-
- for (arma::uword c = 0; c< theMat.n_cols; ++c){
- log.append(QString("%1 | ").arg(theMat(row,c), 6, 'f', 5));
- }
- log.append("
\n");
-
- }
- log.append("
");
- QTextEdit *display = new QTextEdit();
- display->resize(2500,1000);
- display->insertHtml(log);
-
- display->show();
-
-}
void zernikeProcess::initGrid(int width, double radius, double cx, double cy, int maxOrder,
double insideRad){
- qDebug() << "initGrid width " << width << radius << cx << cy << maxOrder << insideRad;
+
// if grid or maxOrder is different then update values.
double obsPercent = 0.;
bool shouldUseAnnulus = false;
@@ -1583,17 +1464,18 @@ std::vector zernikeProcess::ZernFitWavefront(wavefront &wf){
if (i%5000 == 0) {
prg->setValue(i);
QApplication::processEvents();
-// if (prg->wasCanceled()){
-// throw 42;
-// }
+ if (prg->wasCanceled()){
+ std::vector dummy;
+ return dummy; // a zero lengh vector signals cancelation.
+
+ }
}
if ( rho <= 1. && (wf.mask.at( m_row[i], m_col[i]) != 0)){
for ( int zi = 0; zi < ztermCnt; ++zi)
{
double t = m_zerns(i,zi);
- //if (zi == 0)
- // qDebug() << "z0" << t << "rho:"< zernikeProcess::ZernFitWavefront(wavefront &wf){
wf.InputZerns = std::vector(ztermCnt,0);
for (std::size_t z = 0; z < static_cast(X.rows); ++z){
- if (z < wf.InputZerns.size()){
- //qDebug() << z << X(z) << wf.InputZerns[z] << (QString("%1").arg(X(z) - wf.InputZerns[z], 6, 'f', 4)).toDouble();
- }
- else {
- //qDebug() << z << X(z);
- }
+
wf.InputZerns[z] = X(z);
}
@@ -1626,148 +1503,54 @@ std::vector zernikeProcess::ZernFitWavefront(wavefront &wf){
X.col(0).copyTo(r);
return r;
}
-void make3DPsf(cv::Mat surface){
-
- QWidget *plotWindow = new QWidget;
- Q3DSurface *m_PSF_3Dgraph;
- m_PSF_3Dgraph = new Q3DSurface();
- QWidget *container = QWidget::createWindowContainer(m_PSF_3Dgraph);
- QHBoxLayout *hLayout = new QHBoxLayout();
- QVBoxLayout *vLayout = new QVBoxLayout();
- hLayout->addWidget(container, 1);
- hLayout->addLayout(vLayout);
- plotWindow->setLayout(hLayout);
-
- cv::Mat data = surface.clone();//(cv::Rect(start,start,nx/2,nx/2));
-
+//debug routine to see what is matrix values.
+void dumpArma(arma::mat mm, QString title = "", QVector colHeading = QVector(0),
+ QVector RowLable = QVector(0)){
+ arma::mat theMat = mm;
+ QString transposed(" ");
- double xmin,xmax;
- cv::minMaxLoc(data, &xmin,&xmax);
- data/=xmax;
+ QString log;
- QSurfaceDataProxy *m_sqrtSinProxy = new QSurfaceDataProxy();
- QSurface3DSeries *m_sqrtSinSeries = new QSurface3DSeries(m_sqrtSinProxy);
+ QString s;
+ QTextStream out(&s);
- //draw surfaced
- {
+ out << "" << transposed << title <<" zern matrix size "<< mm.n_rows <<"X" << mm.n_cols << "
";
- int sampleCountX = data.size[1];
- int sampleCountZ = data.size[0];
- int width = sampleCountX;
- QSurfaceDataArray *dataArray = new QSurfaceDataArray;
- QSurfaceDataArray *dataArray2 = new QSurfaceDataArray;
- dataArray->reserve(sampleCountZ);
- dataArray2->reserve(sampleCountZ);
- for (int i = 0 ; i < sampleCountZ ; i++) {
- QSurfaceDataRow *newRow = new QSurfaceDataRow(sampleCountX);
- QSurfaceDataRow *backRow = new QSurfaceDataRow(sampleCountX);
- float z = -(sampleCountZ/2. - i);
- int index = 0;
- for (int j = 0; j < sampleCountX; j++) {
- float x = -(sampleCountX/2. -j);
-
- float y = data.at(i,j);
- (*newRow)[index].setPosition(QVector3D(x, y, z));
- (*backRow)[index++].setPosition(QVector3D(x, y, width/2));
- }
- *dataArray << newRow;
- *dataArray2 << backRow;
+ log.append(s);
+ if (!colHeading.empty()){
+ log.append("");
+ for (int c = 0; c < colHeading.size(); ++c){
+ log.append("| "+colHeading[c] + " | ");
}
+ log.append("
\n");
+ }
- QSurfaceDataProxy *m_sqrtSinProxy2 = new QSurfaceDataProxy();
- QSurface3DSeries *m_sqrtSinSeries2 = new QSurface3DSeries(m_sqrtSinProxy2);
-
-
- m_sqrtSinProxy->resetArray(dataArray);
- m_sqrtSinSeries->setDrawMode(QSurface3DSeries::DrawSurface);
- m_sqrtSinSeries->setFlatShadingEnabled(false);
-
- m_sqrtSinProxy2->resetArray(dataArray2);
- m_sqrtSinSeries2->setDrawMode(QSurface3DSeries::DrawSurfaceAndWireframe);
- m_sqrtSinSeries2->setFlatShadingEnabled(false);
-
- QLinearGradient gr;
- gr.setColorAt(0.0, Qt::darkGray);
- gr.setColorAt(0.01,Qt::cyan);
- gr.setColorAt(0.33, Qt::blue);
- gr.setColorAt(0.67, Qt::lightGray);
- gr.setColorAt(1.0, Qt::red);
- m_PSF_3Dgraph->activeTheme()->setType(Q3DTheme::Theme(3));
+ for (arma::uword row =0; row < theMat.n_rows; ++row){
+ if (row > 20) break;
+ log.append(" | ");
+ if (!RowLable.empty()){
+ if (row < static_cast(RowLable.size())){
+ log.append(QString("%1").arg(RowLable[row]));
+ }
+ }
+ log.append(" | ");
- m_PSF_3Dgraph->axisX()->setRange(-width/2, width/2);
- m_PSF_3Dgraph->axisZ()->setRange(-width/2, width/2);
+ for (arma::uword c = 0; c< theMat.n_cols; ++c){
+ log.append(QString("%1 | ").arg(theMat(row,c), 6, 'f', 5));
+ }
+ log.append("
\n");
- m_PSF_3Dgraph->addSeries(m_sqrtSinSeries);
- m_PSF_3Dgraph->addSeries(m_sqrtSinSeries2);
- m_PSF_3Dgraph->seriesList().at(0)->setBaseGradient(gr);
- m_PSF_3Dgraph->seriesList().at(0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
- }
- plotWindow->show();
-}
-#include
-#include
-#include "zernikesmoothingdlg.h"
-using namespace cv;
-void debugZernRoutines(wavefront &wf){
- int cols = 4;
- for (int i = 0; i < 10; ++i) {
- qDebug() << i << i/cols << i%cols;
}
- return;
- zernikeProcess &zp = *zernikeProcess::get_Instance();
-
-// QFile inputFile("C:\\Users\\doeas\\Documents\\t.txt");
-// double xc = 487.;
-// double yc = 486.;
-// double rad = 463.;
-// if (inputFile.open(QIODevice::ReadOnly))
-// {
-// QTextStream in(&inputFile);
-// int row = 0;
-// vector tmpRow;
-// vector< vector> data;
-// while (!in.atEnd())
-// {
-// QString line = in.readLine();
-// QStringList fields = line.simplified().split(" ");
-// tmpRow.clear();
-// for (int i = 0; i < fields.size(); ++i){
-// if (fields[i].contains("NA")){
-// tmpRow.push_back(0.0);
-// }
-// else {
-// tmpRow.push_back(fields[i].toDouble());
-// }
-// }
-// data.push_back(tmpRow);
-// }
-// inputFile.close();
-// qDebug() << "data" << data.size() << data[10].size();
-// cv::Mat matd(data.size(),data[1].size(), numType,0.);
-// for(int i=0; i(i, j) = data.at(i).at(j);
-// make3DPsf(matd);
-
-// sm->createSurfaceFromPhaseMap(matd,
-// CircleOutline(QPointF(xc,yc),rad),
-// CircleOutline(QPointF(0,0),0),
-// QString("Mikes wavefront"));
-
-
-
-
- for (int terms = 6; terms < 50; terms += 2) {
-
- zp.initGrid(wf, terms);
- zp.ZernFitWavefront(wf);
- qDebug() << "Max Order" << terms << wf.InputZerns[8]/(sqrt(5.));
- }
+ log.append("
");
+ QTextEdit *display = new QTextEdit();
+ display->resize(2500,1000);
+ display->insertHtml(log);
+ display->show();
- }
+}
diff --git a/zernikesmoothingdlg.cpp b/zernikesmoothingdlg.cpp
index 9bba9d0f..a3ecfddb 100644
--- a/zernikesmoothingdlg.cpp
+++ b/zernikesmoothingdlg.cpp
@@ -20,7 +20,8 @@ ZernikeSmoothingDlg::ZernikeSmoothingDlg(wavefront &wf, QWidget *parent) :
std::vector val(m_noOfTerms,0.);
ui->zernView->setModel(tableModel);
QSettings set;
- m_maxOrder = set.value("Zern maxOrder", 12).toInt();
+
+ m_maxOrder = set.value("Zern maxOrder", 22).toInt();
ui->maxOrder->setValue(m_maxOrder);
ui->termCnt->setText(QString("%1 Terms").arg(m_noOfTerms));
connect(&m_timer, SIGNAL(timeout()), this, SLOT(intiZernTable()));
@@ -52,10 +53,12 @@ void ZernikeSmoothingDlg::on_maxOrder_valueChanged(int arg1)
{
if (arg1 % 2 != 0)
++arg1;
+ QSettings set;
+ set.setValue("Zern maxOrder",arg1);
+
ui->maxOrder->setValue( arg1);
m_maxOrder = arg1;
-
m_zp->setMaxOrder(arg1);
m_noOfTerms = m_zp->getNumberOfTerms();
ui->termCnt->setText(QString("%1 Terms").arg(m_noOfTerms));
@@ -66,25 +69,51 @@ void ZernikeSmoothingDlg::on_maxOrder_valueChanged(int arg1)
m_timer.setSingleShot(true);
m_timer.start(1000);
+
}
-cv::Mat makeSurfaceFromZerns(int width, zernikeProcess &zp, std::vector theZerns){
+
+cv::Mat makeSurfaceFromZerns(int width, zernikeProcess &zp, std::vector theZerns, bool sph = false){
int wx = width;
cv::Mat result = cv::Mat::zeros(wx,wx, numType);
-
- for (unsigned long long i = 0; i < zp.m_zerns.n_rows; ++i){
- double S1 = 0.0;
- for (unsigned int z = 0; z < theZerns.size(); ++z){
- double val = theZerns[z];
- S1 += val * zp.m_zerns(i,z);
+ if (!sph) {
+ for (unsigned long long i = 0; i < zp.m_zerns.n_rows; ++i){
+ double S1 = 0.0;
+ for (unsigned int z = 0; z < theZerns.size(); ++z){
+ double val = theZerns[z];
+ S1 += val * zp.m_zerns(i,z);
+
+ //if (rho < .5) S1 = 0.;
+ }
int x = zp.m_col[i];
int y = zp.m_row[i];
-
if (S1 == 0.0) S1 += .0000001;
- //if (rho < .5) S1 = 0.;
result.at(y,x) = S1;
}
}
+ else { // use only spherical terms.
+ unsigned int z = 0;
+ for (unsigned long long i = 4; i < zp.m_zerns.n_rows; ++i){
+
+ double S1 = 0.0;
+ unsigned int z = 8;
+ for (unsigned int j = 6; z < theZerns.size(); j+=2){
+
+ double val = theZerns[z];
+ S1 += val * zp.m_zerns(i,z);
+
+ z = j * j/4 + j;
+ }
+ int x = zp.m_col[i];
+ int y = zp.m_row[i];
+ if (S1 == 0.0) S1 += .0000001;
+ result.at(y,x) = S1;
+ if (y == wx/2.){
+ qDebug() << x << y << S1;
+ }
+
+ }
+ }
return result;
}
@@ -94,16 +123,17 @@ void ZernikeSmoothingDlg::on_createWaveFront_clicked()
QApplication::setOverrideCursor(Qt::WaitCursor);
m_wf = *p_wf;
if (!ui->useCurrentZernySet->isChecked()){
- theZerns = m_zp->ZernFitWavefront(m_wf);
- qDebug() << "the zerns";
- for (int z = 0; z < 8; ++z){
- qDebug() << z << theZerns[z];
+ std::vector tzerns = m_zp->ZernFitWavefront(m_wf);
+ if (tzerns.size() == 0){
+ QApplication::restoreOverrideCursor();
+ return;
}
+ theZerns = tzerns;
}
tableModel->setValues(&theZerns);
- cv::Mat result = makeSurfaceFromZerns(m_wf.data.cols, *m_zp, theZerns);
+ cv::Mat result = makeSurfaceFromZerns(m_wf.data.cols, *m_zp, theZerns, m_spherical_only);
QStringList l = m_wf.name.split("/");
l.back().replace(".wft","");
@@ -123,3 +153,9 @@ void ZernikeSmoothingDlg::on_createWaveFront_clicked()
}
QApplication::restoreOverrideCursor();
}
+
+void ZernikeSmoothingDlg::on_sphereOnly_toggled(bool checked)
+{
+ m_spherical_only = checked;
+}
+
diff --git a/zernikesmoothingdlg.h b/zernikesmoothingdlg.h
index 0ab059e4..b1479e61 100644
--- a/zernikesmoothingdlg.h
+++ b/zernikesmoothingdlg.h
@@ -16,11 +16,14 @@ class ZernikeSmoothingDlg : public QDialog
public:
explicit ZernikeSmoothingDlg(wavefront &wf, QWidget *parent = nullptr);
~ZernikeSmoothingDlg();
-
+ bool m_spherical_only = false;
private slots:
void on_maxOrder_valueChanged(int arg1);
void on_createWaveFront_clicked();
void intiZernTable();
+
+ void on_sphereOnly_toggled(bool checked);
+
private:
Ui::ZernikeSmoothingDlg *ui;
int m_maxOrder;
diff --git a/zernikesmoothingdlg.ui b/zernikesmoothingdlg.ui
index ced903bd..44ea69d9 100644
--- a/zernikesmoothingdlg.ui
+++ b/zernikesmoothingdlg.ui
@@ -65,6 +65,9 @@ p, li { white-space: pre-wrap; }
2
+
+ 22
+
@@ -97,6 +100,13 @@ p, li { white-space: pre-wrap; }
+ -
+
+
+ Spherical terms only
+
+
+
-