pyvale 2025.7.0__cp311-cp311-musllinux_1_2_aarch64.whl → 2025.7.2__cp311-cp311-musllinux_1_2_aarch64.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.

Potentially problematic release.


This version of pyvale might be problematic. Click here for more details.

@@ -84,6 +84,7 @@ class DICRegionOfInterest:
84
84
  self.height = None
85
85
  self.width = None
86
86
  self.subset_size = None
87
+ self.coord_label = None
87
88
 
88
89
  def interactive_selection(self, subset_size):
89
90
  """
@@ -117,6 +118,8 @@ class DICRegionOfInterest:
117
118
 
118
119
  # Create graphics widget
119
120
  self.graphics_widget = pg.GraphicsLayoutWidget()
121
+
122
+
120
123
 
121
124
  main_layout.addLayout(sidebar)
122
125
  main_layout.addWidget(self.graphics_widget)
@@ -165,7 +168,27 @@ class DICRegionOfInterest:
165
168
  self.buttons['undo_prev'].setEnabled(False)
166
169
  self.buttons['redo_prev'].setEnabled(False)
167
170
 
171
+ self.coord_label = QtWidgets.QLabel("(-, -)")
172
+ self.coord_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight)
173
+
174
+ # Set fixed width to handle largest expected value comfortably
175
+ self.coord_label.setMinimumWidth(350)
176
+ self.coord_label.setMaximumWidth(350)
177
+
178
+ self.coord_label.setStyleSheet("""
179
+ QLabel {
180
+ background-color: rgba(0, 0, 0, 150);
181
+ color: white;
182
+ padding: 5px;
183
+ border-radius: 3px;
184
+ font-family: monospace;
185
+ font-size: 12px;
186
+ }
187
+ """)
188
+
168
189
  sidebar.addStretch()
190
+ sidebar.addWidget(self.coord_label)
191
+
169
192
  return sidebar
170
193
 
171
194
  def _setup_graphics(self):
@@ -222,6 +245,24 @@ class DICRegionOfInterest:
222
245
  self.buttons[btn_id].clicked.connect(handler)
223
246
 
224
247
  self.main_view.scene().sigMouseClicked.connect(self._mouse_clicked)
248
+ self.main_view.scene().sigMouseMoved.connect(self._mouse_moved)
249
+
250
+
251
+ def _mouse_moved(self, pos):
252
+ """Handle mouse movement to update coordinate display."""
253
+ if self.main_view.sceneBoundingRect().contains(pos):
254
+ mouse_point = self.main_view.mapSceneToView(pos)
255
+ # Convert from graphics coordinates to image coordinates
256
+ img_x = int(round(mouse_point.x()))
257
+ img_y = int(round(self.width - mouse_point.y()))
258
+
259
+ # Clamp coordinates to image bounds
260
+ img_x = max(0, min(img_x, self.height - 1))
261
+ img_y = max(0, min(img_y, self.width - 1))
262
+
263
+ self.coord_label.setText(f"({img_x}, {img_y})")
264
+ else:
265
+ self.coord_label.setText("(-, -)")
225
266
 
226
267
  def _start_drawing_mode(self, mode):
227
268
  """Start drawing mode for specified shape type."""
@@ -536,7 +577,7 @@ class DICRegionOfInterest:
536
577
  self._update_button_states()
537
578
 
538
579
  def _save_interactive_roi(self):
539
- """Save the current ROI to a YAML file."""
580
+ """Save the current ROI to a YAML file. This only works with the interactive GUI."""
540
581
  filename, _ = QtWidgets.QFileDialog.getSaveFileName(self.main_window, 'Save ROI', 'roi_interactive.yaml', filter='YAML Files (*.yaml)')
541
582
 
542
583
  if filename:
@@ -566,7 +607,7 @@ class DICRegionOfInterest:
566
607
  yaml.dump(serialized, f, sort_keys=False)
567
608
 
568
609
  def _open_interactive_roi(self):
569
- """Open ROI from a YAML file."""
610
+ """Open ROI from a YAML file. This only works with the interactive GUI."""
570
611
  filename, _ = QtWidgets.QFileDialog.getOpenFileName(
571
612
  self.main_window, 'Open ROI', filter='YAML Files (*.yaml)'
572
613
  )
@@ -586,6 +627,7 @@ class DICRegionOfInterest:
586
627
  if entry.get('type') == 'SeedROI':
587
628
  # Restore the seed ROI
588
629
  x, y = entry['pos']
630
+ y = self.width-y
589
631
  size = entry.get('size', [10, 10]) # fallback default
590
632
  self.seed_roi = pg.RectROI(
591
633
  [x, y], size,
@@ -671,13 +713,13 @@ class DICRegionOfInterest:
671
713
  def _finalize_selection(self):
672
714
  """Process the final mask and seed location."""
673
715
  self.mask = np.flipud(self.temp_mask.T)
674
-
716
+
675
717
  if hasattr(self, 'seed_roi'):
676
718
  pos = self.seed_roi.pos()
677
719
  x = int(np.floor(pos.x()))
678
720
  y = int(np.floor(self.width - pos.y()))
679
721
  self.seed = [x, y]
680
-
722
+
681
723
  if not self.mask[y, x]:
682
724
  raise ValueError(f"Seed location [{x}, {y}] is not within the mask")
683
725
  print(f"Final seed location: [{x}, {y}]")
@@ -833,6 +875,111 @@ class DICRegionOfInterest:
833
875
  self.__roi_selected = True
834
876
 
835
877
 
878
+ def save_yaml(self, filename: str | Path) -> None:
879
+ """
880
+ Save the current ROI to a YAML file. This only works with the after having run the interactive GUI.
881
+
882
+ Parameters
883
+ ----------
884
+ filename : str or pathlib.Path
885
+ Filename of the YAML file to save the ROI data.
886
+
887
+ Raises
888
+ ------
889
+ ValueError
890
+ If no ROI has been selected.
891
+ """
892
+
893
+ if filename:
894
+
895
+ # Ensure extension is added if user doesn't include it
896
+ if filename and not filename.endswith('.yaml'):
897
+ filename += '.yaml'
898
+
899
+ print("Saving to file:", filename)
900
+ serialized = [
901
+ self._get_roi_data(roi, add)
902
+ for roi, add in zip(self.roi_list, self.add_list)
903
+ ]
904
+
905
+ # add ROI to serialized data
906
+ if hasattr(self, 'seed_roi'):
907
+ self._finalize_selection()
908
+ seed_data = {
909
+ 'type': 'SeedROI',
910
+ 'pos': [self.seed[0], self.seed[1]],
911
+ 'size': [self.subset_size, self.subset_size],
912
+ 'add': True
913
+ }
914
+ serialized.append(seed_data)
915
+
916
+ with open(filename, 'w') as f:
917
+ yaml.dump(serialized, f, sort_keys=False)
918
+
919
+ def read_yaml(self, filename: str | Path) -> None:
920
+ """
921
+ Load the ROI from a YAML file and restore the state of the GUI.
922
+ This method will clear existing ROIs and restore the state from the YAML file.
923
+
924
+ Parameters
925
+ ----------
926
+ filename : str or pathlib.Path
927
+ Path to the YAML file containing the ROI data.
928
+
929
+ Raises
930
+ ------
931
+ FileNotFoundError
932
+ If the specified file does not exist.
933
+ ValueError
934
+ If the loaded data is not a valid ROI format.
935
+ """
936
+
937
+ # need to create a temp qapplication so I can import the ROI.
938
+ self.__roi_selected = True
939
+
940
+ # Initialize GUI
941
+ self._setup_gui()
942
+ self._setup_graphics()
943
+ self._connect_signals()
944
+
945
+ if filename:
946
+ with open(filename, 'r') as f:
947
+ data = yaml.safe_load(f)
948
+
949
+ self.roi_list = []
950
+ self.add_list = []
951
+
952
+ self.seed_roi = None # Clear existing seed
953
+
954
+ for entry in data:
955
+ if entry.get('type') == 'SeedROI':
956
+ # Restore the seed ROI
957
+ x, y = entry['pos']
958
+ y = self.width-y
959
+ size = entry.get('size', [10, 10]) # fallback default
960
+ self.seed_roi = pg.RectROI(
961
+ [x, y], size,
962
+ pen=pg.mkPen('b', width=3),
963
+ hoverPen=pg.mkPen('y', width=3),
964
+ handlePen='#0000',
965
+ handleHoverPen='#0000'
966
+ )
967
+ self.main_view.addItem(self.seed_roi)
968
+
969
+ else:
970
+ # Restore standard ROI
971
+ roi = self._create_roi_from_data(entry)
972
+ self.roi_list.append(roi)
973
+ self.add_list.append(entry['add'])
974
+ self.main_view.addItem(roi)
975
+ roi.sigRegionChanged.connect(self._redraw_fill_layer)
976
+
977
+ self._redraw_fill_layer()
978
+ self._update_button_states()
979
+ self._finalize_selection()
980
+
981
+
982
+
836
983
  def show_image(self) -> None:
837
984
  """
