sparc-visualization 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sparc_visualization-0.1.0/LICENCE.txt +7 -0
- sparc_visualization-0.1.0/PKG-INFO +229 -0
- sparc_visualization-0.1.0/README.md +210 -0
- sparc_visualization-0.1.0/pyproject.toml +27 -0
- sparc_visualization-0.1.0/sparc_visualization/__init__.py +0 -0
- sparc_visualization-0.1.0/sparc_visualization/objects/board.py +50 -0
- sparc_visualization-0.1.0/sparc_visualization/objects/tile.py +35 -0
- sparc_visualization-0.1.0/sparc_visualization/plot.py +63 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/black_frame_plot.py +59 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/coordinate_grid_plot.py +97 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/low_contrast_plot.py +85 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/low_resolution_plot.py +69 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/original_plot.py +334 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/path_cell_annotation_plot.py +66 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/plot.py +166 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/rotated_plot.py +91 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/start_end_marked_plot.py +58 -0
- sparc_visualization-0.1.0/sparc_visualization/plots/text_plot.py +229 -0
- sparc_visualization-0.1.0/sparc_visualization/prompt.py +18 -0
- sparc_visualization-0.1.0/sparc_visualization/prompts/default.py +38 -0
- sparc_visualization-0.1.0/sparc_visualization/prompts/prompt_engineering.py +55 -0
- sparc_visualization-0.1.0/sparc_visualization/prompts/prompts.py +31 -0
- sparc_visualization-0.1.0/sparc_visualization/util.py +15 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright (c) 2025 Florian Valentin Wunderlich
|
|
2
|
+
|
|
3
|
+
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:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
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.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sparc-visualization
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary:
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENCE.txt
|
|
7
|
+
Author: Florian Valentin Wunderlich
|
|
8
|
+
Author-email: florian.valentin.wunderlich@gmail.com
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Requires-Dist: Pillow (>=12)
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
SPaRC (sparc-puzzle) provides a comprehensive framework for evaluating language models on spatial reasoning tasks inspired by "The Witness" puzzle game.
|
|
22
|
+
This package (sparc-visualization) includes various visual puzzle representations and an improved visual reasoning prompt to complement the functionality of the sparc-puzzle package.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
Install the package from PyPI:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install sparc-visualization
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or install from source:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/flowun/sparc-visualization.git
|
|
36
|
+
cd sparc-visualization
|
|
37
|
+
pip install -e .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Example Usage
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from sparc_visualization.plot import get_puzzle_image
|
|
47
|
+
from sparc_visualization.prompt import generate_prompt
|
|
48
|
+
from sparc.validation import extract_solution_path, validate_solution, analyze_path
|
|
49
|
+
from datasets import load_dataset
|
|
50
|
+
|
|
51
|
+
# Load the dataset
|
|
52
|
+
dataset = load_dataset("lkaesberg/SPaRC", "all", split="test")
|
|
53
|
+
puzzle = dataset[0]
|
|
54
|
+
|
|
55
|
+
puzzle_image = get_puzzle_image(puzzle, plot_type="path_cell_annotated")
|
|
56
|
+
|
|
57
|
+
# Generate prompt and image, e.g.
|
|
58
|
+
plot_type = "path_cell_annotated"
|
|
59
|
+
prompt_type = "prompt_engineering"
|
|
60
|
+
|
|
61
|
+
b64_image = get_puzzle_image(puzzle, plot_type=plot_type, base_64_image=True)
|
|
62
|
+
text_prompt = generate_prompt(puzzle, plot_type, prompt_type)
|
|
63
|
+
|
|
64
|
+
# create message array and payload for an LLM
|
|
65
|
+
puzzle_prompt = [
|
|
66
|
+
{
|
|
67
|
+
"role": "user",
|
|
68
|
+
"content": [
|
|
69
|
+
{
|
|
70
|
+
"type": "image_url",
|
|
71
|
+
"image_url": {
|
|
72
|
+
"url": f"data:image/png;base64,{b64_image}"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"type": "text",
|
|
77
|
+
"text": text_prompt
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
payload = {
|
|
84
|
+
"model": your_model_name,
|
|
85
|
+
"messages": puzzle_prompt,
|
|
86
|
+
"temperature": temperature,
|
|
87
|
+
"max_tokens": max_tokens,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Your model generates a response
|
|
91
|
+
model_response = "... model response with path coordinates ..."
|
|
92
|
+
|
|
93
|
+
# Analysis using sparc-puzzle package
|
|
94
|
+
|
|
95
|
+
# Extract the path from model response
|
|
96
|
+
extracted_path = extract_solution_path(model_response, puzzle)
|
|
97
|
+
# Returns: [{"x": 0, "y": 2}, {"x": 0, "y": 1}, ...]
|
|
98
|
+
|
|
99
|
+
# Validate against ground truth
|
|
100
|
+
is_correct = validate_solution(extracted_path, puzzle)
|
|
101
|
+
# Returns: True/False
|
|
102
|
+
|
|
103
|
+
# Get detailed analysis
|
|
104
|
+
analysis = analyze_path(extracted_path, puzzle)
|
|
105
|
+
# Returns: {
|
|
106
|
+
# "starts_at_start_ends_at_exit": True,
|
|
107
|
+
# "connected_line": True,
|
|
108
|
+
# "non_intersecting_line": True,
|
|
109
|
+
# "no_rule_crossing": True,
|
|
110
|
+
# "fully_valid_path": True
|
|
111
|
+
# }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Core Functions
|
|
115
|
+
|
|
116
|
+
`get_puzzle_image(puzzle: Dict, plot_type: str = "original", base_64_image: bool = False, show_plot: bool = False, save_to_disk: bool = False, save_dir: str = ".", save_filename: str = "puzzle_image.png") -> PIL.Image.Image | str`
|
|
117
|
+
Renders a SPaRC puzzle into one of the supported visual representations (`plot_type` values). To get a base64-encoded string of the image suitable for LLM input, set `base_64_image=True`.
|
|
118
|
+
Besides returning the image object or base64 string, the function has options to display the image (`show_plot=True`) or save it to disk (`save_to_disk=True`).
|
|
119
|
+
|
|
120
|
+
`generate_prompt(puzzle: Dict, plot_type: str = "original", prompt_type: str = "prompt_engineering") -> str`
|
|
121
|
+
Generates the text prompt (based on `prompt_type` values) that should be paired with the rendered image for an LLM call.
|
|
122
|
+
Available `prompt_type` values are:
|
|
123
|
+
- "default_tr": visual prompt from the SPaRC paper (with textual coordinates)
|
|
124
|
+
- "default_no_tr": visual prompt from the SPaRC paper (however with textual coordinates removed)
|
|
125
|
+
- "prompt_engineering": improved vision-only prompt with prompt engineering (no textual coordinates)
|
|
126
|
+
`puzzle` and `plot_type` should be provided the same as in `get_puzzle_image` to allow small prompt adjustments.
|
|
127
|
+
|
|
128
|
+
### Available Puzzle Representations (`plot_type`)
|
|
129
|
+
|
|
130
|
+
<table>
|
|
131
|
+
<tr>
|
|
132
|
+
<td align="center">
|
|
133
|
+
<code>original</code><br/>
|
|
134
|
+
<img src="docs/images/original.png" alt="original" width="200" />
|
|
135
|
+
</td>
|
|
136
|
+
<td align="center">
|
|
137
|
+
<code>start_end_marked</code><br/>
|
|
138
|
+
<img src="docs/images/start_end_marked.png" alt="start_end_marked" width="200" />
|
|
139
|
+
</td>
|
|
140
|
+
<td align="center">
|
|
141
|
+
<code>coordinate_grid</code><br/>
|
|
142
|
+
<img src="docs/images/coordinate_grid.png" alt="coordinate_grid" width="200" />
|
|
143
|
+
</td>
|
|
144
|
+
</tr>
|
|
145
|
+
<tr>
|
|
146
|
+
<td align="center">
|
|
147
|
+
<code>coordinate_grid_and_start_end_marked</code><br/>
|
|
148
|
+
<img src="docs/images/coordinate_grid_and_start_end_marked.png" alt="coordinate_grid_and_start_end_marked" width="200" />
|
|
149
|
+
</td>
|
|
150
|
+
<td align="center">
|
|
151
|
+
<code>path_cell_annotated</code><br/>
|
|
152
|
+
<img src="docs/images/path_cell_annotated.png" alt="path_cell_annotated" width="200" />
|
|
153
|
+
</td>
|
|
154
|
+
<td align="center">
|
|
155
|
+
<code>text</code><br/>
|
|
156
|
+
<img src="docs/images/text.png" alt="text" width="200" />
|
|
157
|
+
</td>
|
|
158
|
+
</tr>
|
|
159
|
+
<tr>
|
|
160
|
+
<td align="center">
|
|
161
|
+
<code>low_contrast</code><br/>
|
|
162
|
+
<img src="docs/images/low_contrast.png" alt="low_contrast" width="200" />
|
|
163
|
+
</td>
|
|
164
|
+
<td align="center">
|
|
165
|
+
<code>low_contrast_and_path_cell_annotated</code><br/>
|
|
166
|
+
<img src="docs/images/low_contrast_and_path_cell_annotated.png" alt="low_contrast_and_path_cell_annotated" width="200" />
|
|
167
|
+
</td>
|
|
168
|
+
<td align="center">
|
|
169
|
+
<code>low_resolution</code><br/>
|
|
170
|
+
<img src="docs/images/low_resolution.png" alt="low_resolution" width="200" />
|
|
171
|
+
</td>
|
|
172
|
+
</tr>
|
|
173
|
+
<tr>
|
|
174
|
+
<td align="center">
|
|
175
|
+
<code>low_resolution_and_path_cell_annotated</code><br/>
|
|
176
|
+
<img src="docs/images/low_resolution_and_path_cell_annotated.png" alt="low_resolution_and_path_cell_annotated" width="200" />
|
|
177
|
+
</td>
|
|
178
|
+
<td align="center">
|
|
179
|
+
<code>rotated</code><br/>
|
|
180
|
+
<img src="docs/images/rotated.png" alt="rotated" width="200" />
|
|
181
|
+
</td>
|
|
182
|
+
<td align="center">
|
|
183
|
+
<code>rotated_and_path_cell_annotated</code><br/>
|
|
184
|
+
<img src="docs/images/rotated_and_path_cell_annotated.png" alt="rotated_and_path_cell_annotated" width="200" />
|
|
185
|
+
</td>
|
|
186
|
+
</tr>
|
|
187
|
+
<tr>
|
|
188
|
+
<td align="center">
|
|
189
|
+
<code>black_frame</code><br/>
|
|
190
|
+
<img src="docs/images/black_frame.png" alt="black_frame" width="200" />
|
|
191
|
+
</td>
|
|
192
|
+
<td align="center">
|
|
193
|
+
<code>black_frame_and_path_cell_annotated</code><br/>
|
|
194
|
+
<img src="docs/images/black_frame_and_path_cell_annotated.png" alt="black_frame_and_path_cell_annotated" width="200" />
|
|
195
|
+
</td>
|
|
196
|
+
<td></td>
|
|
197
|
+
</tr>
|
|
198
|
+
</table>
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
## Contributing
|
|
202
|
+
|
|
203
|
+
Contributions are welcome! Please feel free to submit pull requests or open issues.
|
|
204
|
+
|
|
205
|
+
## Citation
|
|
206
|
+
|
|
207
|
+
If you use SPaRC in your research, please cite:
|
|
208
|
+
|
|
209
|
+
```bibtex
|
|
210
|
+
@article{kaesberg2025sparc,
|
|
211
|
+
title = {SPaRC: A Spatial Pathfinding Reasoning Challenge},
|
|
212
|
+
author = {Kaesberg, Lars Benedikt and Wahle, Jan Philip and Ruas, Terry and Gipp, Bela},
|
|
213
|
+
year = {2025},
|
|
214
|
+
url = {https://arxiv.org/abs/2505.16686}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
221
|
+
|
|
222
|
+
## Links
|
|
223
|
+
|
|
224
|
+
- 🌐 **Website**: [sparc.gipplab.org](https://sparc.gipplab.org/)
|
|
225
|
+
- 📚 **Dataset**: [Hugging Face](https://huggingface.co/datasets/lkaesberg/SPaRC)
|
|
226
|
+
- 🐛 **Issues**: [GitHub Issues](https://github.com/flowun/sparc-visualization/issues)
|
|
227
|
+
- 📖 **Documentation**: [GitHub Repository](https://github.com/flowun/sparc-visualization)
|
|
228
|
+
|
|
229
|
+
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
|
|
3
|
+
SPaRC (sparc-puzzle) provides a comprehensive framework for evaluating language models on spatial reasoning tasks inspired by "The Witness" puzzle game.
|
|
4
|
+
This package (sparc-visualization) includes various visual puzzle representations and an improved visual reasoning prompt to complement the functionality of the sparc-puzzle package.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Install the package from PyPI:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install sparc-visualization
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or install from source:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git clone https://github.com/flowun/sparc-visualization.git
|
|
18
|
+
cd sparc-visualization
|
|
19
|
+
pip install -e .
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Example Usage
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from sparc_visualization.plot import get_puzzle_image
|
|
29
|
+
from sparc_visualization.prompt import generate_prompt
|
|
30
|
+
from sparc.validation import extract_solution_path, validate_solution, analyze_path
|
|
31
|
+
from datasets import load_dataset
|
|
32
|
+
|
|
33
|
+
# Load the dataset
|
|
34
|
+
dataset = load_dataset("lkaesberg/SPaRC", "all", split="test")
|
|
35
|
+
puzzle = dataset[0]
|
|
36
|
+
|
|
37
|
+
puzzle_image = get_puzzle_image(puzzle, plot_type="path_cell_annotated")
|
|
38
|
+
|
|
39
|
+
# Generate prompt and image, e.g.
|
|
40
|
+
plot_type = "path_cell_annotated"
|
|
41
|
+
prompt_type = "prompt_engineering"
|
|
42
|
+
|
|
43
|
+
b64_image = get_puzzle_image(puzzle, plot_type=plot_type, base_64_image=True)
|
|
44
|
+
text_prompt = generate_prompt(puzzle, plot_type, prompt_type)
|
|
45
|
+
|
|
46
|
+
# create message array and payload for an LLM
|
|
47
|
+
puzzle_prompt = [
|
|
48
|
+
{
|
|
49
|
+
"role": "user",
|
|
50
|
+
"content": [
|
|
51
|
+
{
|
|
52
|
+
"type": "image_url",
|
|
53
|
+
"image_url": {
|
|
54
|
+
"url": f"data:image/png;base64,{b64_image}"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "text",
|
|
59
|
+
"text": text_prompt
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
payload = {
|
|
66
|
+
"model": your_model_name,
|
|
67
|
+
"messages": puzzle_prompt,
|
|
68
|
+
"temperature": temperature,
|
|
69
|
+
"max_tokens": max_tokens,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Your model generates a response
|
|
73
|
+
model_response = "... model response with path coordinates ..."
|
|
74
|
+
|
|
75
|
+
# Analysis using sparc-puzzle package
|
|
76
|
+
|
|
77
|
+
# Extract the path from model response
|
|
78
|
+
extracted_path = extract_solution_path(model_response, puzzle)
|
|
79
|
+
# Returns: [{"x": 0, "y": 2}, {"x": 0, "y": 1}, ...]
|
|
80
|
+
|
|
81
|
+
# Validate against ground truth
|
|
82
|
+
is_correct = validate_solution(extracted_path, puzzle)
|
|
83
|
+
# Returns: True/False
|
|
84
|
+
|
|
85
|
+
# Get detailed analysis
|
|
86
|
+
analysis = analyze_path(extracted_path, puzzle)
|
|
87
|
+
# Returns: {
|
|
88
|
+
# "starts_at_start_ends_at_exit": True,
|
|
89
|
+
# "connected_line": True,
|
|
90
|
+
# "non_intersecting_line": True,
|
|
91
|
+
# "no_rule_crossing": True,
|
|
92
|
+
# "fully_valid_path": True
|
|
93
|
+
# }
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Core Functions
|
|
97
|
+
|
|
98
|
+
`get_puzzle_image(puzzle: Dict, plot_type: str = "original", base_64_image: bool = False, show_plot: bool = False, save_to_disk: bool = False, save_dir: str = ".", save_filename: str = "puzzle_image.png") -> PIL.Image.Image | str`
|
|
99
|
+
Renders a SPaRC puzzle into one of the supported visual representations (`plot_type` values). To get a base64-encoded string of the image suitable for LLM input, set `base_64_image=True`.
|
|
100
|
+
Besides returning the image object or base64 string, the function has options to display the image (`show_plot=True`) or save it to disk (`save_to_disk=True`).
|
|
101
|
+
|
|
102
|
+
`generate_prompt(puzzle: Dict, plot_type: str = "original", prompt_type: str = "prompt_engineering") -> str`
|
|
103
|
+
Generates the text prompt (based on `prompt_type` values) that should be paired with the rendered image for an LLM call.
|
|
104
|
+
Available `prompt_type` values are:
|
|
105
|
+
- "default_tr": visual prompt from the SPaRC paper (with textual coordinates)
|
|
106
|
+
- "default_no_tr": visual prompt from the SPaRC paper (however with textual coordinates removed)
|
|
107
|
+
- "prompt_engineering": improved vision-only prompt with prompt engineering (no textual coordinates)
|
|
108
|
+
`puzzle` and `plot_type` should be provided the same as in `get_puzzle_image` to allow small prompt adjustments.
|
|
109
|
+
|
|
110
|
+
### Available Puzzle Representations (`plot_type`)
|
|
111
|
+
|
|
112
|
+
<table>
|
|
113
|
+
<tr>
|
|
114
|
+
<td align="center">
|
|
115
|
+
<code>original</code><br/>
|
|
116
|
+
<img src="docs/images/original.png" alt="original" width="200" />
|
|
117
|
+
</td>
|
|
118
|
+
<td align="center">
|
|
119
|
+
<code>start_end_marked</code><br/>
|
|
120
|
+
<img src="docs/images/start_end_marked.png" alt="start_end_marked" width="200" />
|
|
121
|
+
</td>
|
|
122
|
+
<td align="center">
|
|
123
|
+
<code>coordinate_grid</code><br/>
|
|
124
|
+
<img src="docs/images/coordinate_grid.png" alt="coordinate_grid" width="200" />
|
|
125
|
+
</td>
|
|
126
|
+
</tr>
|
|
127
|
+
<tr>
|
|
128
|
+
<td align="center">
|
|
129
|
+
<code>coordinate_grid_and_start_end_marked</code><br/>
|
|
130
|
+
<img src="docs/images/coordinate_grid_and_start_end_marked.png" alt="coordinate_grid_and_start_end_marked" width="200" />
|
|
131
|
+
</td>
|
|
132
|
+
<td align="center">
|
|
133
|
+
<code>path_cell_annotated</code><br/>
|
|
134
|
+
<img src="docs/images/path_cell_annotated.png" alt="path_cell_annotated" width="200" />
|
|
135
|
+
</td>
|
|
136
|
+
<td align="center">
|
|
137
|
+
<code>text</code><br/>
|
|
138
|
+
<img src="docs/images/text.png" alt="text" width="200" />
|
|
139
|
+
</td>
|
|
140
|
+
</tr>
|
|
141
|
+
<tr>
|
|
142
|
+
<td align="center">
|
|
143
|
+
<code>low_contrast</code><br/>
|
|
144
|
+
<img src="docs/images/low_contrast.png" alt="low_contrast" width="200" />
|
|
145
|
+
</td>
|
|
146
|
+
<td align="center">
|
|
147
|
+
<code>low_contrast_and_path_cell_annotated</code><br/>
|
|
148
|
+
<img src="docs/images/low_contrast_and_path_cell_annotated.png" alt="low_contrast_and_path_cell_annotated" width="200" />
|
|
149
|
+
</td>
|
|
150
|
+
<td align="center">
|
|
151
|
+
<code>low_resolution</code><br/>
|
|
152
|
+
<img src="docs/images/low_resolution.png" alt="low_resolution" width="200" />
|
|
153
|
+
</td>
|
|
154
|
+
</tr>
|
|
155
|
+
<tr>
|
|
156
|
+
<td align="center">
|
|
157
|
+
<code>low_resolution_and_path_cell_annotated</code><br/>
|
|
158
|
+
<img src="docs/images/low_resolution_and_path_cell_annotated.png" alt="low_resolution_and_path_cell_annotated" width="200" />
|
|
159
|
+
</td>
|
|
160
|
+
<td align="center">
|
|
161
|
+
<code>rotated</code><br/>
|
|
162
|
+
<img src="docs/images/rotated.png" alt="rotated" width="200" />
|
|
163
|
+
</td>
|
|
164
|
+
<td align="center">
|
|
165
|
+
<code>rotated_and_path_cell_annotated</code><br/>
|
|
166
|
+
<img src="docs/images/rotated_and_path_cell_annotated.png" alt="rotated_and_path_cell_annotated" width="200" />
|
|
167
|
+
</td>
|
|
168
|
+
</tr>
|
|
169
|
+
<tr>
|
|
170
|
+
<td align="center">
|
|
171
|
+
<code>black_frame</code><br/>
|
|
172
|
+
<img src="docs/images/black_frame.png" alt="black_frame" width="200" />
|
|
173
|
+
</td>
|
|
174
|
+
<td align="center">
|
|
175
|
+
<code>black_frame_and_path_cell_annotated</code><br/>
|
|
176
|
+
<img src="docs/images/black_frame_and_path_cell_annotated.png" alt="black_frame_and_path_cell_annotated" width="200" />
|
|
177
|
+
</td>
|
|
178
|
+
<td></td>
|
|
179
|
+
</tr>
|
|
180
|
+
</table>
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
## Contributing
|
|
184
|
+
|
|
185
|
+
Contributions are welcome! Please feel free to submit pull requests or open issues.
|
|
186
|
+
|
|
187
|
+
## Citation
|
|
188
|
+
|
|
189
|
+
If you use SPaRC in your research, please cite:
|
|
190
|
+
|
|
191
|
+
```bibtex
|
|
192
|
+
@article{kaesberg2025sparc,
|
|
193
|
+
title = {SPaRC: A Spatial Pathfinding Reasoning Challenge},
|
|
194
|
+
author = {Kaesberg, Lars Benedikt and Wahle, Jan Philip and Ruas, Terry and Gipp, Bela},
|
|
195
|
+
year = {2025},
|
|
196
|
+
url = {https://arxiv.org/abs/2505.16686}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
203
|
+
|
|
204
|
+
## Links
|
|
205
|
+
|
|
206
|
+
- 🌐 **Website**: [sparc.gipplab.org](https://sparc.gipplab.org/)
|
|
207
|
+
- 📚 **Dataset**: [Hugging Face](https://huggingface.co/datasets/lkaesberg/SPaRC)
|
|
208
|
+
- 🐛 **Issues**: [GitHub Issues](https://github.com/flowun/sparc-visualization/issues)
|
|
209
|
+
- 📖 **Documentation**: [GitHub Repository](https://github.com/flowun/sparc-visualization)
|
|
210
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "sparc-visualization"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = ""
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "Florian Valentin Wunderlich",email = "florian.valentin.wunderlich@gmail.com"}
|
|
7
|
+
]
|
|
8
|
+
license = "MIT"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"Pillow>=12",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[tool.poetry]
|
|
16
|
+
name = "sparc-visualization"
|
|
17
|
+
description = ""
|
|
18
|
+
authors = ["Florian Valentin Wunderlich <florian.valentin.wunderlich@gmail.com>"]
|
|
19
|
+
readme = "README.md"
|
|
20
|
+
|
|
21
|
+
[tool.poetry.dependencies]
|
|
22
|
+
python = "^3.10"
|
|
23
|
+
Pillow = ">=12"
|
|
24
|
+
|
|
25
|
+
[build-system]
|
|
26
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
27
|
+
build-backend = "poetry.core.masonry.api"
|
|
File without changes
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from sparc_visualization.objects.tile import Tile
|
|
4
|
+
|
|
5
|
+
def get_board_from_data(data):
|
|
6
|
+
return Board(
|
|
7
|
+
height=data['grid_size']['height'],
|
|
8
|
+
width=data['grid_size']['width'],
|
|
9
|
+
difficulty_level=data['difficulty_level'],
|
|
10
|
+
difficulty_score=data['difficulty_score'],
|
|
11
|
+
id=data['id'],
|
|
12
|
+
polyshapes=data['polyshapes'],
|
|
13
|
+
puzzle_array=data['puzzle_array'],
|
|
14
|
+
solution_count=data['solution_count'],
|
|
15
|
+
solutions=data['solutions']
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Board:
|
|
20
|
+
def __init__(self, height, width, difficulty_level, difficulty_score, id, polyshapes, puzzle_array, solution_count, solutions):
|
|
21
|
+
self.height = height * 2 + 1
|
|
22
|
+
self.width = width * 2 + 1
|
|
23
|
+
self.difficulty_level = difficulty_level
|
|
24
|
+
self.difficulty_score = difficulty_score
|
|
25
|
+
self.id = id
|
|
26
|
+
self.polyshapes = json.loads(polyshapes)
|
|
27
|
+
self.puzzle_array = puzzle_array
|
|
28
|
+
self.solution_count = solution_count
|
|
29
|
+
self.solutions = solutions
|
|
30
|
+
self.grid = [[None for _ in range(self.width)] for _ in range(self.height)]
|
|
31
|
+
self.place_all_objects()
|
|
32
|
+
|
|
33
|
+
def place_object(self, x, y, obj):
|
|
34
|
+
if 0 <= x < self.width and 0 <= y < self.height:
|
|
35
|
+
self.grid[y][x] = obj
|
|
36
|
+
else:
|
|
37
|
+
raise ValueError("Coordinates out of bounds")
|
|
38
|
+
|
|
39
|
+
def place_all_objects(self):
|
|
40
|
+
for y in range(self.height):
|
|
41
|
+
for x in range(self.width):
|
|
42
|
+
obj_abbr = self.puzzle_array[y][x]
|
|
43
|
+
obj = Tile(obj_abbr)
|
|
44
|
+
self.place_object(x, y, obj)
|
|
45
|
+
|
|
46
|
+
def get_object(self, x, y):
|
|
47
|
+
if 0 <= x < self.width and 0 <= y < self.height:
|
|
48
|
+
return self.grid[y][x]
|
|
49
|
+
else:
|
|
50
|
+
raise ValueError("Coordinates out of bounds")
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
def get_type_from_abbreviation(abbreviation):
|
|
2
|
+
translation_dict = {
|
|
3
|
+
'S': 'Start',
|
|
4
|
+
'E': 'End',
|
|
5
|
+
'+': 'Walkable',
|
|
6
|
+
'N': 'Empty Rule',
|
|
7
|
+
'G': 'Gap',
|
|
8
|
+
'.': 'Dot',
|
|
9
|
+
'o': 'Stone',
|
|
10
|
+
'*': 'Star',
|
|
11
|
+
'A': 'Triangle',
|
|
12
|
+
'B': 'Triangle',
|
|
13
|
+
'C': 'Triangle',
|
|
14
|
+
'D': 'Triangle',
|
|
15
|
+
'P': 'Positive Polyshape',
|
|
16
|
+
'Y': 'Negative Polyshape'
|
|
17
|
+
}
|
|
18
|
+
return translation_dict[abbreviation]
|
|
19
|
+
|
|
20
|
+
class Tile:
|
|
21
|
+
def __init__(self, abbreviation):
|
|
22
|
+
self.abbreviation = abbreviation
|
|
23
|
+
self.is_walkable = abbreviation in ['S', 'E', '+', '.']
|
|
24
|
+
self.is_rule_cell = abbreviation.startswith(('N', 'o', '*', 'A', 'B', 'C', 'D', 'P', 'Y'))
|
|
25
|
+
self.type = get_type_from_abbreviation(abbreviation[0])
|
|
26
|
+
self.color = None
|
|
27
|
+
self.shape_id = None
|
|
28
|
+
if '-' in abbreviation:
|
|
29
|
+
self.color = abbreviation.split('-')[1]
|
|
30
|
+
if self.abbreviation.startswith(('P', 'Y')):
|
|
31
|
+
parts = abbreviation.split('-')
|
|
32
|
+
self.shape_id = parts[2]
|
|
33
|
+
if self.abbreviation.startswith(('A', 'B', 'C', 'D')):
|
|
34
|
+
self.triangle_count = {'A': 1, 'B': 2, 'C': 3, 'D': 4}[abbreviation[0]]
|
|
35
|
+
# print(f"Created Tile: {self.name}, Walkable: {self.is_walkable}")
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from sparc_visualization.plots.plot import get_plot_class
|
|
2
|
+
from sparc_visualization.objects.board import get_board_from_data
|
|
3
|
+
from sparc_visualization.util import encode_image_to_base64
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_puzzle_image(
|
|
7
|
+
puzzle,
|
|
8
|
+
plot_type="original",
|
|
9
|
+
base_64_image=False,
|
|
10
|
+
show_plot=False,
|
|
11
|
+
save_to_disk=False,
|
|
12
|
+
save_dir=".",
|
|
13
|
+
save_filename="puzzle_image.png",
|
|
14
|
+
):
|
|
15
|
+
"""Render a SPaRC puzzle and return it as a PIL image (or base64).
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
puzzle:
|
|
20
|
+
The puzzle data of a single SPaRC puzzle.
|
|
21
|
+
plot_type:
|
|
22
|
+
- "original" (default)
|
|
23
|
+
- "start_end_marked"
|
|
24
|
+
- "coordinate_grid"
|
|
25
|
+
- "coordinate_grid_and_start_end_marked"
|
|
26
|
+
- "path_cell_annotated"
|
|
27
|
+
- "text"
|
|
28
|
+
- "low_contrast"
|
|
29
|
+
- "low_contrast_and_path_cell_annotated"
|
|
30
|
+
- "low_resolution"
|
|
31
|
+
- "low_resolution_and_path_cell_annotated"
|
|
32
|
+
- "rotated"
|
|
33
|
+
- "rotated_and_path_cell_annotated"
|
|
34
|
+
- "black_frame"
|
|
35
|
+
- "black_frame_and_path_cell_annotated"
|
|
36
|
+
base_64_image:
|
|
37
|
+
If True, returns a base64-encoded string instead of a PIL Image.
|
|
38
|
+
show_plot:
|
|
39
|
+
If True, shows the plot in a GUI window.
|
|
40
|
+
save_to_disk:
|
|
41
|
+
If True, saves the plot to disk.
|
|
42
|
+
save_dir:
|
|
43
|
+
Directory to save the plot if ``save_to_disk=True``.
|
|
44
|
+
save_filename:
|
|
45
|
+
Filename to save the plot if ``save_to_disk=True``.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
PIL.Image.Image | str
|
|
50
|
+
Either a PIL Image (default) or a base64-encoded string if ``base_64_image=True``.
|
|
51
|
+
"""
|
|
52
|
+
board = get_board_from_data(puzzle)
|
|
53
|
+
plot = get_plot_class(plot_type, board, size=(board.width, board.height))
|
|
54
|
+
plot.render()
|
|
55
|
+
if save_to_disk:
|
|
56
|
+
plot.save(dir=save_dir, filename=save_filename)
|
|
57
|
+
if show_plot:
|
|
58
|
+
plot.show()
|
|
59
|
+
if base_64_image:
|
|
60
|
+
return encode_image_to_base64(plot._img)
|
|
61
|
+
else:
|
|
62
|
+
return plot._img
|
|
63
|
+
|