PaIRS-UniNa 0.2.8__cp312-cp312-win_amd64.whl → 0.2.10__cp312-cp312-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PaIRS_UniNa/Calibration_Tab.py +16 -0
- PaIRS_UniNa/Changes.txt +21 -0
- PaIRS_UniNa/Explorer.py +3312 -3126
- PaIRS_UniNa/FolderLoop.py +561 -561
- PaIRS_UniNa/Input_Tab.py +824 -826
- PaIRS_UniNa/Input_Tab_CalVi.py +1 -0
- PaIRS_UniNa/Input_Tab_tools.py +3020 -3019
- PaIRS_UniNa/PaIRS.py +17 -17
- PaIRS_UniNa/PaIRS_pypacks.py +18 -65
- PaIRS_UniNa/Process_Tab.py +19 -15
- PaIRS_UniNa/Process_Tab_Disp.py +8 -1
- PaIRS_UniNa/SPIVCalHelp.py +155 -0
- PaIRS_UniNa/Saving_tools.py +279 -277
- PaIRS_UniNa/TabTools.py +165 -6
- PaIRS_UniNa/Vis_Tab.py +11 -4
- PaIRS_UniNa/Vis_Tab_CalVi.py +1 -2
- PaIRS_UniNa/_PaIRS_PIV.pyd +0 -0
- PaIRS_UniNa/__init__.py +3 -3
- PaIRS_UniNa/addwidgets_ps.py +570 -70
- PaIRS_UniNa/gPaIRS.py +3933 -3889
- PaIRS_UniNa/icons/information.png +0 -0
- PaIRS_UniNa/icons/information2.png +0 -0
- PaIRS_UniNa/icons/spiv_setup_no.png +0 -0
- PaIRS_UniNa/icons/spiv_setup_ok.png +0 -0
- PaIRS_UniNa/listLib.py +301 -301
- PaIRS_UniNa/parForMulti.py +433 -433
- PaIRS_UniNa/rqrdpckgs.txt +7 -7
- PaIRS_UniNa/tabSplitter.py +606 -606
- PaIRS_UniNa/ui_Calibration_Tab.py +576 -543
- PaIRS_UniNa/ui_Custom_Top.py +294 -294
- PaIRS_UniNa/ui_Input_Tab.py +1098 -1098
- PaIRS_UniNa/ui_Input_Tab_CalVi.py +1280 -1280
- PaIRS_UniNa/ui_Log_Tab.py +261 -261
- PaIRS_UniNa/ui_Output_Tab.py +2360 -2360
- PaIRS_UniNa/ui_Process_Tab.py +3808 -3808
- PaIRS_UniNa/ui_Process_Tab_CalVi.py +1547 -1547
- PaIRS_UniNa/ui_Process_Tab_Disp.py +1139 -1139
- PaIRS_UniNa/ui_Process_Tab_Min.py +435 -435
- PaIRS_UniNa/ui_ResizePopup.py +203 -203
- PaIRS_UniNa/ui_Vis_Tab.py +1626 -1626
- PaIRS_UniNa/ui_Vis_Tab_CalVi.py +1249 -1249
- PaIRS_UniNa/ui_Whatsnew.py +131 -131
- PaIRS_UniNa/ui_gPairs.py +873 -873
- PaIRS_UniNa/ui_infoPaIRS.py +550 -550
- PaIRS_UniNa/whatsnew.txt +2 -4
- {pairs_unina-0.2.8.dist-info → pairs_unina-0.2.10.dist-info}/METADATA +7 -13
- {pairs_unina-0.2.8.dist-info → pairs_unina-0.2.10.dist-info}/RECORD +49 -45
- {pairs_unina-0.2.8.dist-info → pairs_unina-0.2.10.dist-info}/WHEEL +0 -0
- {pairs_unina-0.2.8.dist-info → pairs_unina-0.2.10.dist-info}/top_level.txt +0 -0
PaIRS_UniNa/PaIRS.py
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
from .gPaIRS import *
|
|
2
|
-
|
|
3
|
-
def run():
|
|
4
|
-
gui:gPaIRS
|
|
5
|
-
app,gui,flagPrint=launchPaIRS()
|
|
6
|
-
quitPaIRS(app,flagPrint)
|
|
7
|
-
|
|
8
|
-
def cleanRun():
|
|
9
|
-
if os.path.exists(lastcfgname):
|
|
10
|
-
os.remove(lastcfgname)
|
|
11
|
-
run()
|
|
12
|
-
|
|
13
|
-
def debugRun():
|
|
14
|
-
gui:gPaIRS
|
|
15
|
-
app,gui,flagPrint=launchPaIRS(flagInputDebug=True)
|
|
16
|
-
quitPaIRS(app,flagPrint)
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
|
|
3
|
+
def run():
|
|
4
|
+
gui:gPaIRS
|
|
5
|
+
app,gui,flagPrint=launchPaIRS()
|
|
6
|
+
quitPaIRS(app,flagPrint)
|
|
7
|
+
|
|
8
|
+
def cleanRun():
|
|
9
|
+
if os.path.exists(lastcfgname):
|
|
10
|
+
os.remove(lastcfgname)
|
|
11
|
+
run()
|
|
12
|
+
|
|
13
|
+
def debugRun():
|
|
14
|
+
gui:gPaIRS
|
|
15
|
+
app,gui,flagPrint=launchPaIRS(flagInputDebug=True)
|
|
16
|
+
quitPaIRS(app,flagPrint)
|
|
17
|
+
|
|
18
|
+
|
PaIRS_UniNa/PaIRS_pypacks.py
CHANGED
|
@@ -80,8 +80,10 @@ if currentID in (developerIDs['GP_Win_Office'],developerIDs['GP_Win_Office_New']
|
|
|
80
80
|
'C:/desk/PIV_Img/img1/',
|
|
81
81
|
'C:/desk/PIV_Img/_data/PIV_data/virtual_case/',
|
|
82
82
|
'C:/desk/PIV_Img/_data/PIV_data/real_case/',
|
|
83
|
+
'C:/desk/PIV_Img/_data/SPIV_data/real_case/img/',
|
|
83
84
|
'C:/desk/PIV_Img/_data/Calibration_data/pinhole/',
|
|
84
85
|
'C:/desk/PIV_Img/_data/Calibration_data/cylinder/',
|
|
86
|
+
'C:/desk/PIV_Img/_data/SPIV_data/real_case/calib/',
|
|
85
87
|
]
|
|
86
88
|
basefold_DEBUG_VIS='C:/desk/PIV_Img/_data/PIV_data/real_case/'
|
|
87
89
|
elif currentID==developerIDs['GP_WSL']:
|
|
@@ -148,6 +150,15 @@ fileChanges='Changes.txt'
|
|
|
148
150
|
fileWhatsNew=['whatsnew.txt','whatwasnew.txt']
|
|
149
151
|
icons_path="icons/"
|
|
150
152
|
|
|
153
|
+
gPaIRS_QMenu_style="""
|
|
154
|
+
QMenu::item:selected,
|
|
155
|
+
QMenu::item:checked,
|
|
156
|
+
QMenu::item:pressed {
|
|
157
|
+
background-color: rgba(0, 116, 255, 0.8);
|
|
158
|
+
color: white;
|
|
159
|
+
}
|
|
160
|
+
"""
|
|
161
|
+
|
|
151
162
|
from psutil import cpu_count
|
|
152
163
|
NUMTHREADS_MAX=cpu_count(logical=True)#-1
|
|
153
164
|
if NUMTHREADS_MAX<1: NUMTHREADS_MAX=1
|
|
@@ -808,12 +819,6 @@ def toPlainText(text):
|
|
|
808
819
|
PlainTextConverter.setHtml(text) #for safety
|
|
809
820
|
return PlainTextConverter.toPlainText()
|
|
810
821
|
|
|
811
|
-
def showTip(obj,message):
|
|
812
|
-
toolTipDuration=obj.toolTipDuration()
|
|
813
|
-
obj.setToolTipDuration(3000)
|
|
814
|
-
QToolTip.showText(QCursor.pos(),message)
|
|
815
|
-
obj.setToolTipDuration(toolTipDuration)
|
|
816
|
-
|
|
817
822
|
def clean_tree(tree:QTreeWidget):
|
|
818
823
|
def remove_children(item:QTreeWidgetItem):
|
|
819
824
|
while item.childCount() > 0:
|
|
@@ -1166,59 +1171,6 @@ def checkOutDated(packageName:str,printOutDated):
|
|
|
1166
1171
|
f3=executor.submit(asyncio.run,checkOutDatedInternal(packageName))
|
|
1167
1172
|
f3.add_done_callback(checkOutDatedComplete)
|
|
1168
1173
|
|
|
1169
|
-
def changes(self,TabType,filename,title=" Changes"):
|
|
1170
|
-
FlagShow=False
|
|
1171
|
-
if self.logChanges:
|
|
1172
|
-
if self.logChanges.isVisible():
|
|
1173
|
-
FlagShow=True
|
|
1174
|
-
if FlagShow:
|
|
1175
|
-
self.logChanges.hide()
|
|
1176
|
-
self.logChanges.show()
|
|
1177
|
-
else:
|
|
1178
|
-
self.logChanges=TabType(self,True)
|
|
1179
|
-
self.logChanges.resize(720,720)
|
|
1180
|
-
self.logChanges.show()
|
|
1181
|
-
self.logChanges.ui.progress_Proc.hide()
|
|
1182
|
-
self.logChanges.ui.button_close_tab.hide()
|
|
1183
|
-
icon=QPixmap(''+ icons_path +'news.png')
|
|
1184
|
-
self.logChanges.ui.icon.setPixmap(icon)
|
|
1185
|
-
self.logChanges.setWindowIcon(self.windowIcon())
|
|
1186
|
-
self.logChanges.setWindowTitle(title)
|
|
1187
|
-
self.logChanges.ui.name_tab.setText(title)
|
|
1188
|
-
|
|
1189
|
-
self.logChanges.ui.log.setLineWrapColumnOrWidth(self.logChanges.ui.log.width()-20)
|
|
1190
|
-
self.logChanges.ui.log.setStyleSheet("")
|
|
1191
|
-
|
|
1192
|
-
def setFontPixelSize(logChanges:type(self.logChanges),fPixSize):
|
|
1193
|
-
logfont=self.font()
|
|
1194
|
-
logfont.setFamily(fontName)
|
|
1195
|
-
logfont.setPixelSize(fPixSize+2)
|
|
1196
|
-
logChanges.ui.log.setFont(logfont)
|
|
1197
|
-
fPixSize_TabNames=min([fPixSize*2,30])
|
|
1198
|
-
lab=logChanges.ui.name_tab
|
|
1199
|
-
font=lab.font()
|
|
1200
|
-
font.setPixelSize(fPixSize_TabNames)
|
|
1201
|
-
lab.setFont(font)
|
|
1202
|
-
self.logChanges.setFontPixelSize=lambda fS: setFontPixelSize(self.logChanges,fS)
|
|
1203
|
-
self.logChanges.setFontPixelSize(self.TABpar.fontPixelSize)
|
|
1204
|
-
def logResizeEvent(logChanges:type(self.logChanges),e):
|
|
1205
|
-
super(type(logChanges),logChanges).resizeEvent(e)
|
|
1206
|
-
logChanges.ui.log.setLineWrapColumnOrWidth(logChanges.ui.log.width()-20)
|
|
1207
|
-
self.logChanges.ui.log.resizeEvent=lambda e: logResizeEvent(self.logChanges,e)
|
|
1208
|
-
|
|
1209
|
-
self.logChanges.ui.icon.addfuncclick['whatsnew']=self.whatsNew
|
|
1210
|
-
self.logChanges.ui.icon.setCustomCursor()
|
|
1211
|
-
|
|
1212
|
-
try:
|
|
1213
|
-
file = open(filename, "rb")
|
|
1214
|
-
content = file.read().decode("utf-8")
|
|
1215
|
-
self.logChanges.ui.log.setText(content)
|
|
1216
|
-
file.close()
|
|
1217
|
-
except Exception as inst:
|
|
1218
|
-
pri.Error.red(f'There was a problem while reading the file {filename}:\n{inst}')
|
|
1219
|
-
self.logChanges.ui.log.setText(f'No information about PaIRS-UniNa updates available!\n\nSorry for this, try to reinstall PaIRS-UniNa or alternatively contact the authors at {__mail__}.')
|
|
1220
|
-
return
|
|
1221
|
-
|
|
1222
1174
|
import webbrowser
|
|
1223
1175
|
def downloadExampleData(self,url):
|
|
1224
1176
|
Message=f'Test data are available at the following link:\n{url}'
|
|
@@ -1354,7 +1306,7 @@ def checkRequiredPackages(self, filename=rqrdpckgs_filename, FlagDisplay=False,
|
|
|
1354
1306
|
else:
|
|
1355
1307
|
pri.Error.red(f"Malformed line: {line}")
|
|
1356
1308
|
|
|
1357
|
-
|
|
1309
|
+
FlagUpdateFile = False
|
|
1358
1310
|
warnings = []
|
|
1359
1311
|
|
|
1360
1312
|
for i, pkg in enumerate(required_packages):
|
|
@@ -1364,9 +1316,10 @@ def checkRequiredPackages(self, filename=rqrdpckgs_filename, FlagDisplay=False,
|
|
|
1364
1316
|
installed_version = None
|
|
1365
1317
|
|
|
1366
1318
|
# Update current installed version
|
|
1367
|
-
if installed_version is not None
|
|
1368
|
-
vcurr_list[i]
|
|
1369
|
-
|
|
1319
|
+
if installed_version is not None:
|
|
1320
|
+
if installed_version != vcurr_list[i]:
|
|
1321
|
+
vcurr_list[i] = installed_version
|
|
1322
|
+
FlagUpdateFile = True
|
|
1370
1323
|
|
|
1371
1324
|
# Check if within [vmin, vmax]
|
|
1372
1325
|
if not (le_ver(vmin_list[i],installed_version) and le_ver(installed_version,vmax_list[i])):
|
|
@@ -1381,7 +1334,7 @@ def checkRequiredPackages(self, filename=rqrdpckgs_filename, FlagDisplay=False,
|
|
|
1381
1334
|
|
|
1382
1335
|
# Show warning
|
|
1383
1336
|
if len(warnings)>0: self.FlagPackIssue=True
|
|
1384
|
-
if len(warnings)>0 or FlagForcePrint:
|
|
1337
|
+
if ( (FlagUpdateFile or FlagDisplay) and len(warnings)>0 ) or FlagForcePrint :
|
|
1385
1338
|
message = (
|
|
1386
1339
|
"Some installed packages have a version outside the target range used to develop "
|
|
1387
1340
|
"the current release of the PaIRS_UniNa package.\n\n"
|
|
@@ -1413,7 +1366,7 @@ def checkRequiredPackages(self, filename=rqrdpckgs_filename, FlagDisplay=False,
|
|
|
1413
1366
|
warningDialog(self, Message="All installed packages are within the expected version range.", flagScreenCenter=True,pixmap=icons_path+'greenv.png')
|
|
1414
1367
|
|
|
1415
1368
|
# Update file if needed
|
|
1416
|
-
if
|
|
1369
|
+
if FlagUpdateFile:
|
|
1417
1370
|
with open(filename, "w") as f:
|
|
1418
1371
|
for pkg, vmin, vmax, vcurr in zip(required_packages, vmin_list, vmax_list, vcurr_list):
|
|
1419
1372
|
f.write(f"{pkg}\t{vmin}\t{vmax}\t{vcurr if vcurr else 0}\n")
|
PaIRS_UniNa/Process_Tab.py
CHANGED
|
@@ -735,13 +735,12 @@ class Process_Tab(gPaIRS_Tab):
|
|
|
735
735
|
message="Please, insert at least one element!"
|
|
736
736
|
else:
|
|
737
737
|
message="Items must be inserted in decreasing order!"
|
|
738
|
-
wlab.setToolTip(message)
|
|
739
|
-
wlab.setStatusTip(message)
|
|
740
|
-
"""
|
|
741
|
-
QToolTip.showText(QCursor.pos(),wlab.toolTip(),wedit,QRect(),3000)
|
|
742
|
-
"""
|
|
743
738
|
else:
|
|
744
739
|
wlab.setPixmap(QPixmap())
|
|
740
|
+
message=""
|
|
741
|
+
show_mouse_tooltip(wedit,message)
|
|
742
|
+
wlab.setToolTip(message)
|
|
743
|
+
wlab.setStatusTip(message)
|
|
745
744
|
self.PROpar.VectFlag[self.Vect_widgets.index(wedit)]=not FlagError
|
|
746
745
|
return split_text, vect, FlagError
|
|
747
746
|
|
|
@@ -1292,18 +1291,25 @@ class Process_Tab(gPaIRS_Tab):
|
|
|
1292
1291
|
def line_edit_IW_action(self):
|
|
1293
1292
|
text=self.ui.line_edit_IW.text()
|
|
1294
1293
|
split_text=re.split(r'(\d+)', text)[1:-1:2]
|
|
1295
|
-
|
|
1296
|
-
|
|
1294
|
+
if len(split_text)!=4:
|
|
1295
|
+
message="Please insert four distinct values to edit the current PIV process iteration!"
|
|
1296
|
+
show_mouse_tooltip(self,message)
|
|
1297
|
+
self.line_edit_IW_set()
|
|
1298
|
+
else:
|
|
1299
|
+
vect=[int(split_text[i]) for i in (0,2,1,3)]
|
|
1297
1300
|
k=self.PROpar.row
|
|
1298
1301
|
FlagValid=True
|
|
1299
1302
|
if k>0: FlagValid=FlagValid and all([vect[i]<=self.PROpar.Vect[i][k-1] for i in range(4)])
|
|
1300
1303
|
if k<self.PROpar.Nit-1 and FlagValid: FlagValid=FlagValid and all([vect[i]>=self.PROpar.Vect[i][k+1] for i in range(4)])
|
|
1301
1304
|
if FlagValid:
|
|
1305
|
+
message=""
|
|
1306
|
+
show_mouse_tooltip(self,message)
|
|
1302
1307
|
for i in range(4):
|
|
1303
1308
|
self.PROpar.Vect[i][k]=vect[i] #np.array([vect[i]])
|
|
1304
1309
|
else:
|
|
1305
|
-
message='IW sizes
|
|
1306
|
-
|
|
1310
|
+
message='IW sizes or spacings were assigned inconsistently! They must be inserted in decreasing order across iterations. Please, retry!'
|
|
1311
|
+
show_mouse_tooltip(self,message)
|
|
1312
|
+
self.line_edit_IW_set()
|
|
1307
1313
|
self.PROpar.flag_rect_wind=any([v!=w for v,w in zip(self.PROpar.Vect[0],self.PROpar.Vect[2])]) or any([v!=w for v,w in zip(self.PROpar.Vect[1],self.PROpar.Vect[3])])
|
|
1308
1314
|
return
|
|
1309
1315
|
|
|
@@ -1329,6 +1335,7 @@ class Process_Tab(gPaIRS_Tab):
|
|
|
1329
1335
|
item=table_iter.currentItem()
|
|
1330
1336
|
if not item: return
|
|
1331
1337
|
menu=QMenu(table_iter)
|
|
1338
|
+
menu.setStyleSheet(self.gui.ui.menu.styleSheet())
|
|
1332
1339
|
buttons=['add', 'delete']
|
|
1333
1340
|
name=[]
|
|
1334
1341
|
tips=['Add new iteration to the PIV process','Delete current iteration from the PIV process']
|
|
@@ -1361,10 +1368,7 @@ class Process_Tab(gPaIRS_Tab):
|
|
|
1361
1368
|
item.setStatusTip('')
|
|
1362
1369
|
|
|
1363
1370
|
message='No context menu available! Please, pause processing.'
|
|
1364
|
-
|
|
1365
|
-
self.setToolTipDuration(3000)
|
|
1366
|
-
QToolTip.showText(QCursor.pos(),message)
|
|
1367
|
-
self.setToolTipDuration(toolTipDuration)
|
|
1371
|
+
show_mouse_tooltip(self,message)
|
|
1368
1372
|
item.setToolTip(toolTip)
|
|
1369
1373
|
item.setStatusTip(toolTip)
|
|
1370
1374
|
|
|
@@ -1688,13 +1692,13 @@ class Process_Tab(gPaIRS_Tab):
|
|
|
1688
1692
|
FlagStable=FlagStable and not flagUnstable
|
|
1689
1693
|
if k==self.PROpar.Nit-1:
|
|
1690
1694
|
if j==0:
|
|
1691
|
-
if self.father and hasattr(self.father,'
|
|
1695
|
+
if self.father and hasattr(self.father,'w_Output'): Res=self.father.w_Output.OUTpar.xres
|
|
1692
1696
|
else: Res=0
|
|
1693
1697
|
self.MTF=[lam,MTF.T,f'IW size-spacing: {Wa:d}-{Wc:d}. Vel.-correl. windowing: {VelWin}-{CorrWin}.',Res]
|
|
1694
1698
|
|
|
1695
1699
|
else:
|
|
1696
1700
|
if self.PROpar.Vect[j*2][kVect]>self.PROpar.Vect[(j-1)*2][kVect]:
|
|
1697
|
-
if self.father: Res=self.father.
|
|
1701
|
+
if self.father: Res=self.father.w_Output.OUTpar.xres*self.father.w_Output.OUTpar.pixAR
|
|
1698
1702
|
else: Res=0
|
|
1699
1703
|
self.MTF=[lam,MTF.T,f'IW size-spacing: {Wa:d}-{Wc:d}. Vel.-correl. windowing: {VelWin}-{CorrWin}.',Res]
|
|
1700
1704
|
if FlagStable:
|
PaIRS_UniNa/Process_Tab_Disp.py
CHANGED
|
@@ -134,15 +134,22 @@ class Process_Tab_Disp(gPaIRS_Tab):
|
|
|
134
134
|
def line_edit_IW_action(self):
|
|
135
135
|
text=self.ui.line_edit_IW.text()
|
|
136
136
|
split_text=re.split(r'(\d+)', text)[1:-1:2]
|
|
137
|
+
if len(split_text)==0:
|
|
138
|
+
message="Please insert at least one value!"
|
|
139
|
+
show_mouse_tooltip(self,message)
|
|
140
|
+
self.line_edit_IW_set()
|
|
141
|
+
return
|
|
137
142
|
split_num=[int(t) for t in split_text]
|
|
138
143
|
if len(split_num)<4: split_num+=[split_num[-1]]*(4-len(split_num))
|
|
139
144
|
vect=[int(split_num[i]) for i in (0,2,1,3)]
|
|
140
145
|
FlagValid=len(vect)==4 and all([v>0 for v in vect])
|
|
141
146
|
if FlagValid:
|
|
142
147
|
self.PROpar.Vect=vect
|
|
148
|
+
message=""
|
|
143
149
|
else:
|
|
144
150
|
message='IW sizes or spacings were assigned inconsistently! Please, retry!'
|
|
145
|
-
|
|
151
|
+
show_mouse_tooltip(self,message)
|
|
152
|
+
self.line_edit_IW_set()
|
|
146
153
|
return
|
|
147
154
|
|
|
148
155
|
#******************** Settings
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from PySide6 import QtWidgets, QtGui, QtCore
|
|
2
|
+
import sys
|
|
3
|
+
from .PaIRS_pypacks import icons_path, fontPixelSize
|
|
4
|
+
|
|
5
|
+
def showSPIVCalHelp(parent=None,disable_callback=None):
|
|
6
|
+
"""
|
|
7
|
+
Shows an informational dialog explaining the correct calibration setup
|
|
8
|
+
for stereoscopic PIV in PaIRS, ensuring compatibility with disparity
|
|
9
|
+
correction and full stereoscopic reconstruction.
|
|
10
|
+
"""
|
|
11
|
+
dlg = QtWidgets.QDialog(parent)
|
|
12
|
+
dlg.setWindowTitle("Guidelines for stereoscopic PIV calibration")
|
|
13
|
+
#dlg.resize(900, 750)
|
|
14
|
+
dlg.setMinimumWidth(900)
|
|
15
|
+
dlg.setMinimumHeight(750)
|
|
16
|
+
|
|
17
|
+
main_layout = QtWidgets.QVBoxLayout(dlg)
|
|
18
|
+
|
|
19
|
+
# --- Explanatory text (English, corrected axes) ---
|
|
20
|
+
text = (
|
|
21
|
+
"For stereoscopic PIV, PaIRS assumes that:<br><br>"
|
|
22
|
+
|
|
23
|
+
" • the <b>calibration plate defines "
|
|
24
|
+
"the x–y plane</b> of the calibration coordinate system;<br>"
|
|
25
|
+
|
|
26
|
+
" • the <b>x-axis</b> is <b>aligned with the stereoscopic baseline</b>, i.e. "
|
|
27
|
+
"the direction along which the projections of the two camera viewing rays diverge "
|
|
28
|
+
"on the calibration plate (the dominant disparity direction);<br>"
|
|
29
|
+
|
|
30
|
+
" • the <b>y-axis</b> is then defined as the axis <b>perpendicular to the plane containing "
|
|
31
|
+
"the two cameras</b> (i.e. perpendicular to the triangulation plane formed by the two "
|
|
32
|
+
"optical axes);<br>"
|
|
33
|
+
|
|
34
|
+
" • the <b>z-axis is normal to the plate</b> (typically pointing towards the cameras).<br><br>"
|
|
35
|
+
|
|
36
|
+
"To ensure full compatibility with the operations performed in the disparity correction step and the stereoscopic reconstruction,"
|
|
37
|
+
" the calibration procedure must always adhere to the above coordinate convention.<br>"
|
|
38
|
+
" The example below shows a <b>correct</b> configuration (left) and an <b>incorrect</b> one (right).<br>"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
text_label = QtWidgets.QLabel()
|
|
42
|
+
text_label.setWordWrap(True)
|
|
43
|
+
text_label.setTextFormat(QtCore.Qt.RichText)
|
|
44
|
+
text_label.setText(f"<div>{text}</div>")
|
|
45
|
+
main_layout.addWidget(text_label)
|
|
46
|
+
font=dlg.font()
|
|
47
|
+
font.setPixelSize(fontPixelSize+4)
|
|
48
|
+
text_label.setFont(font)
|
|
49
|
+
|
|
50
|
+
# --- Side-by-side images ---
|
|
51
|
+
img_layout = QtWidgets.QHBoxLayout()
|
|
52
|
+
img_layout.setSpacing(10)
|
|
53
|
+
main_layout.addLayout(img_layout)
|
|
54
|
+
|
|
55
|
+
# Paths to images (adjust to match PaIRS resources folder)
|
|
56
|
+
img_ok_path = icons_path+"spiv_setup_ok.png"
|
|
57
|
+
img_no_path = icons_path+"spiv_setup_no.png"
|
|
58
|
+
|
|
59
|
+
# --- Correct configuration image ---
|
|
60
|
+
ok_widget = QtWidgets.QVBoxLayout()
|
|
61
|
+
ok_caption = QtWidgets.QLabel()
|
|
62
|
+
caption_text = "<b>Correct configuration (x–z stereo plane)</b>"
|
|
63
|
+
ok_caption.setText(f"<div>{caption_text}</div>")
|
|
64
|
+
ok_caption.setFont(font)
|
|
65
|
+
ok_caption.setTextFormat(QtCore.Qt.RichText)
|
|
66
|
+
ok_caption.setAlignment(QtCore.Qt.AlignCenter)
|
|
67
|
+
|
|
68
|
+
ok_label_img = QtWidgets.QLabel()
|
|
69
|
+
ok_label_img.setAlignment(QtCore.Qt.AlignCenter)
|
|
70
|
+
ok_label_img.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
|
71
|
+
ok_label_img.setScaledContents(True)
|
|
72
|
+
|
|
73
|
+
ok_pix = QtGui.QPixmap(img_ok_path)
|
|
74
|
+
if not ok_pix.isNull():
|
|
75
|
+
ok_pix = ok_pix.scaledToWidth(400, QtCore.Qt.SmoothTransformation)
|
|
76
|
+
ok_label_img.setPixmap(ok_pix)
|
|
77
|
+
ok_label_img.setFixedSize(ok_pix.width(),ok_pix.height())
|
|
78
|
+
|
|
79
|
+
ok_widget.addWidget(ok_caption)
|
|
80
|
+
ok_widget.addWidget(ok_label_img)
|
|
81
|
+
img_layout.addLayout(ok_widget)
|
|
82
|
+
|
|
83
|
+
# --- Incorrect configuration image ---
|
|
84
|
+
no_widget = QtWidgets.QVBoxLayout()
|
|
85
|
+
no_caption = QtWidgets.QLabel()
|
|
86
|
+
caption_text = "<b>Incorrect configuration</b>"
|
|
87
|
+
no_caption.setText(f"<div'>{caption_text}</div>")
|
|
88
|
+
no_caption.setFont(font)
|
|
89
|
+
no_caption.setTextFormat(QtCore.Qt.RichText)
|
|
90
|
+
no_caption.setAlignment(QtCore.Qt.AlignCenter)
|
|
91
|
+
|
|
92
|
+
no_label_img = QtWidgets.QLabel()
|
|
93
|
+
no_label_img.setAlignment(QtCore.Qt.AlignCenter)
|
|
94
|
+
no_label_img.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
|
95
|
+
no_label_img.setScaledContents(True)
|
|
96
|
+
|
|
97
|
+
no_pix = QtGui.QPixmap(img_no_path)
|
|
98
|
+
if not no_pix.isNull():
|
|
99
|
+
no_pix = no_pix.scaledToWidth(400, QtCore.Qt.SmoothTransformation)
|
|
100
|
+
no_label_img.setPixmap(no_pix)
|
|
101
|
+
no_label_img.setFixedSize(no_pix.width(),no_pix.height())
|
|
102
|
+
|
|
103
|
+
no_widget.addWidget(no_caption)
|
|
104
|
+
no_widget.addWidget(no_label_img)
|
|
105
|
+
img_layout.addLayout(no_widget)
|
|
106
|
+
|
|
107
|
+
# Prevent bottom clipping: allow images row to shrink/expand as needed
|
|
108
|
+
main_layout.setStretch(0, 1)
|
|
109
|
+
main_layout.setStretch(1, 0)
|
|
110
|
+
|
|
111
|
+
# Create a horizontal layout for buttons
|
|
112
|
+
button_layout = QtWidgets.QHBoxLayout()
|
|
113
|
+
|
|
114
|
+
# Spacer pushes OK to the right
|
|
115
|
+
button_layout.addStretch(1)
|
|
116
|
+
|
|
117
|
+
# Left button
|
|
118
|
+
if disable_callback is not None:
|
|
119
|
+
button_disable = QtWidgets.QPushButton("Don't show this message again")
|
|
120
|
+
def on_disable():
|
|
121
|
+
disable_callback()
|
|
122
|
+
dlg.accept()
|
|
123
|
+
button_disable.clicked.connect(on_disable)
|
|
124
|
+
button_layout.addWidget(button_disable)
|
|
125
|
+
|
|
126
|
+
# Right button (OK)
|
|
127
|
+
button_ok = QtWidgets.QPushButton("OK")
|
|
128
|
+
def on_ok():
|
|
129
|
+
dlg.accept()
|
|
130
|
+
button_ok.clicked.connect(on_ok)
|
|
131
|
+
button_layout.addWidget(button_ok)
|
|
132
|
+
|
|
133
|
+
# Add the layout to the dialog
|
|
134
|
+
main_layout.addSpacing(12)
|
|
135
|
+
main_layout.addLayout(button_layout)
|
|
136
|
+
|
|
137
|
+
button_ok.setDefault(True)
|
|
138
|
+
button_ok.setFocus()
|
|
139
|
+
|
|
140
|
+
main_layout.setContentsMargins(20, 25, 20, 25) # slightly larger bottom margin to avoid macOS clipping
|
|
141
|
+
|
|
142
|
+
dlg.exec()
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
# QApplication MUST be created before any QWidget
|
|
146
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
147
|
+
|
|
148
|
+
# Parent window (optional)
|
|
149
|
+
main_window = QtWidgets.QMainWindow()
|
|
150
|
+
main_window.show()
|
|
151
|
+
|
|
152
|
+
# Show the SPIV calibration dialog
|
|
153
|
+
showSPIVCalHelp(parent=main_window)
|
|
154
|
+
|
|
155
|
+
sys.exit(app.exec())
|