-
Notifications
You must be signed in to change notification settings - Fork 117
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
feature: Factory methods for AHS AtomArrangments by AbdullahKazi500 #989
base: main
Are you sure you want to change the base?
feature: Factory methods for AHS AtomArrangments by AbdullahKazi500 #989
Conversation
defined the SiteType enum and AtomArrangementItem dataclass to handle the coordinates and site types, ensuring validations. AtomArrangement Class: The class initializes with an empty list of sites. Add Method: Adds a coordinate to the arrangement with a site type. Retrieves a list of coordinates for a given index. Rounds coordinates to the nearest multiple of the given resolution. Factory Methods: Methods for creating square and rectangular lattice arrangements. Demonstrates creating a square lattice with specified boundary points and lattice constant.
Hi @AbdullahKazi500 , There are good ideas here. But there is also a lot of unnecessary (and confusing) redefinitions and changes that are not pertinent to the issue at hand. Also, to avoid future confusion, please work on this PR going forward. I will close the rest. As a first start:
If you need guidance how to do this, happy to point you to materials. |
@peterkomar-aws Hi peter thanks for the guidance I am new to open source before this I use to push demo code into master branches for my previous projects I have worked as an experimentalist researcher for 4 years and had my formal education in experimental validation research so I hope its okay its my first time I am doing an opensource hackathon I will try following your guidelines but please do accept my apologies for a lot of different PRs |
Hi @AbdullahKazi500 , no worries. We were all there some time in our journey. Please try to follow the contributions guidelines. You can start by creating a fork of the repo, and work there on a feature branch first. Once your tests are passing locally and you are happy with the code, you can create a PR from your fork to this repo. |
I have cleaned up and properly formatted the code to enhance readability and maintainability. Here are the key changes made: Added all necessary imports at the beginning of the code. Defined a custom exception DiscretizationError. Organized and added necessary data classes (LatticeGeometry, DiscretizationProperties, AtomArrangementItem) and enums (SiteType). Implemented validation methods inside AtomArrangementItem to check coordinates and site types. Added docstrings to methods for better understanding. Implemented methods for adding coordinates, getting coordinate lists, iterating, getting length, and discretizing arrangements. Added factory methods for creating different lattice structures (square, rectangular, decorated Bravais, honeycomb, and Bravais lattices).
Hi @peterkomar-aws I have cleaned up and properly formatted the code to enhance readability and maintainability. Here are the key changes made: Added all necessary imports at the beginning of the code. |
Hi @AbdullahKazi500 , thanks for continuing the work. You wrote that you removed unnecessary definitions, but the atom_arrangement.py file in your latest commit still contains many repeated redefinitions. E.g. the original defition of AtomArrangementItem is defined in L41, then redefined in L187, L351, and L393; AtomArrangement is originally defined in L63, then redefined in L208, L428. Your proposed version of the module has 527 lines, I understand that may be difficult to handle, but to move forward with this work, I ask you to review each line of change and addition that you are proposing (here) and carefully consider its function and value. Once you feel that your work is ready for a careful review please click the ready for review button to flip back the PR from draft stage to open. Thank you. |
Hi @peterkomar-aws Thanks to the review I will check and modify this again but after testing it locally I am kind of getting the desired results here but still I will try addressing the feedbacks you have advised |
Imports
This Enum defines two possible types for sites: FILLED and VACANT.
This dataclass represents an item in an atom arrangement with a coordinate and a site type.
Validates the coordinate and site type after initializing an AtomArrangementItem.
Initializes an empty list to hold atom arrangement items.
Adds a new site to the arrangement and returns self for method chaining.
Returns a list of coordinates at the specified index (0 for x-coordinates, 1 for y-coordinates).
Allows iteration over the arrangement and retrieves the number of sites
|
Hi @peterkomar-aws this are what the functions, data classes are |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needing a review
@peterkomar-aws let me know your thoughts |
Hi @AbdullahKazi500 , thanks for working on this PR. In my previous comments, I mentioned that you had many re-definitions in your atom_arrangement.py module. This is still the case. I'd like to start a conversation with you about one particular case, The class
class SiteType(Enum):
VACANT = "Vacant"
FILLED = "Filled"
class SiteType(Enum):
FILLED = "filled"
VACANT = "vacant"
class SiteType(Enum):
VACANT = "Vacant"
FILLED = "Filled"
class SiteType(Enum):
FILLED = "filled"
EMPTY = "empty"
class SiteType(Enum):
FILLED = "filled"
EMPTY = "empty"
Since |
Hi peter thanks for the feedback I will try to address your questions What is the purpose of this code? Why did you not leave the original definition from the main branch in place? Redefinition at Line 347 (Changing VACANT to EMPTY) Redefinition at Line 388 so further plans would be------------- Removimg the redundant redefinition at line 388. Ensure only one consistent definition of SiteType exists in the module.
Remove all other redefinitions to avoid confusion and ensure consistency. |
Hi @AbdullahKazi500 , this sounds like a good next step. |
Hi peter before I make a PR I would like you to review the code if I am going wrong here feel free to correct me
|
Hi @peterkomar-aws made a PR Recently here here |
Hi @AbdullahKazi500 , thanks for adding the changes to the AHS.py file. Since you contribution will be modifications to the atom_arrangement.py file, please add the changes there. If you replace the content of that file with what you have in you AHS.py, then I can do a more through review, beacause I will see the changes with respect to the original atom_arrangement.py file. Thanks. |
Okay peter I will make both separate and in file PRs |
@peterkomar-aws Okay done now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you appended the latest version of the file. Instead, please replace the content of the entire file with this, so I can do a more careful, line-by-line review. Thanks.
AHS.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this file, and make all edits to the atom_arrangement.py module and the test_atom_arrangement.py module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @peterkomar-aws replaced the content of the entire file with this now going through the comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The individual file was deleted
src/braket/ahs/atom_arrangement.py
Outdated
@@ -23,18 +23,24 @@ | |||
import numpy as np | |||
|
|||
from braket.ahs.discretization_types import DiscretizationError, DiscretizationProperties | |||
from typing import Union, Tuple, List, Iterator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please merge this line with L21 above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@peterkomar-aws this part of the import has been removed since I have rewritten the code again replacing the old content
src/braket/ahs/atom_arrangement.py
Outdated
@@ -23,18 +23,24 @@ | |||
import numpy as np | |||
|
|||
from braket.ahs.discretization_types import DiscretizationError, DiscretizationProperties | |||
from typing import Union, Tuple, List, Iterator | |||
from dataclasses import dataclass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a repeated import (same as L17), please remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@peterkomar-aws this import is prevented from repeating by removing the old code
src/braket/ahs/atom_arrangement.py
Outdated
@@ -23,18 +23,24 @@ | |||
import numpy as np | |||
|
|||
from braket.ahs.discretization_types import DiscretizationError, DiscretizationProperties | |||
from typing import Union, Tuple, List, Iterator | |||
from dataclasses import dataclass | |||
import numpy as np |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a repeated import (same as line 23), please remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this import is prevented from repeating by removing the old code
src/braket/ahs/atom_arrangement.py
Outdated
from typing import Union, Tuple, List, Iterator | ||
from dataclasses import dataclass | ||
import numpy as np | ||
from decimal import Decimal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a repeated import (same as line 18), please remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this import is prevented from repeating by removing the old code
src/braket/ahs/atom_arrangement.py
Outdated
|
||
|
||
# Define SiteType enum |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment does not tell anything beyond what the next line is telling already. Please remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes removing
src/braket/ahs/atom_arrangement.py
Outdated
site_type: SiteType = SiteType.FILLED, | ||
) -> AtomArrangement: | ||
) -> "AtomArrangement": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original hint referred to the AtomArrangement
class as a return type. What does turning it into a string literal achieve here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@peterkomar-aws resolved
"""Add a coordinate to the atom arrangement. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using Google formatted docstrings in this repo (see more here: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings), please don't remove these empty lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for many other removed lines in the docstrings below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@peterkomar-aws Hi peter resolved all the issues let me know if something is left
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great start. You have the right structure for the factory methods.
The main thing that needs change is the implementation of the from_decorated_bravais_lattice
method. Currently it cuts off too many sites, sites which would fit on the canvas. See my comment for line 141. This is not easy to solve. Looking forward to your idea how to make this method work for arbitrary vec_a and vec_b values.
The goal is the fill up the entire canvas, and only remove sites that would truly fall outside of the canvas boundary.
|
||
@classmethod | ||
def from_rectangular_lattice(cls, dx: float, dy: float, canvas_boundary_points: List[Tuple[float, float]]) -> AtomArrangement: | ||
"""Create an atom arrangement with a rectangular lattice.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add detailed docstrings listing what each is.
return arrangement | ||
|
||
@classmethod | ||
def from_decorated_bravais_lattice(cls, lattice_vectors: List[Tuple[float, float]], decoration_points: List[Tuple[float, float]], canvas_boundary_points: List[Tuple[float, float]]) -> AtomArrangement: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, let's use the RectangularCanvas
and add docstrings.
x_min, y_min = canvas_boundary_points[0] | ||
x_max, y_max = canvas_boundary_points[2] | ||
i = 0 | ||
while (origin := i * vec_a)[0] < x_max: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few issues with the implementation here:
- To fill in the entire canvas, depending on the values of vec_a and vec_b, it may not be enough to start from
i=0
andj=0
. E.g. ifvec_a = (1,1)
andvec_b = (-1, 1)
, your current implementation leaves a large empty triangle at the lower right side on a rectangular canvas. - When determining where to stop adding points, your implementation first determines which unit cells to add based on whether
point
is inside the canvas. This misses adding decoration points from unit cells whosepoint
variable is outside of the canvas, but the decoration points are inside the canvas boundary. - If the user provides unusual, or meaningless vec_a, vec_b, or decoration_points, we should catch it. Validation is needed to be implemented here.
Getting the implementation of this method right is the crux of this issue. We can start from an inefficient but working solution, and worry about efficiency later, but the current implementation is not filling the canvas properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@peterkomar-aws this is a good catch need to think about it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few issues with the implementation here:
- To fill in the entire canvas, depending on the values of vec_a and vec_b, it may not be enough to start from
i=0
andj=0
. E.g. ifvec_a = (1,1)
andvec_b = (-1, 1)
, your current implementation leaves a large empty triangle at the lower right side on a rectangular canvas.- When determining where to stop adding points, your implementation first determines which unit cells to add based on whether
point
is inside the canvas. This misses adding decoration points from unit cells whosepoint
variable is outside of the canvas, but the decoration points are inside the canvas boundary.- If the user provides unusual, or meaningless vec_a, vec_b, or decoration_points, we should catch it. Validation is needed to be implemented here.
Getting the implementation of this method right is the crux of this issue. We can start from an inefficient but working solution, and worry about efficiency later, but the current implementation is not filling the canvas properly.
to address this issue we can implement something like this
import numpy as np
from typing import List, Tuple, Union
from collections.abc import Iterator
from dataclasses import dataclass
from decimal import Decimal
from enum import Enum
from numbers import Number
class SiteType(Enum):
VACANT = "Vacant"
FILLED = "Filled"
@dataclass
class AtomArrangementItem:
coordinate: Tuple[Number, Number]
site_type: SiteType
def _validate_coordinate(self) -> None:
if len(self.coordinate) != 2:
raise ValueError(f"{self.coordinate} must be of length 2")
for idx, num in enumerate(self.coordinate):
if not isinstance(num, Number):
raise TypeError(f"{num} at position {idx} must be a number")
def _validate_site_type(self) -> None:
allowed_site_types = {SiteType.FILLED, SiteType.VACANT}
if self.site_type not in allowed_site_types:
raise ValueError(f"{self.site_type} must be one of {allowed_site_types}")
def __post_init__(self) -> None:
self._validate_coordinate()
self._validate_site_type()
class AtomArrangement:
def __init__(self):
self._sites = []
def add(self, coordinate: Union[Tuple[Number, Number], np.ndarray], site_type: SiteType = SiteType.FILLED) -> AtomArrangement:
self._sites.append(AtomArrangementItem(tuple(coordinate), site_type))
return self
def coordinate_list(self, coordinate_index: Number) -> List[Number]:
return [site.coordinate[coordinate_index] for site in self._sites]
def __iter__(self) -> Iterator:
return iter(self._sites)
def __len__(self):
return len(self._sites)
def discretize(self, properties: DiscretizationProperties) -> AtomArrangement:
try:
position_res = properties.lattice.positionResolution
discretized_arrangement = AtomArrangement()
for site in self._sites:
new_coordinates = tuple(
round(Decimal(c) / position_res) * position_res for c in site.coordinate
)
discretized_arrangement.add(new_coordinates, site.site_type)
return discretized_arrangement
except Exception as e:
raise DiscretizationError(f"Failed to discretize register {e}") from e
@classmethod
def from_decorated_bravais_lattice(cls, lattice_vectors: List[Tuple[float, float]], decoration_points: List[Tuple[float, float]], canvas_boundary_points: List[Tuple[float, float]]) -> AtomArrangement:
"""Create an atom arrangement with a decorated Bravais lattice."""
# Validate input
if len(lattice_vectors) != 2:
raise ValueError("Two lattice vectors are required.")
if any(len(vec) != 2 for vec in lattice_vectors):
raise ValueError("Each lattice vector must have two components.")
if any(len(dp) != 2 for dp in decoration_points):
raise ValueError("Each decoration point must have two components.")
if len(canvas_boundary_points) != 4:
raise ValueError("Canvas boundary points should define a rectangle with 4 points.")
arrangement = cls()
vec_a, vec_b = np.array(lattice_vectors[0]), np.array(lattice_vectors[1])
x_min, y_min = canvas_boundary_points[0]
x_max, y_max = canvas_boundary_points[2]
def is_within_canvas(point: np.ndarray) -> bool:
return x_min <= point[0] <= x_max and y_min <= point[1] <= y_max
# Determine number of steps needed in each direction to fill the canvas
n_steps_x = int(np.ceil((x_max - x_min) / np.linalg.norm(vec_a)))
n_steps_y = int(np.ceil((y_max - y_min) / np.linalg.norm(vec_b)))
for i in range(-n_steps_x, n_steps_x + 1):
for j in range(-n_steps_y, n_steps_y + 1):
origin = i * vec_a + j * vec_b
for dp in decoration_points:
decorated_point = origin + np.array(dp)
if is_within_canvas(decorated_point):
arrangement.add(tuple(decorated_point))
return arrangement
@dataclass
class LatticeGeometry:
positionResolution: Decimal
@dataclass
class DiscretizationProperties:
lattice: LatticeGeometry
class DiscretizationError(Exception):
pass
# Example usage
if __name__ == "__main__":
canvas_boundary_points = [(0, 0), (7.5e-5, 0), (7.5e-5, 7.5e-5), (0, 7.5e-5)]
# Create lattice structures
decorated_bravais_lattice = AtomArrangement.from_decorated_bravais_lattice(
[(4e-6, 0), (0, 4e-6)],
[(1e-6, 1e-6)],
canvas_boundary_points
)
# Validate lattice structure
def validate_lattice(arrangement, lattice_type):
num_sites = len(arrangement)
min_distance = None
for i, atom1 in enumerate(arrangement):
for j, atom2 in enumerate(arrangement):
if i != j:
distance = np.linalg.norm(np.array(atom1.coordinate) - np.array(atom2.coordinate))
if min_distance is None or distance < min_distance:
min_distance = distance
print(f"Lattice Type: {lattice_type}")
print(f"Number of lattice points: {num_sites}")
print(f"Minimum distance between lattice points: {min_distance:.2e} meters")
print("-" * 40)
validate_lattice(decorated_bravais_lattice, "Decorated Bravais Lattice")
return arrangement | ||
|
||
@classmethod | ||
def from_honeycomb_lattice(cls, lattice_constant: float, canvas_boundary_points: List[Tuple[float, float]]) -> AtomArrangement: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add docstrings.
return cls.from_decorated_bravais_lattice([a1, a2], decoration_points, canvas_boundary_points) | ||
|
||
@classmethod | ||
def from_bravais_lattice(cls, lattice_vectors: List[Tuple[float, float]], canvas_boundary_points: List[Tuple[float, float]]) -> AtomArrangement: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add docstrings.
Hi @peterkomar-aws
|
Hi @AbdullahKazi500 , can you explain the logic behind |
Hi @AbdullahKazi500 , thanks for your contributions. Looking forward to your contributions to this work and repo. Thank you. (I mark the PR draft again; feel free to add commits to it an open it again if you think it's ready for another round of reviews. Thanks.) |
Hi @peterkomar-aws since the Organizers has posted this message
I would like to keep going on this issue and I would like to know your review on this also I am trying to address a few of your comments |
The expression lattice_x_max = min(x_max, x_max - vec_a[0] + vec_b[0]) is used to calculate the maximum bound for the x-coordinates of the lattice within the canvas. This expression, however, does seem asymmetrical and possibly incorrect due to the fact that vec_a and vec_b should be treated symmetrically. Lattice Vectors (vec_a and vec_b): vec_a and vec_b are the lattice vectors defining the Bravais lattice. These values define the rectangular area within which the lattice should be generated. lattice_x_max = min(x_max, x_max - vec_a[0] + vec_b[0]) Logically, vec_a and vec_b are interchangeable as they both define the periodicity of the lattice. The expression x_max - vec_a[0] + vec_b[0] lacks symmetry and might produce incorrect bounds. a more well defined logic would be
Used nested while loops to iterate over lattice points generated by vec_a and vec_b. Calculate the origin point using i * vec_a. |
Hi @AbdullahKazi500 , the implementation you proposed in your previous comment, @classmethod
def from_decorated_bravais_lattice(cls, lattice_vectors: List[Tuple[float, float]], decoration_points: List[Tuple[float, float]], canvas_boundary_points: List[Tuple[float, float]]) -> AtomArrangement:
"""Create an atom arrangement with a decorated Bravais lattice."""
arrangement = cls()
vec_a, vec_b = np.array(lattice_vectors[0]), np.array(lattice_vectors[1])
x_min, y_min = canvas_boundary_points[0]
x_max, y_max = canvas_boundary_points[2]
# Iterate over lattice points within the canvas boundaries
i = 0
while True:
origin = i * vec_a
if origin[0] > x_max:
break
j = 0
while True:
point = origin + j * vec_b
if point[1] > y_max:
break
if x_min <= point[0] <= x_max and y_min <= point[1] <= y_max:
for dp in decoration_points:
decorated_point = point + np.array(dp)
if x_min <= decorated_point[0] <= x_max and y_min <= decorated_point[1] <= y_max:
arrangement.add(tuple(decorated_point))
j += 1
i += 1
return arrangement has the same issue which I pointed out previously, namely
More specifically, running the following test lattice_vectors = (
(1, 1),
(-1, 1),
)
decoration_points = (
(0, 0),
)
canvas_boundary_points = (
(0, 0),
(10, 0),
(10, 10),
(0, 10),
)
register = AtomArrangement.from_decorated_bravais_lattice(lattice_vectors, decoration_points, canvas_boundary_points) |
it seems like it is not covering over the canvas
I have tried modifying the code |
Hi @AbdullahKazi500 , regarding these lines in your proposal, n_steps_x = int(np.ceil((x_max - x_min) / np.linalg.norm(vec_a)))
n_steps_y = int(np.ceil((y_max - y_min) / np.linalg.norm(vec_b))) can you explain why for i in range(-n_steps_x, n_steps_x + 1):
for j in range(-n_steps_y, n_steps_y + 1):
origin = i * vec_a + j * vec_b and why Any implementation that does not treat |
Hi @peterkomar-aws When computing n_steps_x and n_steps_y, we want to ensure that both lattice vectors vec_a and vec_b are treated symmetrically is that what you mean but swapping the order of vec_a and vec_b in lattice_vectors will it affect the outcome of AtomArrangement. |
so if Both n_steps_x and n_steps_y are now calculated based on the maximum difference between canvas boundaries (x_max - x_min and y_max - y_min). will this ensures that the steps taken in both directions (for vec_a and vec_b) are sufficient to cover the entire canvas area.
|
Hi @AbdullahKazi500 , I appreciate that this implementation is symmetric in its treatment of @classmethod
def from_decorated_bravais_lattice(cls, lattice_vectors: List[Tuple[float, float]], decoration_points: List[Tuple[float, float]], canvas_boundary_points: List[Tuple[float, float]]) -> AtomArrangement:
"""Create an atom arrangement with a decorated Bravais lattice."""
if len(lattice_vectors) != 2 or any(len(vec) != 2 for vec in lattice_vectors):
raise ValueError("Invalid lattice vectors provided.")
if any(len(dp) != 2 for dp in decoration_points):
raise ValueError("Invalid decoration points provided.")
if len(canvas_boundary_points) != 4:
raise ValueError("Invalid canvas boundary points provided.")
arrangement = cls()
vec_a, vec_b = np.array(lattice_vectors[0]), np.array(lattice_vectors[1])
x_min, y_min = canvas_boundary_points[0]
x_max, y_max = canvas_boundary_points[2]
def is_within_canvas(point: np.ndarray) -> bool:
return x_min <= point[0] <= x_max and y_min <= point[1] <= y_max
# Determine the step directions and limits symmetrically
n_steps_x = int(np.ceil(max(x_max - x_min, y_max - y_min) / np.linalg.norm(vec_a)))
n_steps_y = int(np.ceil(max(x_max - x_min, y_max - y_min) / np.linalg.norm(vec_b)))
for i in range(-n_steps_x, n_steps_x + 1):
for j in range(-n_steps_y, n_steps_y + 1):
origin = i * vec_a + j * vec_b
for dp in decoration_points:
decorated_point = origin + np.array(dp)
if is_within_canvas(decorated_point):
arrangement.add(tuple(decorated_point))
return arrangement also does not properly fill out the canvas for the test I proposed above, i.e. lattice_vectors = (
(1, 1),
(-1, 1),
)
decoration_points = (
(0, 0),
)
canvas_boundary_points = (
(0, 0),
(10, 0),
(10, 10),
(0, 10),
)
register = AtomArrangement.from_decorated_bravais_lattice(lattice_vectors, decoration_points, canvas_boundary_points) produces a I suspect this is due to the premature stopping of the |
okay peter I will have a look |
Issue #, if available:
fixes #969
Description of changes:
added lattice.py polygon.py and the factory ahs all in one file
Testing done:
Merge Checklist
Put an
x
in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.General
Tests
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.