Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ruler update #30

Closed
wants to merge 6 commits into from
Closed

Ruler update #30

wants to merge 6 commits into from

Conversation

mawc2019
Copy link
Collaborator

A new version of ruler, i.e., ruler_cv.py, is added. This version relies on the cv2 module of OpenCV. Tests based on @mfschubert's design patterns are also included. Overall, compared with the results of the old version, minimum length scales estimated by the new version are closer to the declared values. However, the new version does not work for 3d patterns, because cv2 does not support 3d calculation. Since almost all design patterns in this project are 2d (and the only 3d patterns have constant 2d cross sections, which can be treated as 2d patterns), maybe we could just delete the old version and use the new version, which only supports 2d calculation.

@oskooi
Copy link
Collaborator

oskooi commented Nov 15, 2022

It might be useful to show the various designs (CSV files) in the README.md tiled as a single image file with a label for the measured lengthscale.

@stevengj
Copy link
Contributor

I'm not convinced that this should be merged:

  • The old code does more (2d and 3d), and is already written, and we don't care about performance, so we mostly lose by switching to OpenCV.
  • If OpenCV is giving slightly different results from your code, then probably either there is a bug or you are misunderstanding the OpenCV API? If you take an image and do a convolution, either with your code or OpenCV, you should get exactly the same results up to floating-point roundoff errors.

@mawc2019
Copy link
Collaborator Author

Here is a different issue.
In the current version of ruler.py, the difference between open and close is calculated. Alternatively, one can simply calculate the difference between the original design pattern and its open, or the difference between the original design pattern and its close. The minimum length scales estimated from these operations are nearly the same in most cases. However, significant discrepancy arises when the design pattern has a narrow feature near the boundary. For example, in the design pattern below, the declared diameter of the disc (solid region) is 1.6, and its distance from the nearest boundary is 0.2, which is narrow enough.
image
If we estimate the length scale from the difference between open and close, just as we have been doing in ruler.py, the result is 0.45, which is roughly twice the width of the narrow region between the disc and the boundary. However, if we estimate the length scale from the difference between the original design pattern and its open, the result is 1.57, which roughly equals to the diameter of the disc.
The reason for the discrepancy is related to the different characters between close and open operations. If we want to ignore the narrow region near boundaries when estimating minimum length scales, we should refrain from using the close operation, which means to take the difference between the original design pattern and its open. In contrast, if we want to count the narrow region near boundaries when estimating minimum length scales, the close operation needs to be involved.
In order to avoid potential inaccuracies, maybe we should estimate the minimum length scale of each design pattern in two ways, one of which relies on the difference between the original design pattern and its open, while the other relies on the difference between the original design pattern and its close. If the two values are distinct (e.g., above the size of 10 pixels) from each other, the code may need to display a warning.

@mawc2019
Copy link
Collaborator Author

Here is another issue.
When a design pattern contains a sharp feature that is beyond one-pixel level and away from boundaries, the theoretical minimum length scale is 0 or the size of one pixel. However, due to discretization error, the estimated minimum length scale is above 0. For example, if such a sharp feature is a rectangular corner, the estimated minimum length scale is roughly $4\sqrt{2}/(\sqrt{2}-1) \approx 13.7$ times the pixel size, which is much larger than the size of one pixel. A user may mistake this value for the minimum length scale. To avoid this situation, perhaps we need to detect straight lines in the design pattern, and enforce the minimum length scale to be 0 or the size of one pixel if two straight lines intersect.

@mawc2019
Copy link
Collaborator Author

mawc2019 commented Jan 20, 2023

The ndimage package in scipy also contains the morphological functions binary_opening and binary_closing, but for 3d tasks, the computational cost of these functions is higher than those in ruler.py. Even if the 3d pattern and the 3d kernel have moderate sizes, out-of-memory error can still occur when the morphological functions in ndimage are invoked. The example code is as follows. The out-of-memory error can be avoided when more CPUs are used.

import numpy as np
from scipy.ndimage import binary_opening

pattern_length, kernel_length = 80, 40
pattern = np.ones((pattern_length,pattern_length,pattern_length),dtype=bool)
kernel = np.ones((kernel_length,kernel_length,kernel_length),dtype=bool)
binary_opening(pattern,structure=kernel,output=pattern)

The advantages of using the ndimage package are that the code of ruler.py can be simplified and the morphological operations become more accurate. Shall we use the ndimage package and replace all the morphological functions in ruler.py?

@stevengj
Copy link
Contributor

That example runs for me (32GB ram) in about 30 seconds without running out of memory. It also runs with pattern_length = 160 without running out of memory.

@stevengj
Copy link
Contributor

stevengj commented Mar 7, 2023

Conclusion: let's go with min(open-design, design-close), use opencv, use the new definition of interfacial pixels, and use the simplest-to-explain definition of the discretized "circular" kernel.

@oskooi
Copy link
Collaborator

oskooi commented Mar 10, 2023

One other feature relates to the padding of the edge pixels of the design region. Our convention will be:

  1. when measuring the minimum length of the solid regions, the edge padding (as part of the open operation) will use solid pixels.
  2. when measuring the minimum length of the void regions, we will pad with void pixels.

@stevengj
Copy link
Contributor

Obsoleted by recent changes.

@stevengj stevengj closed this Mar 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants