Quite the workout last time. Let’s see what it takes to repeat the other tranformation image types. Though I may for now skip the mosaic transform to transform type.

gnarly_t

I just copied some of the stuff over from the appropriate route and things seemed to work just fine for my test image.

      elif 'gnarly' in r.d_rpt[r.do_nbr]['i_typ']:
        # Generate transformed datasets
        dt_x, dt_y, _ = make_transforms(r_xs, r_ys, "gnarly_t", do_qd2, lld_rot, trdy, y_mlt=y_mlt, do_t1=do_qd)

        for i in range(len(dt_x)):
          ax.plot(dt_x[i], dt_y[i], lw=g.ln_w, alpha=1)
          ax.autoscale()
... ...
    elif r.d_rpt[r.do_nbr]['i_typ'] == 'gnarly_t':
      d_end = "top" if g.drp_f else "bottom"  
      p_data = {
              'd_end': d_end, 'd_nbr': g.r_skp,
              'ntr': g.nbr_tr, 'trang': lld_deg, 'trpt': f'(0, {round(trdy, 3)}) ({y_mlt})',
              'trord2': do_qd2
             }

Test

The data saved from the display page was:

gnarly_t
Curve Parameters
    Wheels: 9 wheels (shape(s): rhombus (r))
    Symmetry: k_fold = 4, congruency = 3
    Frequencies: [-1, -9, -5, 15, 3, 11, -1, -5, 11]
    Widths: [1, 0.6769585152867885, 0.657421016579852j, 0.6308918613542178j, 0.5101357922701247, 0.48555975482889846j, 0.46707223242611007, 0.2817619386262918, 0.1626706687783567j]
    Heights: [1, 0.6259081347764245, 0.4991308174443422, 0.38208587908718655j, 0.22753198914071018j, 0.13975254705360463j, 0.125, 0.125j, 0.125]
    Data points: 1024
Image Type Parameters
    Drop data rows: 1 datarow
    From: dropped from the 'top' of the curve dataset
Drawing Parameters
    Colour map: inferno (0.75, 3)
    BG colour map: gist_rainbow (0.15)
    Line width (if used): 1
    Image size: 8
    Image DPI: 72
Transformations
    Number of transforms: 8
    Angles: [45.0, 90.0, 135.0, 180.0, 225.0, 270.0, 315.0, 360.0]
    Base linear translation point: (0, 1.218) (0.5)
    Order: [0, 2, 3, 4, 1, 7, 6, 5]
