Skip to content

Commit 5179000

Browse files
Generate animations for new/modified datasets/shapes (#222)
--------- Signed-off-by: Daniel Schaefer <[email protected]> Co-authored-by: Stefanie Molin <[email protected]>
1 parent f231a66 commit 5179000

File tree

4 files changed

+159
-1
lines changed

4 files changed

+159
-1
lines changed

.github/workflows/check-pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- name: Set up Python
2626
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
2727
with:
28-
python-version: "3.11"
28+
python-version: "3.x"
2929

3030
- name: Install Dependencies
3131
run: |

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ on:
1212
branches: [ "main" ]
1313
paths:
1414
- '**'
15+
- '!bin/**'
1516
- '!docs/**'
1617
- '!.github/**'
1718
- '.github/workflows/ci.yml'
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# This workflow runs Data Morph on datasets and/or shapes that have
2+
# been added or modified.
3+
#
4+
# Author: Stefanie Molin, Daniel Schaefer
5+
6+
name: Generate Morphs
7+
8+
on:
9+
pull_request:
10+
paths:
11+
- 'src/**'
12+
- 'pyproject.toml'
13+
- '.github/workflows/generate-morphs.yml'
14+
15+
concurrency:
16+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
generate-morphs:
21+
name: Run Data Morph on new/altered datasets/shapes
22+
23+
# Just generate on one operating system (they should all be the same)
24+
runs-on: ubuntu-latest
25+
26+
defaults:
27+
run:
28+
shell: bash -e {0}
29+
30+
strategy:
31+
fail-fast: false
32+
33+
steps:
34+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
35+
36+
- name: Set up Python
37+
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
38+
with:
39+
python-version: "3.x"
40+
41+
- name: Install Data Morph
42+
run: |
43+
python -m pip install --upgrade pip
44+
python -m pip install setuptools --upgrade
45+
python -m pip install .
46+
47+
# docs for this action: https://github.com/tj-actions/changed-files
48+
- name: Get all dataset and shape files that have changed
49+
id: changed-files-yaml
50+
uses: tj-actions/changed-files@4edd678ac3f81e2dc578756871e4d00c19191daf # v45.0.4
51+
with:
52+
files_yaml: |
53+
dataset:
54+
- src/data_morph/data/starter_shapes/*
55+
shape:
56+
- src/data_morph/shapes/**
57+
58+
# If datasets were added or changed in this PR
59+
- name: Generate morphs from new or changed datasets
60+
if: steps.changed-files-yaml.outputs.dataset_any_changed == 'true'
61+
env:
62+
DATASET_ALL_CHANGED_FILES: ${{ steps.changed-files-yaml.outputs.dataset_all_changed_files }}
63+
run: |
64+
echo "Detected changes to dataset(s): $DATASET_ALL_CHANGED_FILES"
65+
DATASET_ARGS=$(python bin/ci.py $DATASET_ALL_CHANGED_FILES)
66+
echo "Generating morphs for the following datasets: $DATASET_ARGS"
67+
parallel -j0 data-morph \
68+
--start-shape $DATASET_ARGS \
69+
--target-shape {} \
70+
::: bullseye heart rectangle star slant_up
71+
72+
# If shapes are added or modified in this PR
73+
- name: Generate morphs from new or changed shapes
74+
if: steps.changed-files-yaml.outputs.shape_any_changed == 'true'
75+
env:
76+
SHAPE_ALL_CHANGED_FILES: ${{ steps.changed-files-yaml.outputs.shape_all_changed_files }}
77+
run: |
78+
echo "Detected changes to shape(s): $SHAPE_ALL_CHANGED_FILES"
79+
SHAPE_ARGS=$(python bin/ci.py $SHAPE_ALL_CHANGED_FILES)
80+
echo "Generating morphs for the following shapes: $SHAPE_ARGS"
81+
parallel -j0 data-morph \
82+
--start-shape music \
83+
--target-shape {} \
84+
::: $SHAPE_ARGS
85+
86+
# For core code changes, we want to do a couple morphs to see if they still look ok
87+
# Only need to run if neither of the previous two morphs ran
88+
- name: Morph shapes with core code changes
89+
if: steps.changed-files-yaml.outputs.dataset_any_changed != 'true' && steps.changed-files-yaml.outputs.shape_any_changed != 'true'
90+
run: |
91+
parallel -j0 data-morph \
92+
--start-shape music \
93+
--target-shape {} \
94+
::: bullseye heart rectangle star slant_up
95+
96+
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
97+
with:
98+
name: morphed-data-pr${{ github.event.number }}-${{ github.sha }}
99+
path: morphed_data

bin/ci.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env python
2+
"""
3+
Call this script with the names of files that have changed to get the
4+
datasets and shapes to test with the CLI.
5+
6+
Examples
7+
--------
8+
9+
$ python bin/ci.py src/data_morph/shapes/circles.py
10+
bullseye circle rings
11+
12+
$ python bin/ci.py src/data_morph/shapes/bases/line_collection.py
13+
high_lines h_lines slant_down slant_up v_lines wide_lines x diamond rectangle star
14+
15+
$ python bin/ci.py src/data_morph/shapes/points/heart.py
16+
heart spade
17+
18+
$ python bin/ci.py src/data_morph/data/starter_shapes/superdatascience.csv
19+
SDS
20+
"""
21+
22+
import sys
23+
from pathlib import Path
24+
25+
from data_morph.data.loader import DataLoader
26+
from data_morph.shapes.factory import ShapeFactory
27+
28+
new_paths = sys.argv[1:]
29+
30+
args = []
31+
32+
# Figure out argument of datasets based on .csv filename
33+
for dataset, filename in DataLoader._DATASETS.items():
34+
for new_file in new_paths:
35+
if filename in new_file:
36+
args.append(dataset)
37+
38+
# Figure out argument of shapes based on .py filename
39+
new_files = [Path(x).name for x in new_paths]
40+
for shape, shape_cls in ShapeFactory._SHAPE_MAPPING.items():
41+
# Find the class and all parent classes and get their module name
42+
# We get the module name because it ends in the Python file without .py extension
43+
mro = [
44+
x.__module__ for x in shape_cls.__mro__ if x.__module__.startswith('data_morph')
45+
]
46+
47+
if shape == 'spade':
48+
mro.append('heart')
49+
50+
all_modules = [f'{x}.py' for x in mro]
51+
52+
for new_file in new_files:
53+
for module in all_modules:
54+
if module.endswith(new_file):
55+
args.append(shape)
56+
break
57+
58+
print(' '.join(args))

0 commit comments

Comments
 (0)