838
985
  Displays the current mask in grayscale.
@@ -842,20 +989,30 @@ class DICRegionOfInterest:
842
989
  ValueError: If no ROI is selected.
843
990
  """
844
991
 
845
-
846
- if not self.__roi_selected:
847
- raise ValueError("No ROI selected with 'interactive_selection' or 'rect_boundary'")
992
+ # Convert grayscale image to 3-channel if needed
993
+ if self.ref_image.ndim == 2:
994
+ ref_image_color = cv2.cvtColor(self.ref_image.astype(np.uint8), cv2.COLOR_GRAY2BGR)
995
+ else:
996
+ ref_image_color = self.ref_image
848
997
 
849
998
  # Create a green mask image
850
- green_mask = np.zeros_like(self.ref_image)
999
+ if self.ref_image.ndim == 3:
1000
+ green_mask = np.zeros_like(self.ref_image)
1001
+ elif self.ref_image.ndim == 2:
1002
+ h, w = self.ref_image.shape
1003
+ green_mask = np.zeros((h, w, 3), dtype=self.ref_image.dtype)
1004
+ else:
1005
+ raise ValueError(f"Unsupported image shape: {self.ref_image.shape}")
851
1006
 
852
- green_mask[self.mask,:] = [0, 255, 0]
1007
+ # Apply the green mask
1008
+ green_mask[self.mask, :] = [0, 255, 0]
853
1009
 
854
- # Blend the original image and the mask
855
- blended = self.ref_image.astype(float) * 0.7 + green_mask.astype(float) * 0.3
1010
+ # Blend the original image and the green mask
1011
+ blended = ref_image_color.astype(float) * 0.7 + green_mask.astype(float) * 0.3
856
1012
  blended = blended.astype(np.uint8)
857
1013
 
858
1014
  # Display using Matplotlib
1015
+ import matplotlib.pyplot as plt
859
1016
  plt.figure()
860
1017
  plt.imshow(blended)
861
1018
  plt.axis('off')
pyvale/dicresults.py CHANGED
@@ -38,6 +38,8 @@ class DICResults:
38
38
  Final `xtol` value from the optimization routine, indicating solution tolerance.
39
39
  niter : np.ndarray
40
40
  Number of iterations taken to converge for each subset point.
41
+ shape_params : np.ndarray | None
42
+ Optional shape parameters if output during DIC calculation (e.g., affine, rigid).
41
43
  filenames : list[str]
42
44
  name of DIC result files that have been found
43
45
  """
