diff --git a/.github/workflows/code_coverage.yaml b/.github/workflows/code_coverage.yaml deleted file mode 100644 index ef43a8a7..00000000 --- a/.github/workflows/code_coverage.yaml +++ /dev/null @@ -1,4 +0,0 @@ -name: Upload coverage reports to Codecov -uses: codecov/codecov-action@v3 -env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 3c5ae46a..e8f1d979 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -2,7 +2,9 @@ name: "piel-coverage" on: workflow_dispatch: - pull_request: + push: + branches: + - develop defaults: run: @@ -55,3 +57,18 @@ jobs: coverage report -m echo "total=$(coverage report --format=total)" >> $GITHUB_ENV echo '### Total coverage: ${{ env.total }}%' + + - name: "Create badge" + # if: ${{ github.ref == 'refs/heads/latest' }} + # https://gist.githubusercontent.com/nedbat/8c6980f77988a327348f9b02bbaf67f5 + uses: schneegans/dynamic-badges-action@v1.7.0 + with: + auth: ${{ secrets.GH_PAT }} + gistID: 605df9da19061593715258b77e06ab9b + filename: piel_coverage.json + label: Coverage + message: ${{ env.total }}% + minColorRange: 60 + maxColorRange: 95 + valColorRange: ${{ env.total }} + style: "for-the-badge" diff --git a/README.md b/README.md index a250b363..8eaa6c79 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,12 @@ Name](https://img.shields.io/badge/pypi-piel-blue?style=for-the-badge)](https:// Version](https://img.shields.io/pypi/v/piel.svg?style=for-the-badge)](https://pypi.python.org/pypi/piel) [![Documentation Status](https://readthedocs.org/projects/piel/badge/?style=for-the-badge)](https://piel.readthedocs.io/en/latest/?version=latest) +![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/daquintero/605df9da19061593715258b77e06ab9b/raw/piel_coverage.json) [![MIT](https://img.shields.io/github/license/gdsfactory/gdsfactory?style=for-the-badge)](https://choosealicense.com/licenses/mit/) [![Black](https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge)](https://github.com/psf/black) +**`piel < 0.1` is still in active development. The API is starting to stabilize, but use it currently at your own risk.** + Microservices to codesign photonics, electronics, communications, quantum, and more. diff --git a/docs/README.rst b/docs/README.rst index bc51d0b4..5192e3d5 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -2,9 +2,13 @@ **P**\ hotonic **I**\ ntegrated **EL**\ ectronics #################################################### -|PyPI Name| |PyPI Version| |Documentation Status| |MIT| +|PyPI Name| |PyPI Version| |Documentation Status| |Coverage| |MIT| |Black| +.. warning:: + + **``piel < 0.1`` is still in active development. The API is starting to stabilize, but use it currently at your own risk.** + Microservices to codesign photonics, electronics, communications, quantum, and more. @@ -84,7 +88,11 @@ want to do a single contribution, let's do this together! :target: https://pypi.python.org/pypi/piel .. |Documentation Status| image:: https://readthedocs.org/projects/piel/badge/?style=for-the-badge :target: https://piel.readthedocs.io/en/latest/?version=latest +.. |Coverage| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/daquintero/605df9da19061593715258b77e06ab9b/raw/piel_coverage.json .. |MIT| image:: https://img.shields.io/github/license/gdsfactory/gdsfactory?style=for-the-badge :target: https://choosealicense.com/licenses/mit/ .. |Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge :target: https://github.com/psf/black + + + diff --git a/docs/conf.py b/docs/conf.py index 8ba03188..83165aa6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -144,7 +144,7 @@ versionwarning_messages = { "develop": 'You are reading the "develop" pip-unreleased version of this documentation.' " See the ``stable`` branch for the stable release.", - "latest": 'You are reading the "latest" pip-unreleased version of this documentation.' + "latest": 'You are reading the "latest" version of this documentation.' " See the ``stable`` branch for the latest release.", } versionwarning_admonition_type = "tip" diff --git a/piel/materials/thermal_conductivity/copper.py b/piel/materials/thermal_conductivity/copper.py index 32b07bd0..c8c0ced8 100644 --- a/piel/materials/thermal_conductivity/copper.py +++ b/piel/materials/thermal_conductivity/copper.py @@ -19,7 +19,7 @@ def copper( temperature_range_K: TemperatureRangeTypes, material_reference: MaterialReferenceType, *args, - **kwargs + **kwargs, ) -> ArrayTypes: specification = material_reference[1] copper_thermal_conductivity_file = ( @@ -63,65 +63,3 @@ def copper( thermal_conductivity_fit = numerator / denominator return thermal_conductivity_fit - - -# if self.material_name == "copper": -# thermal_conductivity_material_dataset = pd.read_csv( -# file_path + "/../materials/files/raw/thermal_conductivity/ofhc_copper_thermal_conductivity.csv") -# a = nsy.C(s=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "a"][self.material_sub_name].values[0], -# n=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "a"][ -# self.material_sub_name].values) -# b = nsy.C(s=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "b"][self.material_sub_name].values[0], -# n=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "b"][ -# self.material_sub_name].values) -# c = nsy.C(s=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "c"][self.material_sub_name].values[0], -# n=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "c"][ -# self.material_sub_name].values) -# d = nsy.C(s=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "d"][self.material_sub_name].values[0], -# n=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "d"][ -# self.material_sub_name].values) -# e = nsy.C(s=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "e"][self.material_sub_name].values[0], -# n=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "e"][ -# self.material_sub_name].values) -# f = nsy.C(s=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "f"][self.material_sub_name].values[0], -# n=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "f"][ -# self.material_sub_name].values) -# g = nsy.C(s=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "g"][self.material_sub_name].values[0], -# n=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "g"][ -# self.material_sub_name].values) -# h = nsy.C(s=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "h"][self.material_sub_name].values[0], -# n=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "h"][ -# self.material_sub_name].values) -# i = nsy.C(s=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "i"][self.material_sub_name].values[0], -# n=thermal_conductivity_material_dataset[ -# thermal_conductivity_material_dataset["coefficient"] == "i"][ -# self.material_sub_name].values) -# self.__thermal_conductivity_fit__ = nsy.V(n=10) ** ((a + -# c * self.temperature_range_K ** 0.5 + -# e * self.temperature_range_K + -# g * self.temperature_range_K ** 1.5 + -# i * self.temperature_range_K ** 2) / -# (1 + -# b * self.temperature_range_K ** 0.5 + -# d * self.temperature_range_K + -# f * self.temperature_range_K ** 1.5 + -# h * self.temperature_range_K ** 2) -# -# return self.__thermal_conductivity_fit__.n diff --git a/piel/materials/thermal_conductivity/stainless_steel.py b/piel/materials/thermal_conductivity/stainless_steel.py index 11a62c8a..66f61983 100644 --- a/piel/materials/thermal_conductivity/stainless_steel.py +++ b/piel/materials/thermal_conductivity/stainless_steel.py @@ -14,18 +14,18 @@ def stainless_steel( temperature_range_K: TemperatureRangeTypes, material_reference: MaterialReferenceType, *args, - **kwargs + **kwargs, ): - try: - specification = material_reference[1] - material_sub_name = specification[1] - except IndexError as e: + specification = material_reference[1] + if specification not in supported_specifications: raise ValueError( "Invalid specification for stainless steel: " + specification + ". Valid options are: " - + str(supported_specifications) - ) from e + + ", ".join(supported_specifications) + ) + + material_sub_name = specification if material_sub_name == "304": # https://trc.nist.gov/cryogenics/materials/304Stainless/304Stainless_rev.htm diff --git a/piel/types/connectivity/abstract.py b/piel/types/connectivity/abstract.py index 42c5e3af..64761919 100644 --- a/piel/types/connectivity/abstract.py +++ b/piel/types/connectivity/abstract.py @@ -25,7 +25,7 @@ class Connection(Instance): This represents the fundamental data structure to identify a connection between two ports. """ - ports: tuple[Port, Port] + ports: tuple[Port, Port] = tuple() class Component(Instance): @@ -33,9 +33,9 @@ class Component(Instance): This represents the fundamental data structure to identify a component with ports and internal or external connectivity. """ - ports: list[Port] + ports: list[Port] = [] - connections: list[Connection] + connections: list[Connection] = [] components: list[Component] = [] """ diff --git a/piel/types/environment.py b/piel/types/environment.py index b23ce131..e8ac5067 100644 --- a/piel/types/environment.py +++ b/piel/types/environment.py @@ -7,5 +7,5 @@ class Environment(PielBaseModel): Data structure to define a corresponding environment. """ - temperature_K: float + temperature_K: float = None region: Optional[str] = None diff --git a/tests/import/__init__.py b/tests/import/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/import/test_import_core.py b/tests/import/test_import_core.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/import/test_import_experimental.py b/tests/import/test_import_experimental.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/materials/__init__.py b/tests/materials/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/materials/thermal_conductivity/__init__.py b/tests/materials/thermal_conductivity/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/materials/thermal_conductivity/test_aluminum.py b/tests/materials/thermal_conductivity/test_aluminum.py new file mode 100644 index 00000000..51665b3d --- /dev/null +++ b/tests/materials/thermal_conductivity/test_aluminum.py @@ -0,0 +1,39 @@ +import pytest +import jax.numpy as jnp +from piel.materials.thermal_conductivity import aluminum + + +@pytest.mark.parametrize( + "temperature, expected", + [ + ( + 300, + 211.78811, + ), # Expected value needs to be calculated or verified beforehand + (400, 236.965), # Example expected values, replace with correct ones + ], +) +def test_aluminum_correct_calculations(temperature, expected): + material_ref = ("aluminum", "1100") + result = aluminum(temperature, material_ref) + assert jnp.isclose( + result, expected, rtol=1e-4 + ), f"Expected {expected}, got {result}" + + +def test_aluminum_invalid_specification(): + with pytest.raises(ValueError): + aluminum(300, ("aluminum", "9999")) + + +@pytest.mark.parametrize( + "temperature", + [ + 300, # scalar + jnp.array([300, 350]), # JAX array + ], +) +def test_aluminum_input_types(temperature): + material_ref = ("aluminum", "1100") + result = aluminum(temperature, material_ref) + assert isinstance(result, jnp.ndarray), "Result should be a JAX array" diff --git a/tests/materials/thermal_conductivity/test_stainless_steel.py b/tests/materials/thermal_conductivity/test_stainless_steel.py new file mode 100644 index 00000000..48ad4342 --- /dev/null +++ b/tests/materials/thermal_conductivity/test_stainless_steel.py @@ -0,0 +1,39 @@ +import pytest +import jax.numpy as jnp +from piel.materials.thermal_conductivity import stainless_steel + + +@pytest.mark.parametrize( + "temperature, specification, expected", + [ + (300, ("stainless_steel", "304"), 15.308), # Example expected value + (400, ("stainless_steel", "310"), 13.542), # Example expected value + (300, ("stainless_steel", "316"), 15.308), # Example expected value + ], +) +def test_stainless_steel_valid_specifications(temperature, specification, expected): + result = stainless_steel(temperature, specification) + assert jnp.isclose( + result, expected, rtol=1e-4 + ), f"Expected {expected}, got {result}" + + +def test_stainless_steel_invalid_specification(): + with pytest.raises(ValueError): + stainless_steel(300, ("stainless_steel", "999")) + + +@pytest.mark.parametrize( + "temperature, specification", + [ + (jnp.array([300, 350]), ("stainless_steel", "304")), + (jnp.array([300, 350, 400]), ("stainless_steel", "310")), + ], +) +def test_stainless_steel_temperature_array_input(temperature, specification): + results = stainless_steel(temperature, specification) + assert isinstance(results, jnp.ndarray), "Expected results to be a JAX array" + assert results.shape == temperature.shape, "Result array should match input shape" + + +# Add additional tests to cover edge cases or specific behaviors diff --git a/tests/types/connectivity/__init__.py b/tests/types/connectivity/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/types/connectivity/test_physical.py b/tests/types/connectivity/test_physical.py new file mode 100644 index 00000000..32ed0db6 --- /dev/null +++ b/tests/types/connectivity/test_physical.py @@ -0,0 +1,50 @@ +from piel.types import PhysicalPort +from piel.types import PhysicalConnection, Connection +from piel.types import PhysicalComponent, Environment, Component + + +def test_physical_port_initialization(): + port = PhysicalPort() + assert port.domain is None + assert port.connector is None + assert port.manifold is None + + +def test_physical_port_assignment(): + port = PhysicalPort(domain="DC", connector="USB-C", manifold="Top") + assert port.domain == "DC" + assert port.connector == "USB-C" + assert port.manifold == "Top" + + +def test_physical_connection_initialization(): + conn = PhysicalConnection(connections=[]) + assert isinstance(conn.connections, list) + assert conn.components is None + + +def test_physical_connection_with_components(): + conn = PhysicalConnection(connections=[Connection()], components=(Component(),)) + assert len(conn.connections) == 1 + assert isinstance(conn.components, tuple) + assert len(conn.components) == 1 + + +def test_physical_component_initialization(): + component = PhysicalComponent(ports=[PhysicalPort()], connections=[]) + assert isinstance(component.ports, list) + assert isinstance(component.connections, list) + assert component.environment is None + + +def test_physical_component_assignment(): + component = PhysicalComponent( + ports=[PhysicalPort(connector="HDMI")], + connections=[PhysicalConnection(connections=[Connection()])], + environment=Environment(), + manufacturer="Example Corp", + model="Model X", + ) + assert component.manufacturer == "Example Corp" + assert component.model == "Model X" + assert isinstance(component.environment, Environment)