PaIRS-UniNa 0.2.5__cp311-cp311-win_amd64.whl → 0.2.7__cp311-cp311-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/Changes.txt CHANGED
@@ -1,4 +1,29 @@
1
- ********* Changes in version 0.2.5 (2025.07.18) **********
1
+ ********* Changes in version 0.2.7 (2025.10.13) **********
2
+ Bug fixes:
3
+ - resolved an issue related to visulazion of streamlines when the image is shown in pixel units and a custom resolution is specified (in previous versions, streamlines were always represented in physical units);
4
+ - corrected the update of reprojection errors in CalVi when the control point grid is expanded after a calibration. Each new control point now has its error recalculated and plotted, providing a correct view of the extrapolation error;
5
+ - fixed the automatic resize/reshape behavior specified in the Output tab: when an image transformation is assigned, it is now preserved even if the automatic reshape button is active.
6
+
7
+ User-interface enhancements:
8
+ - changed the behavior of the Vis button for restricting view on the interrogation window area: clicking it now opens a popup menu that allows users to select the desired interrogation-window size to focus on among all iterations of the process;
9
+ - names of processes duplicated in the process tree are now automatically updated to avoid conflicts: if a name already exists, the new one is appended with an incremental suffix;
10
+ - improved interaction with editable input fields: when hovering the highlighted style is displayed correctly, the text cursor now appears exactly where clicked and the background color is properly restored when leaving the field.
11
+
12
+
13
+
14
+ ********* Changes in version 0.2.6 (2025.09.06) **********
15
+ Bug fixes:
16
+ - fixed bugs related to process tree management.
17
+
18
+ User-interface enhancements:
19
+ - enhanced release check using SSL for reliable retrieval of the latest version.
20
+
21
+ Distribution:
22
+ - ready-to-use executables of PaIRS are now available!
23
+
24
+
25
+
26
+ ********* Changes in version 0.2.5 (2025.07.28) **********
2
27
  Bug fixes:
3
28
  - fixed bugs in launching PIV and stereoscopic PIV processes in special cases;
4
29
  - fixed tooltip crash introduced by PySide 6.9;
@@ -17,7 +42,7 @@ User-interface enhancements:
17
42
 
18
43
  Distribution:
19
44
  - Support for Python 3.9 has been discontinued;
20
- - Python 3.13 builds have been successfully created and tested.
45
+ - Python 3.13 builds have been successfully created and tested in Windows.
21
46
 
22
47
 
23
48
 
PaIRS_UniNa/Explorer.py CHANGED
@@ -1318,7 +1318,7 @@ class ProcessTree(PaIRSTree):
1318
1318
  par.ind[1]=int(self.FlagBin)
1319
1319
  par.ind[2]=i
1320
1320
  except Exception as inst:
1321
- pri.Error.red(inst)
1321
+ pri.Error.red(f"{inst}\n{traceback.format_exc()}")
1322
1322
  pass
1323
1323
  if hasattr(self.gui,'setLinks'):
1324
1324
  inds_new_list=list(inds_new)
@@ -1383,7 +1383,7 @@ class ProcessTree(PaIRSTree):
1383
1383
  if self.FlagExternalDrag:
1384
1384
  self.FlagExternalDrag=False
1385
1385
  self.dragged_items=None
1386
- self.setStyleSheet("")
1386
+ self.setStyleSheet(self.initialStyleSheet)
1387
1387
  if self.parent(): self.setPalette(self.parent().palette())
1388
1388
  self.hovered_item=None
1389
1389
 
@@ -1424,7 +1424,7 @@ class ProcessTree(PaIRSTree):
1424
1424
  if not self.widgets: return
1425
1425
  for w in self.widgets:
1426
1426
  w:gPaIRS_Tab
1427
- w.gen_TABpar(ITE.ind,FlagEmptyPrev=True,FlagInsert=3,Process=ITE.Process,Step=ITE.Step)
1427
+ w.gen_TABpar(ITE.ind,FlagEmptyPrev=True,FlagInsert=2,Process=ITE.Process,Step=ITE.Step)
1428
1428
  pass
1429
1429
  return
1430
1430
 
@@ -1434,11 +1434,11 @@ class ProcessTree(PaIRSTree):
1434
1434
  if t in self.widgetNames:
1435
1435
  k=self.widgetNames.index(t)
1436
1436
  w:gPaIRS_Tab=self.widgets[k]
