Skip to content

Commit

Permalink
FEAT: add example template and writer
Browse files Browse the repository at this point in the history
  • Loading branch information
SMoraisAnsys committed Feb 20, 2024
1 parent 27f703d commit 4d9ca39
Show file tree
Hide file tree
Showing 6 changed files with 416 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/ansys/pyaedt/examples/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
Project dedicated to PyAEDT examples
"""

__version__ = "0.1.dev0"
111 changes: 111 additions & 0 deletions src/ansys/pyaedt/examples/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Constants used in PyAEDT examples.
"""

AEDT_VERSION = "2023.2"
EDB_VERSION = "2023.2"

HEADER = """# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE."""

EDB_PREAMBLE = """# This example shows how you can use EDB to create a layout.
# ## Final expected project
#
# <img src="_static/diff_via.png" width="500">"""

EDB_IMPORTS = """
# +
import os
import tempfile
from src.ansys.pyaedt.examples.constants import EDB_VERSION
from pyaedt import Edb
# -"""

EDB_TMP_DIR = r"""# Create and return a temporary directory
temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
print(f"Temporary directory created at {temp_dir.name}")"""

EDB_APP_SETUP = r"""# +
aedb_path = os.path.join(temp_dir.name, "create_via.aedb")
print(f"Path used to save the AEDB file: {aedb_path}")
edb = Edb(edbpath=aedb_path, edbversion=edb_version)
# -"""

EDB_PROCESSING = """# ## Add stackup layers
# A stackup can be created layer by layer or imported from a CSV file or XML file.
edb.stackup.add_layer("GND")
edb.stackup.add_layer(
"Diel", "GND", layer_type="dielectric", thickness="0.1mm", material="FR4_epoxy"
)
edb.stackup.add_layer("TOP", "Diel", thickness="0.05mm")
# ## Create signal net and ground planes
points = [[0.0, 0], [100e-3, 0.0]]
edb.modeler.create_trace(points, "TOP", width=1e-3)
points = [[0.0, 1e-3], [0.0, 10e-3], [100e-3, 10e-3], [100e-3, 1e-3], [0.0, 1e-3]]
edb.modeler.create_polygon(points, "TOP")
points = [[0.0, -1e-3], [0.0, -10e-3], [100e-3, -10e-3], [100e-3, -1e-3], [0.0, -1e-3]]
edb.modeler.create_polygon(points, "TOP")
# ## Create vias with parametric positions
edb.padstacks.create("MyVia")
edb.padstacks.place([5e-3, 5e-3], "MyVia")
edb.padstacks.place([15e-3, 5e-3], "MyVia")
edb.padstacks.place([35e-3, 5e-3], "MyVia")
edb.padstacks.place([45e-3, 5e-3], "MyVia")
edb.padstacks.place([5e-3, -5e-3], "MyVia")
edb.padstacks.place([15e-3, -5e-3], "MyVia")
edb.padstacks.place([35e-3, -5e-3], "MyVia")
edb.padstacks.place([45e-3, -5e-3], "MyVia")
# ## Generate geometry plot
edb.nets.plot(None, color_by_net=True)
# ## Generate stackup plot
edb.stackup.plot(plot_definitions="MyVia")"""
75 changes: 75 additions & 0 deletions src/ansys/pyaedt/examples/edb_writer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Utils to write an EDB example.
If used as a python script, this file will generate a simple example.
"""

import os

from ansys.pyaedt.examples.constants import (
EDB_APP_SETUP,
EDB_IMPORTS,
EDB_PREAMBLE,
EDB_PROCESSING,
EDB_TMP_DIR,
EDB_VERSION,
HEADER,
)
from ansys.pyaedt.examples.models import CodeCell, EDBModel, TextCell
from jinja2 import Environment, FileSystemLoader

PARENT_DIR = os.path.dirname(os.path.abspath(__file__))


def write_example(example_path, data: EDBModel):
"""Write a new example using a template and user information."""

file_loader = FileSystemLoader(os.path.join(PARENT_DIR, "templates"))
env = Environment(loader=file_loader)
template = env.get_template("template_edb.j2")

output = template.render(data.model_dump())
with open(example_path, "w") as f:
f.write(output)


if __name__ == "__main__":

# Data of a simple edb example
data = {
"header_required": False,
"header": HEADER,
"example_title": "Simple workflow using EDB",
"example_preamble": TextCell(EDB_PREAMBLE),
"step_imports": CodeCell(EDB_IMPORTS),
"step_temp_dir": CodeCell(EDB_TMP_DIR),
"download_required": False,
"step_download": CodeCell(""),
"edb_version": EDB_VERSION,
"step_app_setup": CodeCell(EDB_APP_SETUP),
"step_processing": EDB_PROCESSING,
}
model_data = EDBModel(**data)

example_path = os.path.join(PARENT_DIR, "simple_example.py")
write_example(example_path, data=model_data)
83 changes: 83 additions & 0 deletions src/ansys/pyaedt/examples/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Models used to store data related to writing PyAEDT examples.
"""
from typing import Union

