Skip to content

Commit a62398b

Browse files
committed
Add some variable chapters
1 parent c59da00 commit a62398b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+4506
-17
lines changed

notebooks/Format Sequencer Source File.ipynb

Lines changed: 1467 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Make Volumetric Graphs of Sequencer"
8+
]
9+
},
10+
{
11+
"cell_type": "code",
12+
"execution_count": 1,
13+
"metadata": {},
14+
"outputs": [],
15+
"source": [
16+
"colors_base = {\n",
17+
"\"00\":\"c64_black\", \n",
18+
"\"01\":\"c64_white\", \n",
19+
"\"02\":\"c64_red\", \n",
20+
"\"03\":\"c64_cyan\", \n",
21+
"\"04\":\"c64_purple\", \n",
22+
"\"05\":\"c64_green\", \n",
23+
"\"06\":\"c64_blue\", \n",
24+
"\"07\":\"c64_yellow\", \n",
25+
"\"08\":\"c64_orange\", \n",
26+
"\"09\":\"c64_brown\", \n",
27+
"\"0a\":\"c64_ltred\", \n",
28+
"\"0b\":\"c64_gray1\", \n",
29+
"\"0c\":\"c64_lightgray\", \n",
30+
"\"0d\":\"c64_ltgreen\",\n",
31+
"\"0e\":\"c64_ltblue\", \n",
32+
"\"0f\":\"c64_gray3\", \n",
33+
"}\n",
34+
"colors = [v for k,v in colors_base.items()]\n",
35+
" \n",
36+
"c64_to_rgb = {\n",
37+
"\"c64_black\": \"#000000\", \n",
38+
"\"c64_white\": \"#ffffff\", \n",
39+
"\"c64_red\": \"#880000\", \n",
40+
"\"c64_cyan\": \"#aaffee\", \n",
41+
"\"c64_purple\": \"#cc44cc\", \n",
42+
"\"c64_green\": \"#00cc55\", \n",
43+
"#\"c64_blue\": \"#0000aa\", \n",
44+
"\"c64_blue\": \"#0088ff\", \n",
45+
"\"c64_yellow\": \"#eeee77\", \n",
46+
"\"c64_orange\": \"#dd8855\", \n",
47+
"\"c64_brown\": \"#664400\", \n",
48+
"\"c64_ltred\": \"#ff7777\", \n",
49+
"\"c64_gray1\": \"#333333\", \n",
50+
"\"c64_ltgreen\": \"#aaff66\",\n",
51+
"\"c64_ltblue\": \"#0088ff\",\n",
52+
"\"c64_lightgrey\": \"#bbbbbb\", \n",
53+
"\"c64_lightgray\": \"#bbbbbb\", \n",
54+
"\"c64_gray3\": \"#bbbbbb\", \n",
55+
"}\n"
56+
]
57+
},
58+
{
59+
"cell_type": "markdown",
60+
"metadata": {},
61+
"source": [
62+
"Run the following command:\n",
63+
"```sh\n",
64+
"~/Dev/vice-emu-code/vice/src/x64sc -directory ~/Dev/vice-emu-code/vice/data/ -moncommands painttrace.txt bin/psychedelia.prg \n",
65+
"```\n",
66+
"Where `painttrace.txt` is:\n",
67+
"\n",
68+
"```\n",
69+
"log on\n",
70+
"logname \"PsychedeliaIndividualPatterns.txt\"\n",
71+
"tr exec 0973\n",
72+
"command 1 \"mem d800 dbff\"\n",
73+
"```"
74+
]
75+
},
76+
{
77+
"cell_type": "markdown",
78+
"metadata": {},
79+
"source": [
80+
"Read in the ram history."
81+
]
82+
},
83+
{
84+
"cell_type": "code",
85+
"execution_count": 14,
86+
"metadata": {},
87+
"outputs": [],
88+
"source": [
89+
"log_file = \"PsychedeliaSequencePaintTrace.txt\"\n",
90+
"input_file = open(log_file,'r')\n",
91+
"\n",
92+
"ram_history = []\n",
93+
"lines = input_file.readlines()\n",
94+
"c = 0\n",
95+
"for i in range(5, len(lines), 67):\n",
96+
" raw_ram = [l[9:60].split() for l in lines[i:i+64]]\n",
97+
" raw_ram = [int(v,16) & 0x0f for l in raw_ram for v in l]\n",
98+
" color_ram = list(reversed([raw_ram[v:v+40] for v in range(0, len(raw_ram), 40)]))[2:]\n",
99+
" ram_history += [color_ram]\n",
100+
" c += 1\n"
101+
]
102+
},
103+
{
104+
"cell_type": "markdown",
105+
"metadata": {},
106+
"source": [
107+
"Slice up the ram history into the different patterns."
108+
]
109+
},
110+
{
111+
"cell_type": "markdown",
112+
"metadata": {},
113+
"source": [
114+
"Methods for culling the pixel data to just the volume that's occupied."
115+
]
116+
},
117+
{
118+
"cell_type": "code",
119+
"execution_count": 5,
120+
"metadata": {},
121+
"outputs": [],
122+
"source": [
123+
"def firstNonZero(l):\n",
124+
" for i,e in enumerate(l):\n",
125+
" if e > 0:\n",
126+
" return i\n",
127+
" return i\n",
128+
"\n",
129+
"def getLeftMostPixelForPattern(pattern):\n",
130+
" return min([firstNonZero(r) for scr in pattern for r in scr])\n",
131+
"\n",
132+
"def getRightMostPixelForPattern(pattern):\n",
133+
" return len(pattern[0][0]) - min([firstNonZero(list(reversed(r)))\n",
134+
" for scr in pattern for r in scr])\n",
135+
"\n",
136+
"def rotatePatternToCols(pattern):\n",
137+
" pattern_cols = []\n",
138+
" for scr in pattern:\n",
139+
" col_arr = [[0 for i in range(len(scr))] for j in range(len(scr[0]))]\n",
140+
" for i,r in enumerate(scr):\n",
141+
" for j,v in enumerate(r):\n",
142+
" col_arr[j][i] = v\n",
143+
" pattern_cols += [col_arr]\n",
144+
" return pattern_cols\n",
145+
"\n",
146+
"def cullPattern(pattern):\n",
147+
" first_left = getLeftMostPixelForPattern(pattern)\n",
148+
" last_right = getRightMostPixelForPattern(pattern)\n",
149+
" width = last_right - first_left\n",
150+
"\n",
151+
" pattern_as_cols = rotatePatternToCols(pattern)\n",
152+
" first_top = getLeftMostPixelForPattern(pattern_as_cols)\n",
153+
" last_bottom = getRightMostPixelForPattern(pattern_as_cols)\n",
154+
" height = last_bottom - first_top\n",
155+
" \n",
156+
" culled = [[r[first_left:last_right] \n",
157+
" for r in scr[first_top:last_bottom]]\n",
158+
" for scr in pattern]\n",
159+
" return culled\n",
160+
"\n",
161+
"#cullPattern(patterns[0])\n",
162+
"#patterns[0]"
163+
]
164+
},
165+
{
166+
"cell_type": "code",
167+
"execution_count": 26,
168+
"metadata": {},
169+
"outputs": [],
170+
"source": [
171+
"import matplotlib.pyplot as plt\n",
172+
"from PIL import Image\n",
173+
"from matplotlib.colors import LightSource"
174+
]
175+
},
176+
{
177+
"cell_type": "code",
178+
"execution_count": 27,
179+
"metadata": {},
180+
"outputs": [],
181+
"source": [
182+
"import numpy as np\n",
183+
"plt.rcParams[\"figure.figsize\"] = (80,80)\n",
184+
"plt.rcParams['figure.dpi'] = 20\n",
185+
"\n",
186+
"def explode(data):\n",
187+
" size = np.array(data.shape)*2\n",
188+
" data_e = np.zeros(size - 1, dtype=data.dtype)\n",
189+
" data_e[::2, ::2, ::2] = data\n",
190+
" return data_e\n",
191+
"\n",
192+
"def createVoxelData(screens):\n",
193+
" # prepare some coordinates\n",
194+
" width = len(screens[0][0])\n",
195+
" height = len (screens[0])\n",
196+
" x, y, z = np.indices((width,height,len(screens)))\n",
197+
" voxelarray = np.zeros((width,height,len(screens)), dtype=bool)\n",
198+
" colorarray = np.empty(voxelarray.shape, dtype=object)\n",
199+
" for zp,screen in enumerate(screens):\n",
200+
" for yp, row in enumerate(screen):\n",
201+
" for xp, col in enumerate(row):\n",
202+
" # Skip black, white and gray cells\n",
203+
" if col in [0,1,0x0c]:\n",
204+
" continue\n",
205+
" cube = (x == xp) & (y == yp) & (z == zp)\n",
206+
" voxelarray |= cube\n",
207+
" color = c64_to_rgb[colors[col]]\n",
208+
" colorarray[cube] = color+\"c0\"\n",
209+
"\n",
210+
" # upscale the above voxel image, leaving gaps\n",
211+
" filled_2 = explode(voxelarray)\n",
212+
" ecolors_2 = explode(colorarray)\n",
213+
"\n",
214+
" # Shrink the gaps\n",
215+
" x, y, z = np.indices(np.array(filled_2.shape) + 1).astype(float) // 2\n",
216+
" x[0::2, :, :] += 0.10\n",
217+
" y[:, 0::2, :] += 0.10\n",
218+
" z[:, :, 0::2] += 0.10\n",
219+
" x[1::2, :, :] += 0.90\n",
220+
" y[:, 1::2, :] += 0.90\n",
221+
" z[:, :, 1::2] += 0.90\n",
222+
"\n",
223+
" return ((x,y,z), filled_2, ecolors_2)"
224+
]
225+
},
226+
{
227+
"cell_type": "code",
228+
"execution_count": 10,
229+
"metadata": {},
230+
"outputs": [],
231+
"source": [
232+
"def fig2img(fig):\n",
233+
" \"\"\"Convert a Matplotlib figure to a PIL Image and return it\"\"\"\n",
234+
" import io\n",
235+
" buf = io.BytesIO()\n",
236+
" fig.savefig(buf)\n",
237+
" buf.seek(0)\n",
238+
" img = Image.open(buf)\n",
239+
" return img\n",
240+
"\n"
241+
]
242+
},
243+
{
244+
"cell_type": "markdown",
245+
"metadata": {},
246+
"source": [
247+
" Finally, write out our visualisation of each pattern evolution."
248+
]
249+
},
250+
{
251+
"cell_type": "code",
252+
"execution_count": 31,
253+
"metadata": {},
254+
"outputs": [],
255+
"source": [
256+
"# Select our pattern\n",
257+
"#screens = cullPattern(patterns[5])\n",
258+
"import os\n",
259+
"import gc\n",
260+
"\n",
261+
"patterns = [ram_history[:80]]\n",
262+
"for i, screens in enumerate([cullPattern(p) for p in patterns if len(p) > 1]):\n",
263+
" for azim in [-45,-225]:\n",
264+
" if os.path.isfile(f'sequencer/pattern{i}{azim}.png'):\n",
265+
" continue\n",
266+
" ((x,y,z), voxels, vcolors) = createVoxelData(screens)\n",
267+
"\n",
268+
" # and plot everything\n",
269+
" ax = plt.figure().add_subplot(projection='3d')\n",
270+
" ls = LightSource(45)\n",
271+
" ax.voxels(x,y,z,voxels, facecolors=vcolors, edgecolors=vcolors,lightsource=ls)\n",
272+
" ax.axis('off')\n",
273+
" ax.view_init(azim=azim, vertical_axis='y')\n",
274+
" img = fig2img(plt.gcf())\n",
275+
" im1 = None\n",
276+
" if azim == -45:\n",
277+
" im1 = img.crop((img.width/5, img.height/5, \n",
278+
" (img.width/7) * 6, (img.height/5) * 4))\n",
279+
" else:\n",
280+
" OFFSET = 150\n",
281+
" im1 = img.crop(((img.width/5) - OFFSET, (img.height/5) - OFFSET,\n",
282+
" ((img.width/7) * 6) - OFFSET, ((img.height/5) * 4) - OFFSET))\n",
283+
" newImage = []\n",
284+
" for item in im1.getdata():\n",
285+
" if item[:3] == (255, 255, 255):\n",
286+
" newImage.append((255, 255, 255, 0))\n",
287+
" else:\n",
288+
" newImage.append(item)\n",
289+
"\n",
290+
" im1.putdata(newImage)\n",
291+
" im1.save(f'sequencer/pattern{i}{azim}.png')\n",
292+
" plt.clf()\n",
293+
" del voxels, vcolors\n",
294+
" plt.close()\n",
295+
" gc.collect()\n"
296+
]
297+
},
298+
{
299+
"cell_type": "code",
300+
"execution_count": null,
301+
"metadata": {},
302+
"outputs": [],
303+
"source": [
304+
"\n",
305+
"\n",
306+
"\n",
307+
"\n",
308+
"\n",
309+
"\n",
310+
"\n",
311+
"\n",
312+
"\n",
313+
"\n",
314+
"\n",
315+
"\n",
316+
"\n",
317+
"\n",
318+
"\n",
319+
"\n",
320+
"\n"
321+
]
322+
}
323+
],
324+
"metadata": {
325+
"kernelspec": {
326+
"display_name": "Python 3",
327+
"language": "python",
328+
"name": "python3"
329+
},
330+
"language_info": {
331+
"codemirror_mode": {
332+
"name": "ipython",
333+
"version": 3
334+
},
335+
"file_extension": ".py",
336+
"mimetype": "text/x-python",
337+
"name": "python",
338+
"nbconvert_exporter": "python",
339+
"pygments_lexer": "ipython3",
340+
"version": "3.8.10"
341+
}
342+
},
343+
"nbformat": 4,
344+
"nbformat_minor": 4
345+
}

0 commit comments

Comments
 (0)