Colour Arrays
    Background array: [[0.17556021 0.09677037 0.75796826 0.75292477] [0.50097762 0.12006618 0.33752684 0.38438516] [0.50038911 0.25366481 0.6676264 0.93126733] [0.01702525 0.33626939 0.90119215 0.42099212]]
    Colour cycle: [(0.001462, 0.000466, 0.013866, 1.0), (0.013995, 0.011225, 0.071862, 1.0), (0.042253, 0.028139, 0.141141, 1.0), (0.081962, 0.043328, 0.215289, 1.0), (0.129285, 0.047293, 0.290788, 1.0), (0.183429, 0.040329, 0.354971, 1.0), (0.238273, 0.036621, 0.396353, 1.0), (0.290763, 0.045644, 0.418637, 1.0), (0.3415, 0.062325, 0.429425, 1.0), (0.391453, 0.080927, 0.433109, 1.0), (0.441207, 0.099338, 0.431594, 1.0), (0.491022, 0.117179, 0.425552, 1.0), (0.54092, 0.134729, 0.415123, 1.0), (0.590734, 0.152563, 0.40029, 1.0), (0.640135, 0.171438, 0.381065, 1.0), (0.688653, 0.192239, 0.357603, 1.0), (0.735683, 0.215906, 0.330245, 1.0), (0.780517, 0.243327, 0.299523, 1.0), (0.822386, 0.275197, 0.266085, 1.0), (0.860533, 0.311892, 0.230606, 1.0), (0.894305, 0.353399, 0.193584, 1.0), (0.923215, 0.399359, 0.155193, 1.0), (0.946965, 0.449191, 0.115272, 1.0), (0.965397, 0.502249, 0.073859, 1.0), (0.978422, 0.557937, 0.034931, 1.0), (0.985952, 0.61575, 0.025592, 1.0), (0.987874, 0.675267, 0.065257, 1.0), (0.984075, 0.736087, 0.129527, 1.0), (0.974638, 0.797692, 0.206332, 1.0), (0.960626, 0.859069, 0.29801, 1.0), (0.947594, 0.917399, 0.410665, 1.0), (0.954529, 0.965896, 0.540361, 1.0), (0.988362, 0.998364, 0.644924, 1.0), (0.946809, 0.924168, 0.426373, 1.0), (0.956834, 0.874129, 0.323974, 1.0), (0.971468, 0.813122, 0.227658, 1.0), (0.981173, 0.759135, 0.156863, 1.0), (0.986694, 0.70554, 0.095694, 1.0), (0.987622, 0.64532, 0.039886, 1.0), (0.983779, 0.593849, 0.02377, 1.0), (0.975677, 0.543798, 0.043618, 1.0), (0.961293, 0.488716, 0.084289, 1.0), (0.944285, 0.442772, 0.120354, 1.0), (0.923215, 0.399359, 0.155193, 1.0), (0.894305, 0.353399, 0.193584, 1.0), (0.865006, 0.316822, 0.226055, 1.0), (0.832299, 0.283913, 0.257383, 1.0), (0.791293, 0.250856, 0.29139, 1.0), (0.752794, 0.225706, 0.319085, 1.0), (0.712396, 0.203656, 0.344383, 1.0), (0.670599, 0.184153, 0.366879, 1.0), (0.621685, 0.164184, 0.388781, 1.0), (0.578304, 0.148039, 0.404411, 1.0), (0.534683, 0.132534, 0.416667, 1.0), (0.484789, 0.114974, 0.426548, 1.0), (0.441207, 0.099338, 0.431594, 1.0), (0.397674, 0.083257, 0.433183, 1.0), (0.347771, 0.064616, 0.430217, 1.0), (0.303568, 0.049396, 0.422182, 1.0), (0.258234, 0.038571, 0.406485, 1.0), (0.204209, 0.037632, 0.373238, 1.0), (0.15585, 0.044559, 0.325338, 1.0), (0.110536, 0.047399, 0.262912, 1.0), (0.066331, 0.038504, 0.186962, 1.0)]

And here are the original image and the repeat version.

original gnarly spirograph with transforms image that I wished to repeat
Original Test Gnarly Image with Transformations
attempted repeat of above spirograph image
Attempted Repeat of Above Image

Well that was amazingly easy.

mosaic_t

Had to add some more fields to the repeat image data dictionary. Also moved one to join the new ones. These are specific to mosaic images. I put them just before the fields specific to image transforms.

    'c_nbr': '16',
    'r_btw': '1',
    'r_mlt': 'false',
    'mlts': [],

In order to pass the current colour cycle index to the appropriate plotting function, I had to refactor it the same way I did in the previous post.

def btw_n_apart(axt, rxs, rys, dx=1, ol=True, r=False, fix=None, mlt=False, sect=1, u_ndx=None):
... ...
  if not g.do_rpt or not g.c_ndx:
    c_ndx = rng.integers(0, c_len-2)
    g.c_ndx = c_ndx
  else:
    if u_ndx:
      c_ndx = u_ndx
    else:
      c_ndx = g.c_ndx

And in the repeat route function, I added the following.

      elif 'mosaic' in r.d_rpt[r.do_nbr]['i_typ']:
        d_xs, d_ys, _ = make_transforms(r_xs, r_ys, 'mosaic_t', do_qd2, lld_rot, trdy, y_mlt=y_mlt)

        # Generate transformed datasets
        for ndx, i in enumerate(do_qd2):
          sal.btw_n_apart(ax, d_xs[i], d_ys[i], dx=g.bw_dx, ol=g.bw_o, r=g.bw_r, fix=None, mlt=g.bw_m,
             sect=g.bw_s, u_ndx=g.c_ndx[ndx])
          ax.autoscale()
          sal.cnt_btw += 1