1437
- w.gen_TABpar(ITE.ind,FlagInsert=4,Process=ITE.Process,Step=ITE.Step)
1437
+ w.gen_TABpar(ITE.ind,FlagInsert=3,Process=ITE.Process,Step=ITE.Step)
1438
1438
  pass
1439
1439
  for w, wn in zip(self.widgets,self.widgetNames):
1440
1440
  if wn not in ITE.tabs+['TabArea']:
1441
- w.gen_TABpar(ITE.ind,FlagNone=True,FlagInsert=4,Process=ITE.Process,Step=ITE.Step)
1441
+ w.gen_TABpar(ITE.ind,FlagNone=True,FlagInsert=3,Process=ITE.Process,Step=ITE.Step)
1442
1442
  pass
1443
1443
  return
1444
1444
 
@@ -1697,10 +1697,14 @@ class ProcessTree(PaIRSTree):
1697
1697
  if errorString:
1698
1698
  if '_data' in filename:
1699
1699
  try:
1700
+ errorString=''
1700
1701
  basename,ext=os.path.splitext(filename)
1701
1702
  filename2=basename[:-5]+ext
1702
1703
  data, errorMessage=loadList(filename2)
1703
- errorString=errorString+errorMessage if errorMessage else ''
1704
+ #errorString=errorString+errorMessage if errorMessage else ''
1705
+ if errorMessage:
1706
+ WarningMessage="It was not possible to determine which process the selected data file belongs to.\nPlease, try again by loading the process output file directly."
1707
+ warningDialog(self,WarningMessage)
1704
1708
  except Exception as inst2:
1705
1709
  errorString+=str(inst2)
1706
1710
  FlagError=True
@@ -1855,11 +1859,20 @@ class ProcessTree(PaIRSTree):
1855
1859
  if not self.FlagCutted and not FlagPasteDeleted:
1856
1860
  self.cutItems(new_items)
1857
1861
  self.pasteLists(row,FlagPasteDeleted)
1858
- for k in indexes:
1859
- item=self.topLevelItem(k)
1860
- ITEs=self.itemList[0][k]
1861
- self.setProcessItemWidget(item,ITEs[0]) # Set the widget container as the
1862
- self.setStepItemWidgets(item,ITEs[0].ind[2])
1862
+ name_list=[i[0].name for i in self.itemList[0]]
1863
+ for pos,k in enumerate(indexes):
1864
+ item=self.topLevelItem(k)
1865
+ ITE=self.itemList[0][k][0]
1866
+ tail=set(indexes[pos:]);
1867
+ forbidden={name_list[j] for j in range(len(name_list)) if j not in tail}
1868
+ if ITE.name in forbidden:
1869
+ base=ITE.name
1870
+ n=1
1871
+ while f"{base} ({n})" in forbidden: n+=1
1872
+ ITE.name=f"{base} ({n})"
1873
+ name_list[k]=ITE.name
1874
+ self.setProcessItemWidget(item,ITE)
1875
+ self.setStepItemWidgets(item,ITE.ind[2])
1863
1876
 
1864
1877
  self.scrollToItem(firstItemToScroll)
1865
1878
  self.scrollToItem(lastItemToScroll)
@@ -1938,6 +1951,9 @@ class ProcessTree(PaIRSTree):
1938
1951
 
1939
1952
  TABname=self.gui.w_Input.TABname
1940
1953
  self.gui.bridge(TABname,ind_new)
1954
+
1955
+ FlagSettingPar=TABpar.FlagSettingPar
1956
+ TABpar.FlagSettingPar=True
1941
1957
  for w in self.gui.tabWidgets:
1942
1958
  w:gPaIRS_Tab
1943
1959
  if w!=self.gui.w_Input:
@@ -1949,6 +1965,7 @@ class ProcessTree(PaIRSTree):
1949
1965
  w.adjustTABparInd()
1950
1966
  w.TABpar.copyfrom(currpar)
1951
1967
  self.gui.bridge(w.TABname,ind_new)
1968
+ TABpar.FlagSettingPar=FlagSettingPar
1952
1969
  #item_child=item.child(j)
1953
1970
  #item_child.setSelected(True)
1954
1971
  #self.setCurrentItem(item_child)
PaIRS_UniNa/Input_Tab.py CHANGED
@@ -102,9 +102,9 @@ class INPpar(TABpar):
102
102
  self.frame_2 = [-1]
103
103
  self.inp_ncam = 3 if Process==ProcessTypes.tpiv else 2 if Process==ProcessTypes.spiv else 1
104
104
  self.inp_cam = 1