@@ -52,4 +54,5 @@ class DICResults:
52
54
  ftol: np.ndarray
53
55
  xtol: np.ndarray
54
56
  niter: np.ndarray
57
+ shape_params: np.ndarray
55
58
  filenames: list[str]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyvale
3
- Version: 2025.7.0
3
+ Version: 2025.7.2
4
4
  Summary: An all-in-one package for sensor simulation, sensor uncertainty quantification, sensor placement optimisation and simulation calibration or validation.
5
5
  Author-email: "scepticalrabbit et al." <thescepticalrabbit@gmail.com>
6
6
  License: MIT License
@@ -14,13 +14,13 @@ pyvale/cameradata2d.py,sha256=O3imDz8BUer6Wxo82KzCQrVLIBDL5RLy8aNoQoKG4b0,2736
14
14
  pyvale/camerasensor.py,sha256=6T-9-bUK5_rLr_qg6VMi-u5gjifHWOMfIHqyqZxL9OQ,5332
15
15
  pyvale/camerastereo.py,sha256=a9rfswcwdiKRuj9Hs4GvIY3_LBuUjYn514wc_XmbCxk,9925
16
16
  pyvale/cameratools.py,sha256=fNulJWAcRpvPQN-TzoNLqCYxrdJFOs37ER4n3OANnJQ,19240