... ...
    elif r.d_rpt[r.do_nbr]['i_typ'] == 'mosaic_t':
      p_data = {'bdx': g.bw_dx, 'bol': g.bw_o, 'bcs': g.bw_s,
              'bmlt': g.u_rmlt != 'false', 'mlts': sal.c_mlts,
              'ntr': g.nbr_tr, 'trang': lld_deg, 'trpt': f'(0, {round(trdy, 3)}) ({y_mlt})',
              'trord2': do_qd2
             }

Test

I didn’t have any mosaic_t with the original image saved. So, I used the current code to generate one for testing purposes.

I won’t bother displaying the saved data; just the images.

original test mosaic spirograph with transforms image that I wished to repeat
Original Test Mosaic Image with Transformations
attempted repeat of above spirograph image
Attempted Repeat of Above Image

And, that appears to work as desired. Also once again fairly easy. Guess I did the bulk of the work when sorting out repeating cycling line width image with transforms.

Wasn’t originally going to add the mosaic with colouring between transforms. But this is going well enough that I thought I’d give it a try.

mosaic_t2t

Ended up taking a bit more refactoring than I expected, but seem to have got it working. Mostly trying to sort exactly how the image was generated and how the various values were obtained. And, I one point I was using an incorrect value in a conditional. Almost all of the extra effort was due to a lack of good documentation on my part. I know it’s probably in old blog posts somewhere—but that’s not exactly good documentation.

Added a new field to the repeat data dictionary: 't2t_btw': [],. Right after 'do_qd2'. It tracks the rows that are coloured between on each iteration of colouring between two transforms. The selection of transforms is controlled by the values of do_qd aand do_qd2 in the image data dictionary.

A wee refactor to set_rpt_data(). The top and bottom rows below. Three, unchanged rows between are there for context.

  g.bw_m = True if r.d_rpt[r.do_nbr]['r_mlt']  == 'true' else False
  g.bw_dx = int(r.d_rpt[r.do_nbr]['r_btw'])
  g.bw_s = int(r.d_rpt[r.do_nbr]['c_nbr'])
  g.bw_o = True
  g.bw_trws = r.d_rpt[r.do_nbr]['t2t_btw']

I was previously just assigning the value of r.d_rpt[r.do_nbr]['r_mlt'] to g.bw_m. That’s a string, so g.bw_m was always evaluating to true. Which was definitely messing with things.

Also refactored sal.btw_qds, adding that optional colour cycle index parameter, u_ndx=None. And refactoring the code to account for it appropriately (see above or previous post).

Then I made sure a call to the function didn’t generate a new set of values for g.bw_trws if doing a repeat. Added the if block below plus the else block. The previous code is in the if block.

  if cnt_btw == 0:
    if not g.do_rpt:
      rys2_i = list(range(len(rys2)))
      rng.shuffle(rys2_i)
      g.bw_trws = []
      rw1 = rng.choice(rys2_i)
      g.bw_trws.append(rw1)
      rys2_i.remove(rw1)
      g.bw_trws.extend(rys2_i)
    else:
      rw1 = g.bw_trws[0]
      rys2_i = g.bw_trws[1:]

    if mlt:

In the repeat route I added the following in the pertinent locations. Do note that the elif 't2t' has to go before the elif 'mosaic'. If it goes after it will never be executed.

      elif 't2t' in r.d_rpt[r.do_nbr]['i_typ']:
        dt_x, dt_y, dt_y2 = make_transforms(r_xs, r_ys, 'mosaic_t2t', do_qd2, lld_rot, trdy, y_mlt=y_mlt, do_t1=do_qd)

        # Generate transformed datasets
        for i in range(g.nbr_tr):
          if do_qd[i] == do_qd2[i]:
            continue
          rys2i = sal.btw_qds(ax, dt_x[i], dt_y[i], dt_y2[i], mlt=g.bw_m, sect=g.bw_s, u_ndx=g.c_ndx[i])    
          ax.autoscale()
      elif 'mosaic' in r.d_rpt[r.do_nbr]['i_typ']:
