Nope, just not ready to quit. So, I thought I’d look at using the plot between method between rows of different transformations. I would generate the data for a set of transformations, then colour between rows in different transformations. No idea what it will look like, or even if really viable, but as with all the previous image iterations, it’s at least worth a look in my opinion.
Initial Attempt
New image type, # 42. I am going to start by generating the usual four transformations (rotational at 45° with a linear translation into each image quadrant). Then, for each transformation, colour between all the rows in it and one of the other transformations. Expect there will be a lot of overcolouring of previous colours. But, not sure how to avoid that. No way to easily determine where data will create overlaps.
To start I will also only look at using one colour for each set of rows.
Wrote a function to do the work for each pair of transformations. I have left my debug print statements in the code below. I do a lot of that.
def btw_qds(axt, rxs, rys1, rys2, mlt=False, sect=1):
# save stuff needed to generate true copy when saving to file
global c_mlts, i_data, rys2_i, t_c_ndx
print(f"\t\tbtw_qds(..., mlt={mlt}, sect={sect})")
c_ndx = 0
c_len = len(cycle)
c_jmp = c_len // 20
if c_jmp % 2 == 0:
c_jmp += 1
if not t_sv:
if mlt:
c_mlts, i_data = incr_data(rys2)
else:
c_mlts = [1.0 for _ in range(len(rys2))]
i_data = rys2
c_ndx = (c_ndx + c_jmp) % c_len
t_c_ndx = c_ndx
if cnt_42 == 0:
rys2_i = list(range(len(rys2)))
random.shuffle(rys2_i)
else:
c_ndx = t_c_ndx
print(f"\t\tDEBUG: rys2_i: {rys2_i}; (cnt_42: {cnt_42})")
if mlt:
print(f"\t\tDEBUG: mlt={mlt}, c_mlts={c_mlts}")
for i in rys2_i:
if do_dbg:
print(f"\t\tax.fill_between(rxs[{i}], rys1[{i}]*{c_mlts[i]}, rys2[{i}], alpha={bw_lph}, c={c_ndx})")
# axt.fill_between(rxs[i], rys1[i], rys2[rys2_i[i]], alpha=bw_lph, color=cycle[c_ndx])
axt.fill_between(rxs[i], rys1[i], rys2[i], alpha=bw_lph, color=cycle[c_ndx])
c_ndx = (c_ndx + c_jmp) % c_len
return rys2_i
And, here’s the relevant code from the image type block.
... ...
# sort number of quadrants and colouring order
if not t_sv:
do_qd = range(nbr_qds)
if tr_qd and tq_r:
do_qd = range(tq_r)
nbr_qds = max(list(do_qd)) + 1
# randomize plotting order
do_qd = list(do_qd)
random.shuffle(do_qd)
do_qd2 = list(range(nbr_qds))
random.shuffle(do_qd2)
... ...
ax.autoscale(True)
qd_data = []
for i in range(nbr_qds):
a = np.array([[np.cos(lld_rot[i]), -np.sin(lld_rot[i])],
[np.sin(lld_rot[i]), np.cos(lld_rot[i])]])
dstx, dsty = affine_transformation(src[0], src[1], a)
dx, dy = rotate_pt(0, trdy, angle=lld_rot[i], cx=0, cy=0)
dstx = dstx + dx
dsty = dsty + dy
print(f"\trot angle: {math.degrees(lld_rot[i])}, pt angle: {math.degrees(pt_rot[i])}, dx: {dx}, dy: {dy}")
qd_data.append([dstx, dsty])
print(f"\tdo_qd: {do_qd}, do_qd2: {do_qd2}, len(qd_data): {len(qd_data)}, len(qd_data[i]): {len(qd_data[i])}")
for i in range(len(do_qd)):
if do_qd[i] == do_qd2[i]:
# don't colour between the same transformations
continue
bwx = qd_data[do_qd[i]][0]
bwy1 = qd_data[do_qd[i]][1]
bwy2 = qd_data[do_qd2[i]][1]
print(f"\n\tbtw_qds(rxs[{do_qd[i]}][0][{src_st}:], rys[{do_qd[i]}][1][{src_st}:], rys[{do_qd2[i]}][1][{src_st}:], mlt={bw_m}, sect={bw_s}, alpha={bw_lph})")
rys2i = btw_qds(ax, bwx, bwy1, bwy2, mlt=False, sect=1)
ax.autoscale(True)
cnt_42 += 1
Got some images that seemed promising. E.G.
But all too many look like this.
And, in this case, the non-elliptical wheels seemed to generate better images.
Attempt #2
Let’s look at what happens if we don’t plot between the same rows in each quadrant. Another module variable so can create and track to separate sets of random data row numbers. And a few changes to the code.
def btw_qds(axt, rxs, rys1, rys2, mlt=False, sect=1):
# save stuff needed to generate true copy when saving to file
global c_mlts, i_data, rxs_i, rys2_i, t_c_ndx, rnd_rw
print(f"\t\tbtw_qds(..., mlt={mlt}, sect={sect})")
c_ndx = 0
c_len = len(cycle)
c_jmp = c_len // 20
if c_jmp % 2 == 0:
c_jmp += 1
if not t_sv:
if mlt:
c_mlts, i_data = incr_data(rys2)
else:
c_mlts = [1.0 for _ in range(len(rys2))]
i_data = rys2
c_ndx = (c_ndx + c_jmp) % c_len
t_c_ndx = c_ndx
# rys2_i = random.shuffle(list(range(n_whl)))
if cnt_42 == 0:
rxs_i = list(range(len(rxs)))
random.shuffle(rxs_i)
rys2_i = list(range(len(rys2)))
random.shuffle(rys2_i)
else:
c_ndx = t_c_ndx
print(f"\t\tDEBUG: rxs_i: {rxs_i}; (cnt_42: {cnt_42})")
print(f"\t\tDEBUG: rys2_i: {rys2_i}")
if mlt:
print(f"\t\tDEBUG: mlt={mlt}, c_mlts={c_mlts}")
for i in range(len(rxs)):
if rxs_i[i] == rys2_i[i]:
# don't plot between same data row
continue
if do_dbg:
print(f"\t\tax.fill_between(rxs[{rxs_i[i]}], rys1[{rxs_i[i]}]*{c_mlts[i]}, rys2[{rys2_i[i]}], alpha={bw_lph}, c={c_ndx})")
# axt.fill_between(rxs[i], rys1[i], rys2[rys2_i[i]], alpha=bw_lph, color=cycle[c_ndx])
axt.fill_between(rxs[rxs_i[i]], rys1[rxs_i[i]], rys2[rys2_i[i]], alpha=bw_lph, color=cycle[c_ndx])
c_ndx = (c_ndx + c_jmp) % c_len
return rys2_i
Not going to show you any images. No significant improvement.
Increase Colour Areas
Okay, let’s try increasing the number of colour sections. Here’s the modification to our plotting function.
... ...
s_sz = len(rxs[0]) // sect
... ...
for i in range(len(rxs)):
if rxs_i[i] == rys2_i[i]:
# don't plot between same data row
continue
if sect == 1:
if do_dbg:
print(f"\t\tax.fill_between(rxs[{rxs_i[i]}], rys1[{rxs_i[i]}]*{c_mlts[i]}, rys2[{rys2_i[i]}], alpha={bw_lph}, c={c_ndx})")
axt.fill_between(rxs[rxs_i[i]], rys1[rxs_i[i]], rys2[rys2_i[i]], alpha=bw_lph, color=cycle[c_ndx])
c_ndx = (c_ndx + c_jmp) % c_len
else:
for j in range(sect-1):
s_st = s_sz * j
s_nd = s_sz * (j+1)
if do_dbg:
print(f"\t\tax.fill_between(rxs[{rxs_i[i]}][{s_st}:{s_nd}], rys1[{rxs_i[i]}][{s_st}:{s_nd}]*{c_mlts[i]}, rys2[{rys2_i[i]}][{s_st}:{s_nd}], alpha={bw_lph}, c={c_ndx})")
axt.fill_between(rxs[rxs_i[i]][s_st:s_nd], rys1[rxs_i[i]][s_st:s_nd], rys2[rys2_i[i]][s_st:s_nd], alpha=bw_lph, color=cycle[c_ndx])
c_ndx = (c_ndx + c_jmp) % c_len
if do_dbg:
print(f"\t\tax.fill_between(rxs[{rxs_i[i]}][{s_nd}:], rys1[{rxs_i[i]}][{s_nd}:]*{c_mlts[i]}, rys2[{rys2_i[i]}][{s_nd}:], alpha={bw_lph}), c={c_ndx}")
axt.fill_between(rxs[rxs_i[i]][s_nd:], rys1[rxs_i[i]][s_nd:], rys2[rys2_i[i]][s_nd:], alpha=bw_lph, color=cycle[c_ndx])
... ...
And things already look better and/or more interesting.
For the one above, the row order is:
DEBUG: rxs_i: [3, 2, 4, 1, 0]; (cnt_42: 4)
DEBUG: rys2_i: [4, 0, 1, 2, 3]
For the one above, the row order is:
DEBUG: rxs_i: [9, 8, 4, 7, 5, 3, 6, 1, 2, 0]; (cnt_42: 4)
DEBUG: rys2_i: [1, 2, 8, 5, 0, 6, 4, 7, 3, 9]
A Further Refactoring
I am thinking that plotting between all the rows is likely a great deal of overkill. So, I am going to look at randomly selecting a single data row from the first transformation and plotting between it and all the rows in the second transformation. Keeping the increased number of colour areas.
A new module variable (to ensure proper saving of images to file) and a bit of code change. I won’t bother showing the modified fill_between()
statements. Simple change to data row indices. And, I am dropping the first data row from the data set. Thought it was adding to the clutter on some of the images.
global c_mlts, i_data, rys2_i, t_c_ndx, rnd_rw
... ...
if cnt_42 == 0:
rys2_i = list(range(len(rys2)))
random.shuffle(rys2_i)
rnd_rw = random.choice(rys2_i)
Example Images
And, you know, I’m liking the results. Here’s a set of images for the same underlying curve (5 circles). But with my cataclysmic variables hard at work.
The following looks a lot like one of the earlier ones. But, there are very visible differences resulting from the changes in the random values.
Again very similar to the viridis coloured one above. Yet different.
And effecively a partial rotation of the one above. With additional changes.
The one above, such a complete change from the others. But there were hints in a number of the preceding images, that it was a possibility.
And, yet again similar, but ever so slightly different. Quite like the colour map in this one.
And finally, the curls where I wanted them. On top, like a fancy bow on a gift (which I consider these images, a gift of code and the mind).
This one just for the colour map.
Another with the ribbons on top. But marginally and visibly different.
And, one more using the jet colour map.
Done
Lots of images (perhaps too many for a single post). So, I think I will call this one done. But I am not yet quite done. I want to see what happens with larger numbers of transformations. And, perhaps with some chaos added. Hoping those will all work without too much code refactoring.
Until next time, enjoy your coding time and any cataclysmic variables with which you may be experimenting.
Resources
- matplotlib.pyplot.fill_between