17
- pyvale/dataset.py,sha256=HOAQJ-UEN7yGyJ0Y-OdymneqEkIHBrgzPwGe0lEJrSs,14939
18
- pyvale/dic2d.py,sha256=DWFMOIf2n354iLlCxf-ruO9-_YeOAp1RFgQel4hhnmE,7567
19
- pyvale/dic2dcpp.cpython-311-aarch64-linux-musl.so,sha256=pcgazFcsjnYeTwuXzPSO3LR_pXgUlLOmTggWaarSDzs,55019857
20
- pyvale/dicchecks.py,sha256=HCgSUiOvGCKjdkASMSWL6DOhYuIN2-X7YLNxJs9fees,16012
21
- pyvale/dicdataimport.py,sha256=2hEGEeVTLQwpuQUxV-CVN_PsDgtDRK1v-xf5YuarOJk,7191
22
- pyvale/dicregionofinterest.py,sha256=RsSjd6ZjcghqpFxDkwmNbJmJ5s96Q7dL1SLNKUDWRbk,32881
23
- pyvale/dicresults.py,sha256=HGZTWNqCsdraUAJSNGYeAcm9ZJT38EeCeAjTYpcTksk,1883
17
+ pyvale/dataset.py,sha256=UfPlHXbFenMZuwUuv40Wr46b9GXHp9Gq8QUbJK2rkYg,14941
18
+ pyvale/dic2d.py,sha256=104AKgmectRIYcezbtFi0HMGS_DAG9JfKXAPAm6UCFQ,8607
19
+ pyvale/dic2dcpp.cpython-311-aarch64-linux-musl.so,sha256=NvxQfjw9IqGs-xZisQbaDnqelyqWDd5xYHKYrpyVYso,55872737
20
+ pyvale/dicchecks.py,sha256=IbmYlMjSbwL09DfaDE6-LuCRSkJ6DBL3OAA9HSApZQk,16753
21
+ pyvale/dicdataimport.py,sha256=YGUcs3LKTaIVCroIraT_D8mMA4mQF5M2yLrk93acHyI,11863
22
+ pyvale/dicregionofinterest.py,sha256=n92jEvOczoE4CPqzQA7lG7I-dsxlxLKa6qzILnDLlDg,38384
23
+ pyvale/dicresults.py,sha256=EIC4y0knc053AOepEEXeA_Z93HLbXW6OpX6XtwrsLYQ,2039
24
24
  pyvale/dicspecklegenerator.py,sha256=PohlSC13wZJZ4hOA5Z-GWML-MsN1pBTSA-pqtiLer8s,7819
25
25
  pyvale/dicspecklequality.py,sha256=soZKclWHSuwCsp_P4_EqDRbzTNw21n8rC8kv14i-NCU,9968
26
26
  pyvale/dicstrain.py,sha256=M4bjJaxb3orG3Ftv7P0BVCGnI8eThptns1FiNj8xVx4,12787
@@ -74,9 +74,11 @@ pyvale/visualsimplotter.py,sha256=m5mPIMGvSF4hhefTilkhBhii9t6rcoRKkqSdx5MugSs,68
74
74
  pyvale/visualsimsensors.py,sha256=hINsI73NQvHunJ3lUZX-F0RrN_u6gzF0tMHZwsxHr34,12405
75
75
  pyvale/visualtools.py,sha256=9nDMZHXv0N7HBl0vOL9QLeHlayYl6ng4dx2-5i2TJjw,4816
76
76
  pyvale/visualtraceplotter.py,sha256=y-GjToF5U2VIGO-YwR_tKi_vMUO3ayhaohaWrWNUFgQ,5487
77
- pyvale/cython/rastercyth.c,sha256=e_TrMLVWqlszlTagd9lh1LCZjMTdGzXTV0KAEc-ATR0,1250303
77
+ pyvale/cython/rastercyth.c,sha256=aWgzRZR_iBDpR0THvJzIhpXEdMWRXQeTZhkYLLYDXuo,1250303
78
78
  pyvale/cython/rastercyth.cpython-311-aarch64-linux-musl.so,sha256=H2tRXWYwlkJI6TSeBVlcwOtRkRceCv7mHWmjcvw1ZvM,1489472