... ...
    elif r.d_rpt[r.do_nbr]['i_typ'] == 'mosaic_t2t':
      p_data = {'bdx': g.bw_dx, 'bol': g.bw_o, 'bcs': g.bw_s,
              'bmlt': g.u_rmlt != 'false', 'mlts': sal.c_mlts,
              'ntr': g.nbr_tr, 'trang': lld_deg, 'trpt': f'(0, {round(trdy, 3)}) ({y_mlt})',
              'trord': do_qd, 'trord2': do_qd2, 'trws': g.bw_trws
             }

Test

As it has changed a bit over the last couple of posts, I decided to list the test image’s repeat data dictionary.

d_rpt.append(
  {
    'i_typ': 'mosaic_t2t',
    'shape': 'q',
    'shp_mlt': 'false',
    'wheels': '10',
    'k_f': 7,
    'cgv': 6,
    'freqs': [6, -15, -22, 34, 34, -1, 27, -8, 20, -22],
    'wds': [1, 0.5839965910642135j, 0.4686729652631233, 0.24111609912316234, 0.2309935900589636j, 0.12585152503709113, 0.125, 0.125, 0.125j, 0.125],
    'hts': [1, 0.5570160786587838, 0.5098948302264085j, 0.35865549348923187, 0.2703810613066595, 0.1656097105665913, 0.1419466650230957, 0.1352013445508208j, 0.125, 0.125],
    'ln_sz': '6',
    'cmap': 'gist_rainbow',
    'c_cyc': [(1.0, 0.0, 0.16, 1.0), (1.0, 0.007419183889772136, 0.0, 1.0), (1.0, 0.17700052994170645, 0.0, 1.0), (1.0, 0.34658187599364076, 0.0, 1.0), (1.0, 0.5161632220455751, 0.0, 1.0), (1.0, 0.6857445680975094, 0.0, 1.0), (1.0, 0.8553259141494436, 0.0, 1.0), (0.9750927397986221, 1.0, 0.0, 1.0), (0.8055113937466878, 1.0, 0.0, 1.0), (0.6359300476947536, 1.0, 0.0, 1.0), (0.4663487016428193, 1.0, 0.0, 1.0), (0.29676735559088496, 1.0, 0.0, 1.0), (0.12718600953895065, 1.0, 0.0, 1.0), (0.0, 1.0, 0.04216740459624712, 1.0), (0.0, 1.0, 0.2108370229812356, 1.0), (0.0, 1.0, 0.3795066413662241, 1.0), (0.0, 1.0, 0.5481762597512125, 1.0), (0.0, 1.0, 0.716845878136201, 1.0), (0.0, 1.0, 0.8855154965211895, 1.0), (0.0, 0.9452259164535375, 1.0, 1.0), (0.0, 0.774722932651321, 1.0, 1.0), (0.0, 0.6042199488491045, 1.0, 1.0), (0.0, 0.43371696504688806, 1.0, 1.0), (0.0, 0.26321398124467155, 1.0, 1.0), (0.0, 0.09271099744245515, 1.0, 1.0), (0.07779198635976144, 0.0, 1.0, 1.0), (0.24829497016197802, 0.0, 1.0, 1.0), (0.4187979539641946, 0.0, 1.0, 1.0), (0.5893009377664112, 0.0, 1.0, 1.0), (0.7598039215686277, 0.0, 1.0, 1.0), (0.9303069053708444, 0.0, 1.0, 1.0), (1.0, 0.0, 0.8991901108269392, 1.0), (1.0, 0.0, 0.75, 1.0), (0.9516197783461214, 0.0, 1.0, 1.0), (0.8024296675191819, 0.0, 1.0, 1.0), (0.6319266837169654, 0.0, 1.0, 1.0), (0.4827365728900258, 0.0, 1.0, 1.0), (0.3335464620630857, 0.0, 1.0, 1.0), (0.16304347826086973, 0.0, 1.0, 1.0), (0.013853367433930218, 0.0, 1.0, 1.0), (0.0, 0.13533674339300916, 1.0, 1.0), (0.0, 0.3058397271952257, 1.0, 1.0), (0.0, 0.4550298380221651, 1.0, 1.0), (0.0, 0.6042199488491045, 1.0, 1.0), (0.0, 0.774722932651321, 1.0, 1.0), (0.0, 0.9239130434782604, 1.0, 1.0), (0.0, 1.0, 0.9276829011174367, 1.0), (0.0, 1.0, 0.7590132827324482, 1.0), (0.0, 1.0, 0.6114273666455833, 1.0), (0.0, 1.0, 0.46384145055871834, 1.0), (0.0, 1.0, 0.3162555344718534, 1.0), (0.0, 1.0, 0.14758591608686492, 1.0), (0.0, 1.0, 0.0, 1.0), (0.14838367779544248, 1.0, 0.0, 1.0), (0.3179650238473768, 1.0, 0.0, 1.0), (0.4663487016428193, 1.0, 0.0, 1.0), (0.6147323794382618, 1.0, 0.0, 1.0), (0.784313725490196, 1.0, 0.0, 1.0), (0.9326974032856385, 1.0, 0.0, 1.0), (1.0, 0.918918918918919, 0.0, 1.0), (1.0, 0.7493375728669847, 0.0, 1.0), (1.0, 0.6009538950715422, 0.0, 1.0), (1.0, 0.4525702172760997, 0.0, 1.0), (1.0, 0.2829888712241654, 0.0, 1.0)],
    'c_lpha': 0.75,
    'c_ndx': [29, 50, 60, 48, 29, 43, 36],
    'do_bg': 'true',
    'c_bg': 'Blues',
    'abg': [[0.6786540244661128, 0.9827608866021652, 0.9890795035417875, 0.882687910132615], [0.5104683567649476, 0.13347974534624163, 0.2795811627180592, 0.23491472489732812], [0.06464296461431818, 0.8905987810315855, 0.39581471675120106, 0.6696642233040028], [0.03045516825782668, 0.8660007981155114, 0.7724032095627454, 0.4933969150825228]],
    'bg_lpha': 0.3,
    'npts': 1024,
    'sz': 8,
    'dpi': 72,
    'how': '',
    'clw_pct': 'false',
    'clwc': '8',
    'clwpp': '12',
    'h_frq': 128,
    'm_inc': None,
    'u_agn': 'false',
    'torb': 'top',
    'drows': '0',
    'c_nbr': '16',
    'r_btw': '1',
    'r_mlt': 'false',
    'mlts': [],
    'ntr': '7',
    'lld_deg': [25.714285714285715, 77.14285714285714, 128.57142857142858, 180.0, 231.42857142857142, 282.85714285714283, 334.2857142857143],
    'y_mlt': 0.5,
    'trdy': 0.788,
    'do_qd': [1, 2, 5, 3, 4, 6, 0],
    'do_qd2': [2, 3, 0, 6, 5, 4, 1],
    't2t_btw': [6, 2, 5, 3, 8, 4, 0, 1, 7],
    'do_drpt': 'false',
    'ani_step': 8,
  }
)

The t2t_btw field is generated from this line from the image display page:

Colouring between row 6 and [2, 5, 3, 8, 4, 0, 1, 7]

original test mosaic spirograph with coloruing between transforms image that I wished to repeat
Original Test Mosaic T2T Image
attempted repeat of above spirograph image
Attempted Repeat of Above Image

Image Data Output

One litte more thing.

The array to generate the background image is a mutli-dimensional Numpy array. When it is printed to the display page, it doesn’t have any commas separating the elements in the array. That has been a minor pain point when I am building the data dictionaries for repeat images. So, I have in sal.get_image_dtl() replaced 'abg': g.abg with 'abg': g.abg.tolist(). Now it is a straight copy and paste. No messing around adding a bunch of commas.

Done

I think that’s it for this one and for the moment working on the repeat route. I do believe it may be time for another refactoring. Including some reasonable documentation. I would like to move all, or at least most, of the functions in the main module to other modules. And see if, for this project, I can reduce the spiro_plotlib module it uses.

Wishing you success in your refactoring and app maintenance efforts.