105
- self.ind_in = -1
105
+ self.ind_in = 0
106
106
  self.npairs = 0
107
- self.step = 1
107
+ self.step = 0
108
108
  self.FlagTR_Import = False
109
109
 
110
110
  self.nExImTree = 3
@@ -197,6 +197,7 @@ class Input_Tab(gPaIRS_Tab):
197
197
 
198
198
  self.ImTreeInd=[]
199
199
  self.ui.imTreeWidget.imTree.signals.stopWorker.connect(self.emptyImTreeInd)
200
+ self.ui.imTreeWidget.FlagInGui=True
200
201
 
201
202
  self.FlagScanPath=False
202
203
  pri.Time.yellow('Input: define callbacks')
@@ -312,10 +313,10 @@ class Input_Tab(gPaIRS_Tab):
312
313
 
313
314
  self.ui.spin_inp_ncam.setEnabled(self.INPpar.FlagCam)
314
315
  self.ui.spin_inp_ncam.setMinimum(self.ncamMinimum())
315
- self.ui.imTreeWidget.spin_ncam.setEnabled(self.INPpar.FlagCam)
316
+ self.ui.imTreeWidget.spin_ncam.setEnabled(False)
316
317
  self.ui.imTreeWidget.FlagCam=self.INPpar.FlagCam
317
318
  self.ui.imTreeWidget.spin_ncam.setMinimum(self.ncamMinimum())
318
- self.ui.imTreeWidget.spin_ncam.setValue(self.INPpar.ncam)
319
+ self.ui.imTreeWidget.spin_ncam.setValue(self.INPpar.importPar.inp_ncam)
319
320
  self.ui.spin_inp_cam.setEnabled(self.INPpar.inp_ncam>1)
320
321
  self.ui.spin_inp_cam.setMaximum(self.INPpar.inp_ncam)
321
322
  self.setImageNumberSpinLimits()
@@ -418,6 +419,8 @@ class Input_Tab(gPaIRS_Tab):
418
419
  self.ui.line_edit_path.setText(currpath)
419
420
  self.INPpar.path=self.ui.line_edit_path.text()
420
421
  self.line_edit_path_preaction()
422
+ else:
423
+ currpath='./'
421
424
 
422
425
  def button_path_action_future(self):
423
426
  self.line_edit_path_action_future()
@@ -37,7 +37,7 @@ class INPpar_CalVi(TABpar):
37
37
  def __init__(self,Process=ProcessTypes.null,Step=StepTypes.null):
38
38
  self.setup(Process,Step)
39
39
  super().__init__('INPpar_CalVi','Input_CalVi')
40
- self.unchecked_fields+=['OptionValidPath','OptionValidPathOut','OptionValidRootOut','row','col','rows','cols']
40
+ self.unchecked_fields+=['OptionValidPath','OptionValidPathOut','OptionValidRootOut','row','col','rows','cols','pathCompleter']
41
41
 
42
42
  def setup(self,Process,Step):
43
43
  self.Process = Process
@@ -311,7 +311,7 @@ class Input_Tab_CalVi(gPaIRS_Tab):
311
311
 
312
312
  def line_edit_cameras_action(self):
313
313
  text=self.ui.line_edit_cameras.text()
314
- split_text=re.findall('(\d+)', text)
314
+ split_text=re.findall(r'(\d+)', text)
315
315
  self.INPpar.cams=[]
316
316
  for s in split_text:
317
317
  i=int(s)
@@ -365,7 +365,7 @@ class Input_Tab_CalVi(gPaIRS_Tab):
365
365
  f=os.path.basename(filename)
366
366
  FlagWarn=False
367
367
  if self.INPpar.FlagCam:
368
- fsplitted=re.split('_cam\d+', f)
368
+ fsplitted=re.split(r'_cam\d+', f)
369
369
  if len(fsplitted)>1:
370
370
  fsplitted.insert(-1,'_cam*')
371
371
  f="".join(fsplitted)
@@ -508,7 +508,7 @@ class Input_Tab_CalVi(gPaIRS_Tab):
508
508
  if self.INPpar.FlagCam and len(self.INPpar.cams)==0:
509
509
  ncam=0
510
510
  for f in self.INPpar.filenames:
511
- pats=re.findall('_cam\d+', f)
511
+ pats=re.findall(r'_cam\d+', f)
512
512
  if len(pats):
513
513
  ncam=int(pats[-1].replace("_cam",""))
514
514
  break