79
79
  pyvale/cython/rastercyth.py,sha256=b-KJDysrc_LxBnWirXkNhKNy6jZ-d4xTFrXGSgDCp34,26411
80
+ pyvale/data/DIC_Challenge_Star_Noise_Def.tiff,sha256=no_q1L4_0plbVmg3TPEpgoRp3iLMrx2vH_X1fBwnLSw,2020090
81
+ pyvale/data/DIC_Challenge_Star_Noise_Ref.tiff,sha256=y0JSFyHvmO_cgabG8hOej5HioQ_9Bh7O8VYVTfVr_S8,2020102
80
82
  pyvale/data/__init__.py,sha256=h1zJBQZxFSPPUksp_ErTC1uTQLdSmoc-ry3D_naPKYE,271
81
83
  pyvale/data/cal_target.tiff,sha256=4dbDIm7h7gYDJOhWOZXO-rs162ZLqxb1bdrbTykMEMk,4718962
82
84
  pyvale/data/case00_HEX20_out.e,sha256=wTdEWvGyQBhP1D1bIy5YZKu7I_QISWLEjl9K9VOOnbI,241172
@@ -101,15 +103,16 @@ pyvale/data/plate_rigid_def0000.tiff,sha256=YlGU0lIlkh61StQku7lK7P6oDZDa-g5R98fU
101
103
  pyvale/data/plate_rigid_def0001.tiff,sha256=CFIveUYubbbUDpQfnsO0iPaBTzwbjQbcAOCG1mm2040,1601722
102
104
  pyvale/data/plate_rigid_ref0000.tiff,sha256=EolObMm5QzGeewgq3bLhlkHor_6ASuNoYrV2AbYrFro,1601722
103
105
  pyvale/dic/cpp/dicbruteforce.cpp,sha256=9Z9jx-K6_wgGX_Ezp1lf1ulqkLQ6X6EaOLwXAxw_Aeg,11915
104
- pyvale/dic/cpp/dicfourier.cpp,sha256=W3RjzqsbUpNSxfozObFJQnpcAGeqWcJpiSXKoaJr-cs,23548
105
- pyvale/dic/cpp/dicinterpolator.cpp,sha256=HkA_qKp70IePO6w50om13L5yqQqYDiYQD2V9i6klhhM,20325
106
- pyvale/dic/cpp/dicmain.cpp,sha256=qZvuC3m42Dg-_cjTVoh8dThtw6enqqTCvhIHSEKwvxA,8860
107
- pyvale/dic/cpp/dicoptimizer.cpp,sha256=krR7jLdLQEvX8iwNWjMKDseXu5Ka5szJTYrbcjOThak,25929
106
+ pyvale/dic/cpp/dicfourier.cpp,sha256=PSaUiDtu3pGOl_MVT5dL5cch-0pKUs2UwyqFiEn6wzE,24702
107
+ pyvale/dic/cpp/dicinterpolator.cpp,sha256=jAByBWInJuufTla4J5tDJledqr2fdmPj8lSZYPzraC0,21837
108
+ pyvale/dic/cpp/dicmain.cpp,sha256=_SaL_joDNs9hpybiirlG11KSsKaR_UqKuwzQOi__mcA,9049
109
+ pyvale/dic/cpp/dicoptimizer.cpp,sha256=k5oCFMvhC7sFu6qdmqbADQtPIsLIZhcDDnHW1OH80YU,26178
108
110
  pyvale/dic/cpp/dicrg.cpp,sha256=uicGKxOAgsTZgOpG18NDN-SoD0pJFu2wYGhP1Xg3S9U,4351
