|
6 | 6 | """ |
7 | 7 |
|
8 | 8 | import pathlib |
9 | | -from dataclasses import dataclass |
10 | 9 | from typing import Optional, Tuple, Union |
11 | 10 | import numpy as np |
12 | 11 | import scipy.ndimage as scn |
|
15 | 14 | from scipy.interpolate import RectBivariateSpline |
16 | 15 | import matplotlib.pyplot as plt |
17 | 16 |
|
18 | | -from importlib_resources import files |
19 | 17 | from openpiv.tools import Multiprocesser, display_vector_field, transform_coordinates |
20 | 18 | from openpiv import validation, filters, tools, scaling, preprocess |
21 | 19 | from openpiv.pyprocess import extended_search_area_piv, get_rect_coordinates, \ |
22 | 20 | get_field_shape |
23 | 21 | from openpiv import smoothn |
| 22 | +from openpiv.settings import PIVSettings |
24 | 23 |
|
25 | 24 |
|
26 | | -@dataclass |
27 | | -class PIVSettings: |
28 | | - """ All the PIV settings for the batch analysis with multi-processing and |
29 | | - window deformation. Default settings are set at the initiation |
30 | | - """ |
31 | | - # "Data related settings" |
32 | | - # Folder with the images to process |
33 | | - filepath_images: Union[pathlib.Path, str] = files('openpiv') / "data" / "test1" # type: ignore |
34 | | - # Folder for the outputs |
35 | | - save_path: pathlib.Path = filepath_images.parent |
36 | | - # Root name of the output Folder for Result Files |
37 | | - save_folder_suffix: str = 'test1' |
38 | | - # Format and Image Sequence |
39 | | - frame_pattern_a: str = 'exp1_001_a.bmp' |
40 | | - frame_pattern_b: str = 'exp1_001_b.bmp' |
41 | | - |
42 | | - # "Region of interest" |
43 | | - # (50,300,50,300) #Region of interest: (xmin,xmax,ymin,ymax) or 'full' |
44 | | - # for full image |
45 | | - roi: Union[Tuple[int, int, int, int], str] = "full" |
46 | | - |
47 | | - # "Image preprocessing" |
48 | | - # Every image would be processed separately and the |
49 | | - # average mask is applied to both A, B, but it's varying |
50 | | - # for the frames sequence |
51 | | - #: None for no masking |
52 | | - #: 'edges' for edges masking, |
53 | | - #: 'intensity' for intensity masking |
54 | | - dynamic_masking_method: Optional[str] = None # ['edge','intensity'] |
55 | | - dynamic_masking_threshold: float = 0.005 |
56 | | - dynamic_masking_filter_size: int = 7 |
57 | | - |
58 | | - # Static masking applied to all images, A,B |
59 | | - static_mask: Optional[np.ndarray] = None # or a boolean matrix of image shape |
60 | | - |
61 | | - # "Processing Parameters" |
62 | | - correlation_method: str="circular" # ['circular', 'linear'] |
63 | | - normalized_correlation: bool=False |
64 | | - |
65 | | - # add the interroagtion window size for each pass. |
66 | | - # For the moment, it should be a power of 2 |
67 | | - windowsizes: Tuple[int, ...]=(64,32,16) |
68 | | - |
69 | | - # The overlap of the interroagtion window for each pass. |
70 | | - overlap: Tuple[int, ...] = (32, 16, 8) # This is 50% overlap |
71 | | - |
72 | | - # Has to be a value with base two. In general window size/2 is a good |
73 | | - # choice. |
74 | | - |
75 | | - num_iterations: int = len(windowsizes) # select the number of PIV |
76 | | - # passes |
77 | | - |
78 | | - # methode used for subpixel interpolation: |
79 | | - # 'gaussian','centroid','parabolic' |
80 | | - subpixel_method: str = "gaussian" |
81 | | - # use vectorized sig2noise and subpixel approximation functions |
82 | | - use_vectorized: bool = False |
83 | | - # 'symmetric' or 'second image', 'symmetric' splits the deformation |
84 | | - # both images, while 'second image' does only deform the second image. |
85 | | - deformation_method: str = 'symmetric' # 'symmetric' or 'second image' |
86 | | - # order of the image interpolation for the window deformation |
87 | | - interpolation_order: int=3 |
88 | | - scaling_factor: float = 1.0 # scaling factor pixel/meter |
89 | | - dt: float = 1.0 # time between to frames (in seconds) |
90 | | - |
91 | | - # Signal to noise ratio: |
92 | | - # we can decide to estimate it or not at every vector position |
93 | | - # we can decided if we use it for validation or only store it for |
94 | | - # later post-processing |
95 | | - # plus we need some parameters for threshold validation and for the |
96 | | - # calculations: |
97 | | - |
98 | | - sig2noise_method: Optional[str]="peak2mean" # or "peak2peak" or "None" |
99 | | - # select the width of the masked to masked out pixels next to the main |
100 | | - # peak |
101 | | - sig2noise_mask: int=2 |
102 | | - # If extract_sig2noise::False the values in the signal to noise ratio |
103 | | - # output column are set to NaN |
104 | | - |
105 | | - # "Validation based on the signal to noise ratio" |
106 | | - # Note: only available when extract_sig2noise::True and only for the |
107 | | - # last pass of the interrogation |
108 | | - # Enable the signal to noise ratio validation. Options: True or False |
109 | | - # sig2noise_validate: False # This is time consuming |
110 | | - # minmum signal to noise ratio that is need for a valid vector |
111 | | - sig2noise_threshold: float=1.0 |
112 | | - sig2noise_validate: bool=True # when it's False we can save time by not |
113 | | - #estimating sig2noise ratio at all, so we can set both sig2noise_method to None |
114 | | - |
115 | | - |
116 | | - # "vector validation options" |
117 | | - # choose if you want to do validation of the first pass: True or False |
118 | | - validation_first_pass: bool=True |
119 | | - # only effecting the first pass of the interrogation the following |
120 | | - # passes |
121 | | - # in the multipass will be validated |
122 | | - |
123 | | - # "Validation Parameters" |
124 | | - # The validation is done at each iteration based on three filters. |
125 | | - # The first filter is based on the min/max ranges. Observe that these |
126 | | - # values are defined in |
127 | | - # terms of minimum and maximum displacement in pixel/frames. |
128 | | - min_max_u_disp: Tuple=(-30, 30) |
129 | | - min_max_v_disp: Tuple=(-30, 30) |
130 | | - # The second filter is based on the global STD threshold |
131 | | - std_threshold: int=10 # threshold of the std validation |
132 | | - # The third filter is the median test: pick between normalized and regular |
133 | | - median_normalized: bool=False # False = do regular median, True = do normalized median |
134 | | - median_threshold: int=3 # threshold of the median validation |
135 | | - median_size: int=1 # defines the size of the local median |
136 | | - # On the last iteration, an additional validation can be done based on |
137 | | - # the S/N. |
138 | | - |
139 | | - |
140 | | - |
141 | | - # "Outlier replacement or Smoothing options" |
142 | | - # Replacment options for vectors which are masked as invalid by the |
143 | | - # validation |
144 | | - # Choose: True or False |
145 | | - replace_vectors: bool=True # Enable the replacement. |
146 | | - smoothn: bool=False # Enables smoothing of the displacement field |
147 | | - smoothn_p: float=0.05 # This is a smoothing parameter |
148 | | - # select a method to replace the outliers: |
149 | | - # 'localmean', 'disk', 'distance' |
150 | | - filter_method: str="localmean" |
151 | | - # maximum iterations performed to replace the outliers |
152 | | - max_filter_iteration: int=4 |
153 | | - filter_kernel_size: int=2 # kernel size for the localmean method |
154 | | - |
155 | | - # "Output options" |
156 | | - # Select if you want to save the plotted vectorfield: True or False |
157 | | - save_plot: bool=False |
158 | | - # Choose wether you want to see the vectorfield or not:True or False |
159 | | - show_plot: bool=False |
160 | | - scale_plot: int=100 # select a value to scale the quiver plot of |
161 | | - # the vectorfield run the script with the given settings |
162 | | - |
163 | | - show_all_plots: bool=False |
164 | | - |
165 | | - invert: bool=False # for the test_invert |
166 | | - |
167 | | - fmt: str="%.4e" |
168 | | - |
169 | 25 | def prepare_images( |
170 | 26 | file_a: pathlib.Path, |
171 | 27 | file_b: pathlib.Path, |
|
0 commit comments