def test_square_mesh(corner_x, corner_y, width, height, _): assume(width > 1e-3) assume(height > 1e-3) # todo limit aspect ratio bg = Rectangle.from_center([0, 0], 2e6, 2e6) r = Rectangle([corner_x, corner_y], width, height) mg = ModelGeometry(allow_overlaps=True) mg.add_domain("bg", bg) mg.add_domain("r", r) points = [ (-1e6, -1e6), (1e-6, -1e6), (1e6, 1e6), (-1e6, 1e6), (corner_x, corner_y), (corner_x + width, corner_y), (corner_x + width, corner_y + height), (corner_x, corner_y + height), ] mesh = create_mesh(mg) coordinates = mesh.coordinates() for p in points: err = coordinates - p assert np.any(np.isclose(err, 0, atol=1e-6))
def test_inside_square(corner_x, corner_y, w, h, px, py): r = Rectangle([corner_x, corner_y], w, h) expr = (r.inside(None, None, buffer=0).replace("x[0]", str(px)).replace( "x[1]", str(py)).replace("&&", "and")) if corner_x < px < corner_x + w and corner_y < py < corner_y + h: assert eval(expr) else: assert not eval(expr)
def create_geometry(self, **kwargs) -> None: background = Rectangle([-0.5, -0.5], 1, 1, lcar=0.01) source = Circle([0, 0], 0.2, lcar=0.01) # particularly sensitive to mesh size self.model_geometry.add_domain("bkg", background, sigma=1) self.model_geometry.add_domain("source", source, sigma=4)
def test_create_rectangle_center(center_x, center_y, width, height, use_height): if use_height: r = Rectangle.from_center([center_x, center_y], width, height) else: r = Rectangle.from_center([center_x, center_y], width) assert np.isclose(r.center[0], center_x) assert np.isclose(r.center[1], center_y) assert np.isclose(width, r.width) if use_height: assert np.isclose(height, r.height) if use_height: check_represented_area(r, width * height) else: check_represented_area(r, width * width)
def test_domain_single(): mg = ModelGeometry() bg = Rectangle.from_center([0, 0], 1) mg.add_domain("bg", bg) mesh = create_mesh(mg) domains = mark_domains(mesh, mg).array() assert np.all(domains == mg.domain_names["bg"])
def create_geometry(self, **kwargs): """Add geometry to the model.""" bg = Rectangle([0, 0], 1, 1) self.model_geometry.add_domain("bkg", bg, sigma=self.BG_COND) source_1 = Circle(self.SOURCE_LOCATION_1, self.SOURCE_RADIUS) source_2 = Circle(self.SOURCE_LOCATION_2, self.SOURCE_RADIUS) self.model_geometry.add_domain("source_1", source_1, sigma=self.BG_COND) self.model_geometry.add_domain("source_2", source_2, sigma=self.BG_COND)
def test_create_rectangle(corner_x, corner_y, width, height, use_height): if use_height: r = Rectangle([corner_x, corner_y], width, height) else: r = Rectangle([corner_x, corner_y], width) assert np.isclose(r.center[0], corner_x + width / 2) if use_height: assert np.isclose(r.center[1], corner_y + height / 2) else: assert np.isclose(r.center[1], corner_y + width / 2) assert np.isclose(width, r.width) if use_height: assert np.isclose(height, r.height) if use_height: check_represented_area(r, width * height) else: check_represented_area(r, width * width)
def create_geometry(self, **kwargs) -> None: background = Rectangle([-0.5, -0.5], 1, 1) source = Circle([0, 0], 0.2) self.model_geometry.add_domain("bkg", background, sigma=lambda x, y: 1 + x) self.model_geometry.add_domain("source", source, sigma=lambda x, y: 1 + y)
def create_geometry(self, **kwargs) -> None: background = Rectangle([-0.5, -0.5], 1, 1) ground = Circle([-0.4, 0.2], 0.02) bottom_source = Circle([0, -0.2], 0.1) top_source = Circle([0.2, 0.3], 0.05) self.model_geometry.add_domain("bkg", background, sigma=1) self.model_geometry.add_domain("ground", ground, sigma=2) self.model_geometry.add_domain("bottom_source", bottom_source, sigma=3) self.model_geometry.add_domain("top_source", top_source, sigma=4)
def test_domain_nested(): mg = ModelGeometry() bg = Rectangle.from_center([0, 0], 1) r = Rectangle.from_center([0, 0], 0.5) mg.add_domain("bg", bg) mg.add_domain("r", r) mesh = create_mesh(mg) domains = mark_domains(mesh, mg).array() checker = r.expand(1e-3)._shapely_representation xy = mesh.coordinates() tri_f = tri.Triangulation(xy[:, 0], xy[:, 1], mesh.cells()) triangles = tri_f.get_masked_triangles() verts = np.stack((tri_f.x[triangles], tri_f.y[triangles]), axis=-1) for ix, (v1, v2, v3) in enumerate(verts): if (checker.contains(shp.Point(v1)) and checker.contains(shp.Point(v2)) and checker.contains(shp.Point(v3))): assert domains[ix] == mg.domain_names["r"] else: assert domains[ix] == mg.domain_names["bg"]
def make_square_in_square_in_square(complex=False): """Make a complex nested square structure. Default behaviour is a nested square Complex behaviour will nest two other squares inside the center square :param complex: If the complex regime will be used :return: Model geometry of the nested squares """ sq1 = Rectangle.from_center([0, 0], 6) sq2 = Rectangle.from_center([0, 0], 4) mg = ModelGeometry(allow_overlaps=True) mg.add_domain("bg", sq1) mg.add_domain("fg", sq2) if complex: sq3 = Rectangle.from_center([0, 0], 2) sq4 = Rectangle.from_center([0, 0], 0.5) # not labeled mg.add_domain("fg2", sq3) mg.add_domain("fake", sq4) mesh = create_mesh(mg) domains = mark_domains(mesh, mg) return domains, mg
def create_geometry( self, fish_x: Sequence[float], fish_y: Sequence[float], species: str = "APTERONOTUS", **kwargs, ): """Create the model geometry by making a fish, tank and ground and adding any additional user geometry. :param fish_x: x coordinates (head->tail) for the fish :param fish_y: y coordinates (head->tail) for the fish :param species: Name of the species :param kwargs: Catchall for the remaining parameters """ self.setup_fish(fish_x, fish_y, species) ground = Circle(self.GROUND_LOCATION, self.GROUND_RADIUS) tank = Rectangle.from_center([0, 0], self.TANK_SIZE) self.model_geometry.add_domain( self.WATER_NAME, tank, sigma=self.WATER_CONDUCTIVITY, ) self.model_geometry.add_domain( self.GROUND_NAME, ground, sigma=self.GROUND_CONDUCTIVITY ) self.add_geometry(**kwargs) # iterate over (possible) multiple fish and add them for ix, (outer_body, body, organ, skin_cond) in enumerate( zip( self.fish_container.outer_body, self.fish_container.body, self.fish_container.organ, self.fish_container.skin_conductance, ) ): self.model_geometry.add_domain( f"{self.SKIN_NAME}_{ix}", outer_body, sigma=skin_cond ) self.model_geometry.add_domain( f"{self.BODY_NAME}_{ix}", body, sigma=self.BODY_CONDUCTIVITY ) self.model_geometry.add_domain( f"{self.ORGAN_NAME}_{ix}", organ, sigma=self.ORGAN_CONDUCTIVITY )
import pytest from fish2eod.geometry.primitives import Circle, Rectangle from fish2eod.mesh.model_geometry import ModelGeometry overlaps_c1 = Circle([0, 0], 0.5) not_on_bg = Circle([15, 15], 1) bg = Rectangle.from_center([0, 0], 10) c1 = Circle([0, 0], 1) c2 = Circle([2, 2], 1) @pytest.mark.quick def test_create_only_bg(): ModelGeometry() @pytest.mark.quick def test_create_seperate_domains(): mg = ModelGeometry() mg.add_domain("bg", bg) mg.add_domain("c1", c1) mg.add_domain("c2", c2) @pytest.mark.quick def test_not_on_bg(): mg = ModelGeometry() mg.add_domain("bg", bg) with pytest.raises(ValueError) as _: mg.add_domain("off", not_on_bg)
def test_rotate(angle, degrees, center): r = Rectangle.from_center([0, 0], 5, 5) re_done = r.rotate(angle, degrees, center).rotate(-angle, degrees, center) check_overlap_equal(r, re_done)
def create_geometry(self, **kwargs) -> None: background = Rectangle([-0.5, -0.5], 1, 1) self.model_geometry.add_domain("bkg", background, sigma=1)
def create_geometry(self, **kwargs): sq = Rectangle.from_center([0, 0], 3) circ = Circle([0, 0], 0.5) self.model_geometry.add_domain("bg", sq, sigma=1) self.model_geometry.add_domain("act", circ, sigma=2)