@@ -534,7 +534,7 @@ class Input_Tab_CalVi(gPaIRS_Tab):
534
534
  if self.INPpar.FlagCam:
535
535
  for k,f in enumerate(self.INPpar.filenames):
536
536
  if '_cam*' in f: continue
537
- fsplitted=re.split('_cam\d+', f)
537
+ fsplitted=re.split(r'_cam\d+', f)
538
538
  fsplitted.insert(-1,'_cam*')
539
539
  f="".join(fsplitted)
540
540
  self.INPpar.filenames[k]=f
@@ -18,11 +18,11 @@ class ImageSet(TABpar):
18
18
  self.lists=[f for f,v in self.__dict__.items() if type(v)==list]
19
19
  self.supported_exts = exts
20
20
  super().__init__('ImageSet','Input')
21
- self.unchecked_fields+=['signals','fname','fnumb']
21
+ self.unchecked_fields+=['signals','fname','fnumb','outFiles']
22
22
  if path: self.scanPath(path)
23
23
 
24
24
  def setup(self):
25
- self.path = ''
25
+ self.path = './'
26
26
  self.count = 0
27
27
  self.pattern = []
28
28
  self.pa = []
@@ -104,7 +104,7 @@ class ImageSet(TABpar):
104
104
 
105
105
  def addPattern(self,basename):
106
106
  _, ext = os.path.splitext(basename)
107
- split_basename=re.split('(\d+)', basename)
107
+ split_basename=re.split(r'(\d+)', basename)
108
108
  c=0
109
109
  for k,s in enumerate(split_basename):
110
110
  if not len(s): continue
@@ -172,7 +172,7 @@ class ImageSet(TABpar):
172
172
  while i<len(jl) and p2[diff[0]]<l[i]: i+=1
173
173
  jl.insert(i-1,j)
174
174
  l.insert(i-1,p2[diff[0]])
175
- self.link[k]=jalpha+jnumber+[k]
175
+ self.link[k]=jalpha+sorted(jnumber)+[k]
176
176
  return
177
177
 
178
178
  def print(self):
@@ -1604,6 +1604,7 @@ class ImageTreeWidget(QWidget):
1604
1604
  self.signals=self.ImageTreeWidget_signals()
1605
1605
  self.FlagSpinButtons=FlagSpinButtons
1606
1606
  self.FlagCam=True
1607
+ self.FlagInGui=False
1607
1608
 
1608
1609
  font=self.font()
1609
1610
  font.setItalic(True)
@@ -2208,7 +2209,7 @@ class ImageTreeWidget(QWidget):
2208
2209
  self.spin_cam.setStatusTip(self.spin_cam.toolTip())
2209
2210
  FlagSingleTree=type(self.imTree)==SingleImageTree
2210
2211
  self.spin_cam.setEnabled(self.imTree.ncam>1 and (self.imTree.nimg>1 or FlagSingleTree))
2211
- self.spin_ncam.setEnabled(not FlagSingleTree and self.FlagCam)
2212
+ self.spin_ncam.setEnabled(not FlagSingleTree and self.FlagCam and not self.FlagInGui)
2212
2213
 
2213
2214
  self.spin_frame.setToolTip(f'Current frame. Number of frames: {self.spin_frame.maximum()}')
2214
2215
  self.spin_frame.setStatusTip(self.spin_frame.toolTip())
PaIRS_UniNa/Output_Tab.py CHANGED
@@ -379,7 +379,7 @@ class Output_Tab(gPaIRS_Tab):
379
379
  self.OUTpar.root=myStandardRoot(self.OUTpar.root)
380
380
 
381
381
  if self.OUTpar.imageFile: self.OUTpar.W,self.OUTpar.H=self.get_image_dimensions(self.OUTpar.inputPath+self.OUTpar.imageFile)
382
- if (self.OUTpar_old.imageFile is None and self.OUTpar.W>0 and self.OUTpar.H>0) or (self.OUTpar.isDifferentFrom(self.OUTpar_old,fields=['W','H','inputPath']) and OUTpar.FlagAutoReshape):
382
+ if (self.OUTpar.isDifferentFrom(self.OUTpar_old,fields=['W','H','inputPath']) and self.OUTpar.ind[:-1]==self.OUTpar_old.ind[:-1] and OUTpar.FlagAutoReshape) or (self.OUTpar_old.imageFile is None and self.OUTpar.W>0 and self.OUTpar.H>0):
383
383
  self.button_resize_action()
384
384
  self.button_reset_rot_flip_action()
385
385