from ansys.pyaedt.examples.constants import EDB_APP_SETUP, EDB_IMPORTS, EDB_TMP_DIR, EDB_VERSION
from pydantic import BaseModel, field_validator


class CodeCell(BaseModel):
"""Notebook code cell"""

code: str

def __init__(self, code: str = None, **data):
code_value = code if code is not None else data.get("code")
super().__init__(code=code_value)

@field_validator("code")
def multiple_blocs(cls, v):
if v.startswith("# +") and not v.endswith("# -"):
raise ValueError("multiple blocks must begin with '# +' and end with '# -'")
return v


class TextCell(BaseModel):
"""Notebook text cell"""

text: str

def __init__(self, text: str = None, **data):
text_value = text if text is not None else data.get("text")
super().__init__(text=text_value)

@field_validator("text")
def must_start_with_hash(cls, v):
lines = v.split("\n")
for line in lines:
if line == "#":
continue
if not line.startswith("# "):
raise ValueError("each line of a text cell must be '#' or start with '# '")
return v


class EDBModel(BaseModel):
"""Store AEDT properties."""

header_required: bool = False
header: Union[TextCell, str] = ""
example_title: str = "Simple workflow using EDB"
example_preamble: Union[TextCell, str] = ""
step_imports: CodeCell = CodeCell(EDB_IMPORTS)
step_temp_dir: CodeCell = CodeCell(EDB_TMP_DIR)
download_required: bool = False
step_download: CodeCell = CodeCell("")
edb_version: str = EDB_VERSION
step_app_setup: CodeCell = CodeCell(EDB_APP_SETUP)
step_processing: str = ""


if __name__ == "__main__":
model = EDBModel()
45 changes: 45 additions & 0 deletions src/ansys/pyaedt/examples/templates/template_edb.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{%- if header_required -%}
{{ header }}
{%- endif -%}
# ## {{ example_title }}
#
{{ example_preamble.text }}

# ## Perform required imports and create a temporary folder.
#
# Perform imports required to run the example and create a temporary folder in which to save files.
{{ step_imports.code }}

{{ step_temp_dir.code }}

{%- if download_required -%}
# ## Download the EDB file.
{{ step_download.code }}
{% endif %}

# ## Create an instance of the Electronics Database using the `pyaedt.Edb` class.
#
# > Note that units are SI.

# Select EDB version (change it manually if needed, e.g. "2023.2")
edb_version = {{ edb_version }}
print(f"EDB version: {edb_version}")

{{ step_app_setup.code }}

{{ step_processing }}

# ## Save and clean up
#
# The following commands save and close the EDB. After that, the temporary
# directory containing the project is deleted. To keep this project, save it to
# another folder of your choice prior to running the following cell.

# +
edb.save_edb()
edb.close_edb()
print("EDB saved correctly to {}. You can import in AEDT.".format(aedb_path))

# Removing the temporary directory
temp_dir.cleanup()
# -
Loading

0 comments on commit 4d9ca39

Please sign in to comment.