From 72e392fd70f849726469c4b61c63317442e0db86 Mon Sep 17 00:00:00 2001
From: Dale Eason
Date: Wed, 21 May 2025 22:27:56 -0500
Subject: [PATCH 01/13] Worked on stand astig removal feature. Change size of
images so that they do not depend upon display resolution but only on printer
paper size. Added astig polar plot to stand removal report. Saved user data
of report to recall when run again. Updated polar plot logic to enable
report to grab it's image and also make it's size proportional to the users
screen size.
---
astigpolargraph.cpp | 35 ++++------
astigpolargraph.h | 12 +++-
astigpolargraph.ui | 2 +-
mainwindow.cpp | 12 +++-
standastigwizard.cpp | 34 +++++++--
surfacemanager.cpp | 159 +++++++++++++++++++++++++++++--------------
surfacemanager.h | 2 +-
7 files changed, 171 insertions(+), 85 deletions(-)
diff --git a/astigpolargraph.cpp b/astigpolargraph.cpp
index ce49c900..3b05d10a 100644
--- a/astigpolargraph.cpp
+++ b/astigpolargraph.cpp
@@ -2,13 +2,16 @@
#include "ui_astigpolargraph.h"
#include "surfacemanager.h"
-void astigPolargraph::makeChart(){
-
+astigPolargraph::astigPolargraph( QListlist, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::astigPolargraph)
+{
+ ui->setupUi(this);
QPolarChart *chart = new QPolarChart();
// process each wave front and place astig on the chart
- ui->waveFrontTable->setRowCount(m_list.size());
+ ui->waveFrontTable->setRowCount(list.size());
QValueAxis *angularAxis = new QValueAxis();
angularAxis->setTickCount(9); // First and last ticks are co-located on 0/360 angle.
@@ -25,15 +28,15 @@ void astigPolargraph::makeChart(){
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;
+ for(int ndx = 0; ndx < list.length(); ++ndx){
+
+ QString name = list[ndx].m_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 xastig = list[ndx].m_xastig;
+ double yastig = list[ndx].m_yastig;
double mag = sqrt(xastig * xastig + yastig * yastig);
if (mag > maxAstig) maxAstig = mag;
@@ -69,7 +72,7 @@ void astigPolargraph::makeChart(){
}
chart->setTitle("Magnitude and axis of high edge");
- if (m_list.length() > 4)
+ if (list.length() > 4)
chart->legend()->setAlignment(Qt::AlignRight);
else chart->legend()->setAlignment(Qt::AlignBottom);
@@ -79,20 +82,6 @@ void astigPolargraph::makeChart(){
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()
diff --git a/astigpolargraph.h b/astigpolargraph.h
index e8d3dbcb..a3ad5daa 100644
--- a/astigpolargraph.h
+++ b/astigpolargraph.h
@@ -13,19 +13,25 @@
namespace Ui {
class astigPolargraph;
}
+class astigSample{
+public:
+ QString m_name;
+ double m_xastig;
+ double m_yastig;
+ astigSample(QString name, double xastig, double yastig): m_name(name), m_xastig(xastig), m_yastig(yastig){};
+};
class astigPolargraph : public QDialog
{
Q_OBJECT
public:
- explicit astigPolargraph(QList list,QWidget *parent = nullptr);
+ 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
index 566f4f73..5c0600d6 100644
--- a/astigpolargraph.ui
+++ b/astigpolargraph.ui
@@ -55,7 +55,7 @@
Qt::Horizontal
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+ QDialogButtonBox::NoButton
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 758e184a..025f5412 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -2074,8 +2074,16 @@ 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);
+ QList samples;
+ foreach(int i, list){
+ wavefront *wf = m_surfaceManager->m_wavefronts[i];
+ astigSample sample(wf->name, wf->InputZerns[4], wf->InputZerns[5]);
+ samples << sample;
+ }
+ astigPolargraph * graph = new astigPolargraph(samples);
+ QScreen *screen = QGuiApplication::primaryScreen();
+ QSizeF physicalSize = screen->availableSize();
+ graph->resize(physicalSize.width()/2,physicalSize.height()/2);
graph->exec();
}
diff --git a/standastigwizard.cpp b/standastigwizard.cpp
index 6c617378..8f0eb553 100644
--- a/standastigwizard.cpp
+++ b/standastigwizard.cpp
@@ -42,8 +42,12 @@ standAstigWizard::standAstigWizard(SurfaceManager *sm, QWidget *parent, Qt::Wind
setWindowTitle(tr("Stand Astig analysis"));
setPixmap(QWizard::WatermarkPixmap, QPixmap(":/res/wats2.png"));
setPixmap(QWizard::LogoPixmap, QPixmap(":/res/mirror_stand.png"));
- //AstigReportTitle = mirrorDlg::get_Instance()->m_name;
- //resize( QSize(600, 489));
+
+
+ QScreen *screen = QGuiApplication::primaryScreen();
+
+ resize(screen->availableSize().width() * .5 ,screen->availableSize().height() * .5);
+
}
standAstigWizard::~standAstigWizard()
@@ -122,6 +126,7 @@ makeAverages::makeAverages(QWidget *parent)
);
txt->setReadOnly(true);
QVBoxLayout *layout = new QVBoxLayout;
+
layout->addWidget(txt);
setLayout(layout);
}
@@ -227,9 +232,15 @@ define_input::define_input(QWidget *parent)
QPushButton *browsePath = new QPushButton("...");
CWRb = new QRadioButton("Rotate CW");
CCWRb = new QRadioButton("Rotate CCW");
- CCWRb->setChecked(true);
+ if (set.value("stand astig ccw", true).toBool())
+ CCWRb->setChecked(true);
+ else
+ CWRb->setChecked(true);
+
connect(browsePath, SIGNAL(pressed()), this, SLOT(setBasePath()));
+
+
browsePath->setStyleSheet("");
QGridLayout *l = new QGridLayout();
@@ -246,6 +257,12 @@ define_input::define_input(QWidget *parent)
listDisplay = new QListWidget();
listDisplay->setSelectionMode( QAbstractItemView::MultiSelection);
listDisplay->setContextMenuPolicy(Qt::CustomContextMenu);
+ int size = set.beginReadArray("stand astig removal files");
+ for (int i = 0; i < size; ++i) {
+ set.setArrayIndex(i);
+ listDisplay->addItem(set.value("item").toString());
+ }
+ set.endArray();
connect(listDisplay, SIGNAL(customContextMenuRequested(QPoint)), this,
SLOT(showContextMenu(QPoint)));
@@ -260,6 +277,7 @@ define_input::define_input(QWidget *parent)
m_log = new QTextEdit();
m_log->append("Ready to add wave fronts to process.");
l->addWidget(m_log,21,0,1,0);
+
setLayout(l);
}
@@ -270,7 +288,15 @@ void define_input::compute(){
QMessageBox::warning(0, "", "You must first add at least 2 wavefront files to the list.");
return;
}
-
+ QSettings set;
+ set.setValue("stand astig ccw",CCWRb->isChecked() );
+ set.beginWriteArray("stand astig removal files");
+ // save the listDisplay of files to process
+ for (int i = 0; i < listDisplay->count(); ++i) {
+ set.setArrayIndex(i);
+ set.setValue("item", listDisplay->item(i)->text());
+ }
+ set.endArray();
AstigReportTitle = title->text();
runpb->setText("Working");
runpb->setEnabled(false);
diff --git a/surfacemanager.cpp b/surfacemanager.cpp
index bfbf9eb6..8cb546d5 100644
--- a/surfacemanager.cpp
+++ b/surfacemanager.cpp
@@ -72,6 +72,7 @@
#include "oglrendered.h"
#include "ui_oglrendered.h"
#include "spdlog/spdlog.h"
+#include "astigpolargraph.h"
cv::Mat theMask;
cv::Mat deb;
@@ -1909,31 +1910,41 @@ void plotlineThruAstigs(QwtPlot *plt, cv::Mat xastig, cv::Mat yastig, QListphysicalDotsPerInchX();
+
+ int Width;
+
+ printer.setPageSize(QPageSize(printer.pageLayout().pageSize()));
+ QPainter painterPDF( &printer );
+
+ // I want to create images that are about 1/2 as wide as the printer paper.
+ // So get the printer paper size
+ // THen get the screen resolution
+ // then calculate how many pixels create that size image on the screen
+
+ // get the size of the printed page in inches.
+ QSize printerSizePixels = printer.pageLayout().paintRectPixels(printer.resolution()).size();
+ qreal pageWidthInches = printerSizePixels.width()/printer.resolution();
+ qreal imageWidthInches= .8 * pageWidthInches/2;
+
+ Width = imageWidthInches * screenDPI;
+ return Width;
+}
// calculate stand astig for each input
// for each input rotate the average by the input angle and subtract it from the input
// plot the astig of each of the inputs which will be the stand only astig.
// on input list is the list of wavefront files and thier rotation angle.
// inputs are the actual wavefronts at original rotations.
// avgNdx is the index in the m_wavefronts list of the average with stand removed.
-textres SurfaceManager::Phase2(QList list, QList inputs, int avgNdx ){
+textres SurfaceManager::Phase2(QList list, QList inputs, int avgNdx , int Width, QPrinter &printer){
QTextEdit *editor = new QTextEdit;
QTextDocument *doc = editor->document();
textres results;
- results.Edit = editor;
- const int Width = 800 * .6;
- const int Height = 600 * .6;
- QImage contour(Width ,Height, QImage::Format_ARGB32 );
-
- QPrinter printer(QPrinter::HighResolution);
- printer.setColorMode( QPrinter::Color );
- printer.setFullPage( true );
- printer.setOutputFileName( "stand.pdf" );
- printer.setOutputFormat( QPrinter::PdfFormat );
- //printer.setResolution(85);
- printer.setPageSize(QPageSize(QPageSize::A4));
- QPainter painterPDF( &printer );
cv::Mat xastig = cv::Mat::zeros(list.size(), 1, numType);
cv::Mat yastig = cv::Mat::zeros(list.size(), 1, numType);
cv::Mat standxastig = cv::Mat::zeros(list.size(), 1, numType);
@@ -1941,8 +1952,15 @@ textres SurfaceManager::Phase2(QList list, QList inp
cv::Mat standastig = cv::Mat::zeros(list.size(), 1, numType);
QVector standwfs;
QVector astigMag;
- editor->resize(printer.pageLayout().paintRectPixels(printer.resolution()).size());
+
+ int Height = Width;
+
+ QImage contour(Width , Height, QImage::Format_ARGB32 );
+
+ results.Edit = editor;
+ editor->resize(Width, Height);
doc->setPageSize(printer.pageLayout().paintRectPixels(printer.resolution()).size());
+
cv::Mat standavg = cv::Mat::zeros(inputs[0]->workData.size(), numType);
cv::Mat standavgZernMat = cv::Mat::zeros(inputs[0]->workData.size(), numType);
double mirrorXaverage = 0;
@@ -2021,7 +2039,7 @@ textres SurfaceManager::Phase2(QList list, QList inp
}
fittedcircle2 = Circle(xmean/xastig.rows, ymean/xastig.rows, avgRadius/xastig.rows );
fittedcircle = fittedcircle2;
-qDebug() << "circle fit"<< avgRadius << fittedcircle1.r << fittedcircle2.r;
+
fittedcircle = fittedcircle1;
if (xastig.rows == 2 || fittedcircle1.r > 1.5 * fittedcircle2.r ){
fittedcircle = fittedcircle2;
@@ -2118,6 +2136,7 @@ qDebug() << "circle fit"<< avgRadius << fittedcircle1.r << fittedcircle2.r;
QPolygonF mirrorAstigAtEachRotation;
double mirrorAstigRadius =0;
plotlineThruAstigs(pl1, xastig, yastig, list);
+ QList samples;
for (int i = 0; i < list.size(); ++i){
if (cnt++ == 0)
imagesHtml.append("");
@@ -2166,15 +2185,21 @@ qDebug() << "circle fit"<< avgRadius << fittedcircle1.r << fittedcircle2.r;
wf->name = QString("%1").arg(list[i]->angle, 6, 'f', 2, QLatin1Char('0'));
cp->setSurface(wf);
- cp->resize(Width,Height);
+ cp->resize(Width,.8 * Height);
cp->replot();
+ astigSample sample(wf->name, wf->InputZerns[4], wf->InputZerns[5]);
+ samples << sample;
+ QSize s = cp->size();
contour.fill( QColor( Qt::white ).rgb() );
- renderer.render( cp, &painter, QRect(0,0,Width,Height) );
+ renderer.render( cp, &painter, QRect(0,0,s.width(),s.height() ));
+
QString imageName = QString("mydata://zern%1.png").arg(wf->name);
imageName.replace("-","CCW");
doc->addResource(QTextDocument::ImageResource, QUrl(imageName), QVariant(contour));
results.res.append (imageName);
- imagesHtml.append("  | ");
+
+ imagesHtml.append(QString(" ") + wf->name + "

| ");
+
if (cnt == 2){
cnt = 0;
imagesHtml.append("
");
@@ -2200,20 +2225,20 @@ qDebug() << "circle fit"<< avgRadius << fittedcircle1.r << fittedcircle2.r;
minMaxIdx(wf2->data, &mmin,&mmax);
wf2->min = mmin;
wf2->max = mmax;
- //wf2->workMask = m_wavefronts[0]->workMask.clone();
+
wf2->name = QString("Average Stand zernike based");
ContourPlot *cp1 = new ContourPlot();
- //cp1->m_zRangeMode = "Min/Max";
+
cp1->setSurface(wf2);
- cp1->resize(Width, Height);
+ cp1->resize(Width, .8 * Height);
cp1->replot();
- QImage contour2(500, 500, QImage::Format_ARGB32 );
+ QImage contour2(Width, Width, QImage::Format_ARGB32 );
contour2.fill( QColor( Qt::white ).rgb() );
QPainter painter2( &contour2 );
renderer.setDiscardFlag(QwtPlotRenderer::DiscardLegend, false);
renderer.render( cp1, &painter2, QRect(0,0,Width,Height) );
- QString imageName = "mydata://StandCotourZerns.png";
+ QString imageName = "mydata://StandContourZerns.png";
doc->addResource(QTextDocument::ImageResource, QUrl(imageName), QVariant(contour2));
wf2->data = wf2->workData = standavg;
@@ -2232,7 +2257,7 @@ qDebug() << "circle fit"<< avgRadius << fittedcircle1.r << fittedcircle2.r;
contour2.fill( QColor( Qt::white ).rgb() );
renderer.render( cp1, &painter2, QRect(0,0,Width,Height) );
cp1->m_zRangeMode = "Auto"; // restore contour plot to auto scaling.
- imageName = QString("mydata://StandCotourMat.png");
+ imageName = QString("mydata://StandContourMat.png");
doc->addResource(QTextDocument::ImageResource, QUrl(imageName), QVariant(contour2));
@@ -2309,15 +2334,22 @@ qDebug() << "circle fit"<< avgRadius << fittedcircle1.r << fittedcircle2.r;
curveAvgMirror->setPen(pen);
curveAvgMirror->setSamples(stdCircle);
curveAvgMirror->attach(pl1);
- pl1->resize(500,500);
+ pl1->resize(1.5 * Width,1.5 * Width);
pl1->replot();
- QwtPlotRenderer renderer3;
- QImage contour3(500, 500, QImage::Format_ARGB32 );
+
+ QImage contour3(1.5 * Width, 1.5 * Width , QImage::Format_ARGB32 );
contour3.fill( QColor( Qt::white ).rgb() );
QPainter painter3( &contour3 );
renderer.setDiscardFlag(QwtPlotRenderer::DiscardLegend, false);
- renderer.render( pl1, &painter3, QRect(0,0,500,500) );
+ renderer.render( pl1, &painter3, QRect(0,0,1.5 * Width,1.5 * Width) );
+
+// QPixmap pixmap = QPixmap::fromImage(contour3); // Create a QPixmap from the QImage
+// QLabel* label = new QLabel(); // Create a QLabel
+// label->setPixmap(pixmap); // Set the QPixmap to the QLabel
+// label->show(); // Show the QLabel
+
+
imageName = QString("mydata://plot.png");
doc->addResource(QTextDocument::ImageResource, QUrl(imageName), QVariant(contour3));
results.res.append (imageName);
@@ -2336,18 +2368,37 @@ qDebug() << "circle fit"<< avgRadius << fittedcircle1.r << fittedcircle2.r;
"The stand removal was good. Idealy the STD (standard deviation) should be"
" less than .1 which means less than .1 wave pv on the surface of the mirror"
"
The colored plus signs are what is calculated for test stand induced astig."
- "at each rotation angle.
"
+ "at each rotation angle.
The plot below is a polar plot of each rotations test stand astig."
+ "The ideal would be they are all the same magnitude and angle. If any one is much different than the rest then the astig removal may not be good.");
+ astigPolargraph *polar = new astigPolargraph(samples);
+ polar->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
+ polar->resize(Width * 2, 2 * Width);
+ QImage polarImage(2 * Width, 2 * Width , QImage::Format_ARGB32 );
+ polarImage.fill( QColor( Qt::white ).rgb() );
+ QPainter painterPolar( &polarImage );
+
+
+ polar->render( &painterPolar);
+
+ imageName = QString("mydata://polarplot.png");
+ doc->addResource(QTextDocument::ImageResource, QUrl(imageName), QVariant(polarImage));
+ results.res.append (imageName);
+ html.append(" 
");
+ html.append(" |  |
"
+ "The contours above are the average system induced forces derived from the average of all rotations.
"
+ "The left contour is based on the zernike values and the contour on the right is based on the wavefront.
");
- ""
- "The contours above are the average system induced forces derived from the average of all rotations.
"
- "The left contour is based on the zernike values and the contour on the right is based on the wavefront.
"
- "The contour plots below are of what is beleived to be test stand only induced errors at each rotation. "
+
+
+ html.append( "
The contour plots below are of what is beleived to be test stand only induced errors at each rotation. "
"Check that they are similar at each rotation. If not then maybe "
"stand (system) induced error is not same at each rotation then the stand removal is not reliable. "
"However it is unlikely that they will all look exactly the same.
");
+
+
html.append(imagesHtml);
html.append("