109
- pyvale/dic/cpp/dicscanmethod.cpp,sha256=MjzxECbRkn-fR211xJRDB4lsn-lf6dqHYXTOrLr2D-A,26766
111
+ pyvale/dic/cpp/dicscanmethod.cpp,sha256=tnMLTuO4pKKf_IDlWFWy2iwJ4Zndpv1pIvX_eu9_c50,27077
112
+ pyvale/dic/cpp/dicsignalhandler.cpp,sha256=MMcKGV7tsO6T6VS5vw0KJKhpfzPgaGAiwum6RPHPt2U,475
110
113
  pyvale/dic/cpp/dicsmooth.cpp,sha256=sKOyPTEBAcPzJjSc4jAl_JCLFBz5eJ8EXYh0iT7i0L4,4445
111
- pyvale/dic/cpp/dicstrain.cpp,sha256=wrcRcx_Jn5EvRLlXc_zVJ15VJVpRBHLLpMbcot8UOCM,14017
112
- pyvale/dic/cpp/dicutil.cpp,sha256=UEN3_Fm4gB_CRJY1wPvEUGGjjoBNwpPridPz32yPWPA,19829
114
+ pyvale/dic/cpp/dicstrain.cpp,sha256=-ObnJ3J1SCl8UAmzskQx_wNPOU5zMB5aNrJtNWnpVpg,14244
115
+ pyvale/dic/cpp/dicutil.cpp,sha256=Y4OAdLViEPlOSDSWoashXmqOmaPkD6TSyTiRDeWSw9Q,21695
113
116
  pyvale/examples/__init__.py,sha256=h1zJBQZxFSPPUksp_ErTC1uTQLdSmoc-ry3D_naPKYE,271
114
117
  pyvale/examples/basics/ex1_1_basicscalars_therm2d.py,sha256=tR8wGXoHUXaOCsJzSTFzgiTJpmoyVg6FCKoLnCmbq-4,5893
115
118
  pyvale/examples/basics/ex1_2_sensormodel_therm2d.py,sha256=ar7w73Nt1rjZiw8ma3nIf7rTbVHhmCRgAdcNLb7tlUg,5898
@@ -205,8 +208,8 @@ pyvale/simcases/run_example_cases.py,sha256=l5KOQvPMNRUkJMotaReG2nmrFtVBNWCwKVez
205
208
  pyvale.libs/libgcc_s-69c45f16.so.1,sha256=BOFjRP57t9LgRNNAnFVK5VHmrp5UU-p5NcfcZ10dnd4,201673
206
209
  pyvale.libs/libgomp-b626072d.so.1.0.0,sha256=0dyDmNGBMMrQqww_YKstjI7dawNUVm3HSzLzLfpYNh4,410617
207
210
  pyvale.libs/libstdc++-1f1a71be.so.6.0.33,sha256=sURAhanafc8tH6FGDqPKz7dsPGNb0Aym8vBo6UbJ3Ok,3650097
208
- pyvale-2025.7.0.dist-info/METADATA,sha256=2EMm9ruK8W9KOWxDCfRibI8tu5dGoemtS5voLp90V8U,6387
209
- pyvale-2025.7.0.dist-info/WHEEL,sha256=LNZuceeFd58B9QVekwESAWqB09LEv_tgGDcYQrpkG9U,113
210
- pyvale-2025.7.0.dist-info/top_level.txt,sha256=u1d_f4iZ3b3_96Rb_zrs9hyrpC4yE5e1Lg6Ey_Wgr0c,7
211
- pyvale-2025.7.0.dist-info/RECORD,,
212
- pyvale-2025.7.0.dist-info/licenses/LICENSE,sha256=h2qWsRIazuLLhALyUsCP6aE0DFcswL9SSSt9sgMzZi4,1099
211
+ pyvale-2025.7.2.dist-info/METADATA,sha256=oemYkdNkKrT7uGin03lIwtFXU-Ob_ayvIngcVz5RkxE,6387
212
+ pyvale-2025.7.2.dist-info/WHEEL,sha256=LNZuceeFd58B9QVekwESAWqB09LEv_tgGDcYQrpkG9U,113
213
+ pyvale-2025.7.2.dist-info/top_level.txt,sha256=u1d_f4iZ3b3_96Rb_zrs9hyrpC4yE5e1Lg6Ey_Wgr0c,7
214
+ pyvale-2025.7.2.dist-info/RECORD,,
215
+ pyvale-2025.7.2.dist-info/licenses/LICENSE,sha256=h2qWsRIazuLLhALyUsCP6aE0DFcswL9SSSt9sgMzZi4,1099