From 687c36012991bb352359749eed53fdd4c68e9e38 Mon Sep 17 00:00:00 2001 From: aelmiger <40243985+aelmiger@users.noreply.github.com> Date: Tue, 16 Apr 2024 12:37:34 +0200 Subject: [PATCH] Feature/pypi deployment workflow (#13) * Update GitHub Actions workflow for PyPI deployment * Update GitHub Actions workflow for PyPI deployment * Update version to 1.2.2 * Add own Perlin noise generator --- .github/workflows/deploy_to_pypi.yaml | 117 ++++++++++++++++++ pyproject.toml | 4 +- requirements.txt | 1 - .../example_job.syclops.yaml | 1 - syclops/preprocessing/texture_processor.py | 71 +++++++++-- syclops/schema/base_schema.yaml | 4 +- 6 files changed, 180 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/deploy_to_pypi.yaml diff --git a/.github/workflows/deploy_to_pypi.yaml b/.github/workflows/deploy_to_pypi.yaml new file mode 100644 index 0000000..857a2ca --- /dev/null +++ b/.github/workflows/deploy_to_pypi.yaml @@ -0,0 +1,117 @@ +name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI + +on: push + +jobs: + build: + name: Build distribution 📦 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Install pypa/build + run: >- + python3 -m + pip install + build + --user + - name: Build a binary wheel and a source tarball + run: python3 -m build + - name: Store the distribution packages + uses: actions/upload-artifact@v3 + with: + name: python-package-distributions + path: dist/ + + publish-to-pypi: + name: >- + Publish Python 🐍 distribution 📦 to PyPI + if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes + needs: + - build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/syclops + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v3 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + github-release: + name: >- + Sign the Python 🐍 distribution 📦 with Sigstore + and upload them to GitHub Release + needs: + - publish-to-pypi + runs-on: ubuntu-latest + + permissions: + contents: write # IMPORTANT: mandatory for making GitHub Releases + id-token: write # IMPORTANT: mandatory for sigstore + + steps: + - name: Download all the dists + uses: actions/download-artifact@v3 + with: + name: python-package-distributions + path: dist/ + - name: Sign the dists with Sigstore + uses: sigstore/gh-action-sigstore-python@v1.2.3 + with: + inputs: >- + ./dist/*.tar.gz + ./dist/*.whl + - name: Create GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release create + '${{ github.ref_name }}' + --repo '${{ github.repository }}' + --notes "" + - name: Upload artifact signatures to GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + # Upload to GitHub Release using the `gh` CLI. + # `dist/` contains the built packages, and the + # sigstore-produced signatures and certificates. + run: >- + gh release upload + '${{ github.ref_name }}' dist/** + --repo '${{ github.repository }}' + + publish-to-testpypi: + name: Publish Python 🐍 distribution 📦 to TestPyPI + needs: + - build + runs-on: ubuntu-latest + + environment: + name: testpypi + url: https://test.pypi.org/p/syclops + + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v3 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution 📦 to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ diff --git a/pyproject.toml b/pyproject.toml index ef04539..66af079 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools", "setuptools-scm"] build-backend = "setuptools.build_meta" [project] -name = "syclops" +name = "Syclops" authors = [ {name = "Anton Elmiger", email = "anton.elmiger@gmail.com"}, ] @@ -12,7 +12,7 @@ readme = "README.md" requires-python = ">=3.8" license = {text = "GPLv3"} -version = "1.2.1" +version = "1.2.2" dynamic = ["dependencies"] diff --git a/requirements.txt b/requirements.txt index e1eb767..4603416 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,6 @@ filelock==3.9.0 GitPython==3.1.29 jsonschema==4.17.3 opencv-python==4.6.0.66 -perlin-numpy @ git+https://github.com/pvigier/perlin-numpy@5e26837db14042e51166eb6cad4c0df2c1907016 Pillow==9.4.0 PyYAML==6.0.1 requests==2.27.1 diff --git a/syclops/__example_assets__/example_job.syclops.yaml b/syclops/__example_assets__/example_job.syclops.yaml index 96f8f1f..c72e604 100644 --- a/syclops/__example_assets__/example_job.syclops.yaml +++ b/syclops/__example_assets__/example_job.syclops.yaml @@ -32,7 +32,6 @@ textures: num_textures: 2 ops: - perlin: - res: 4 octaves: 4 - math_expression: "((x-0.5) * 100 + 65535 / 2)/65535" diff --git a/syclops/preprocessing/texture_processor.py b/syclops/preprocessing/texture_processor.py index 6b41eec..936d532 100644 --- a/syclops/preprocessing/texture_processor.py +++ b/syclops/preprocessing/texture_processor.py @@ -3,7 +3,6 @@ import cv2 import numpy as np import ruamel.yaml as yaml -from perlin_numpy import generate_fractal_noise_2d, generate_perlin_noise_2d def read_yaml(path: Path) -> dict: @@ -15,16 +14,65 @@ def read_yaml(path: Path) -> dict: return None +def fade(t): + return 6 * t**5 - 15 * t**4 + 10 * t**3 + + +def lerp(a, b, t): + return a + (b - a) * t + + +def gradient(h, x, y): + vectors = np.array([[0, 1], [0, -1], [1, 0], [-1, 0]]) + g = vectors[h % 4] + return g[:, :, 0] * x + g[:, :, 1] * y + + +def perlin_octave(shape, frequency, amplitude): + x = np.linspace(0, frequency, shape[1], endpoint=False) + y = np.linspace(0, frequency, shape[0], endpoint=False) + y = y.reshape(-1, 1) + + grid_x, grid_y = np.meshgrid(x, y) + + p = np.arange(256, dtype=int) + np.random.shuffle(p) + p = np.stack([p, p]).flatten() + + xi = grid_x.astype(int) + yi = grid_y.astype(int) + xf = grid_x - xi + yf = grid_y - yi + + u = fade(xf) + v = fade(yf) + + n00 = gradient(p[p[xi] + yi], xf, yf) + n01 = gradient(p[p[xi] + yi + 1], xf, yf - 1) + n11 = gradient(p[p[xi + 1] + yi + 1], xf - 1, yf - 1) + n10 = gradient(p[p[xi + 1] + yi], xf - 1, yf) + + x1 = lerp(n00, n10, u) + x2 = lerp(n01, n11, u) + return lerp(x1, x2, v) * amplitude + + def perlin(texture: np.ndarray, config: dict, textures: dict, current_frame: int): """Generate Perlin Noise""" - res = config["res"] octaves = config["octaves"] - texture = generate_fractal_noise_2d( - shape=texture.shape, res=(res, res), octaves=octaves - ) - texture = (texture + 1) / 2 - # Clip the texture to 0-1 - texture = np.clip(texture, 0, 1) + persistence = config.get("persistence", 0.5) + lacunarity = config.get("lacunarity", 2.0) + + shape = texture.shape + noise = np.zeros(shape) + frequency = 1 + amplitude = 1 + for _ in range(octaves): + noise += perlin_octave(shape, frequency, amplitude) + frequency *= lacunarity + amplitude *= persistence + + texture[:] = np.clip(noise, -1, 1) * 0.5 + 0.5 return texture @@ -167,9 +215,10 @@ def process_texture(tex_name: str, tex_dict: dict, textures: dict, current_frame image_size = tex_dict["config"]["image_size"] texture = np.zeros((image_size[0], image_size[1]), np.float32) - # Set numpy seed - if "seed" in tex_dict["config"]: - np.random.seed(tex_dict["config"]["seed"]) + # Set numpy random seed + seed = tex_dict["config"].get("seed", None) + if seed is not None: + np.random.seed(seed) for operation in tex_dict["ops"]: operation_name = list(operation.keys())[0] diff --git a/syclops/schema/base_schema.yaml b/syclops/schema/base_schema.yaml index 47529ec..7a5e5d7 100644 --- a/syclops/schema/base_schema.yaml +++ b/syclops/schema/base_schema.yaml @@ -360,11 +360,9 @@ definitions: description: Create a Perlin noise texture type: object properties: - res: - type: integer octaves: type: integer - required: [res, octaves] + required: [octaves] additionalProperties: false additionalProperties: false