As previously mentioned, one of the things I did to generate a variation on the mosaic like images was to apply a multiplier to one of the datarows in each pairing to try and generate larger colour areas. While still using multiple colour sections for each datarow pairing.

I will again be using spirograph related code from that earlier project. Which, as usual for this series of posts, I will not display.

Try to Generate Larger Colour Areas

You may have noticed that the call to btw_n_apart() included the paramter mlt=g.bw_m. The use of data value multipliers is already included in the code for that function. And, the global bw_m controls whether or not to use multipliers. The default is not to do so.

New Form Field

Okay, let’s give the user the choice. I.E. a new form field. Once again pretty easy, a simple radio button field; with two choices. So in get_curve.html I added the following after the field for the number of colours for each datarow pairing.

      <div class="radio">
        <p style="margin-left:1rem;margin-top:0;"><b>Use data multipliers when creating image</b></p>
        <p>
          <label for="mno">No: </label>
          <input type="radio" name="r_mlt" id="mno" value="false" />
          <label for="myes">Yes: </label>
          <input type="radio" name="r_mlt" id="myes" value="true" />
        </p>
      </div>

Though I did have to mess the CSS for this form section. And, resorted to in-line CSS which is likely not a good thing. But, I just didn’t feel like working that much on the CSS stylesheet. Though perhaps easier than I think.

And, in proc_curve_form() I added this bit of code.

    if i_typ == 'mosaic':
... ...
      if 'r_mlt' in f_data:
        g.bw_m = True if f_data['r_mlt'] == 'true' else False

Minor Route Refactor

And, the only refactoring I had to make in the route was to pass the appropriate data to disp_image.html so that it could be displayed on screen.

    p_data = {'pttl': pg_ttl, 'n_whl': g.n_whl, 'ln_sz': g.ln_w, 'shape': t_shp,
              'cmap': g.rcm, 'agn': g.u_again, 'bdx': g.bw_dx, 'bol': g.bw_o,
              'bcs': g.bw_s, 'bmlt': g.bw_m, 'mlts': sal.c_mlts
             }

Minor Refactor of Page Templates

I decided to show the multipliers to the user if they selected using them.

    {% if type == 'mosaic' %}
    {% set w_rows = "adjacent datarows" if p_data['bdx'] == 1 else "datarows {} apart".format(p_data['bdx']) %}
    <p>You requested colouring between {{ w_rows }} {{ "with" if p_data['bol'] else "without" }} overlap.
      Using {{ p_data['bcs'] }} colour sections per datarow pairing.
    {% if p_data['bmlt'] %}
      Multipliers in use: {{ p_data['mlts'] }}.
    {% endif %}
    </p>
    {% endif %}

And, I made the images on the home page into links as well as the text above them.

Some Examples

And you know, that was pretty much it. Rather easy when most of the hard code was produced previously. So, a few examples.

The first one uses 7 tetracuspid shaped wheels. Multipliers: [1.8, 2.0, 1.2, 1.4, 1.1, 1.2, 1.4]. 48 colour sections per datarow pairing with a colour map of plasma.

screen shot of mosaic like spirograph image with multiple colour sections and multipliers per datarow pairing

The next one uses 9 wheels with shapes: [’t’, ’t’, ‘c’, ‘r’, ‘r’, ‘q’, ’t’, ‘q’, ’s’]. Multipliers: [1.6, 2.6, 2.4, 2.2, 1.2, 1.4, 1.4, 1.2, 1.0]. 48 colour sections per datarow pairing with a colour map of gnuplot. You can see those first tetracuspid wheel shapes dominating the final result.

screen shot of mosaic like spirograph image with multiple colour sections and multipliers per datarow pairing

The next one uses 11 rhombus shaped wheels. Multipliers: [1.8, 1.8, 1.8, 1.2, 2.6, 1.2, 1.4, 1.5, 1.1, 1.0, 1.0]. 32 colour sections per datarow pairing with a colour map of rainbow.

screen shot of mosaic like spirograph image with multiple colour sections and multipliers per datarow pairing

One last one. 11 ellipse shaped wheels. Multipliers: [1.8, 2.4, 2.2, 2.2, 2.2, 1.2, 1.1, 1.0, 1.6, 1.0, 1.5]. 16 colour sections per datarow pairing with a colour map of twilight_shifted.

screen shot of mosaic like spirograph image with multiple colour sections and multipliers per datarow pairing

Personally, I think using the multipliers enhances the images. But, eye of the beholder and all that.

Major Refactor of Image Display Page

Bit of an aside. I decided to move all the image details, currently displayed before the image, after the image. Afterall the image is the priority, shouldn’t need to scroll down to see it. And, I added considerably more information (in case I ever want to try and replicate one of them in my personal command line app).

To help with this I wrote two functions. I plan to have two or three sections following the image. One for the underlying curve data (e.g. number wheels, shape, k_fold symmetry, frequencies). One for the basic plotting info (e.g. colour map, line width). And possibly one for specific information related to the current image type. The functions will return a dictionary with the data for the the curve and image information section, which will be passed on to the template. Don’t want to be adding all that code to the routing functions. The image type specific data is still being genereated in the route code.

New Functions

Very simple and straightforward. But, removes repetition in each of the routes.

def get_curve_dtl():
  if len(g.su) == 1:
    shape = f"{splt.shp_nm[g.su].lower()} ({g.su})"
  else:
    shape = g.su

  c_d = {
    'n_whl': g.n_whl, 'shape': shape, 'k_f': g.k_f, 'cgv': g.cgv,
    'freqs': g.freqs, 'wds': g.wds, 'hts': g.hts, 'agn': g.u_again
  }

  return c_d


def get_image_dtl(pg_ttl):
  c_d = {
    'pttl': pg_ttl, 'ln_sz': g.ln_w, 'cmap': g.rcm
  }

  return c_d

Refactor Routes

I’ll only show you the mosaic route, as the others are all similar. The only dictionary being coded in the route, is for the route’s image type specific data. Didn’t think a new function would really help in this case.

# Used to look like this
    p_data = {'pttl': pg_ttl, 'n_whl': g.n_whl, 'ln_sz': g.ln_w, 'shape': t_shp,
              'cmap': g.rcm, 'agn': g.u_again, 'bdx': g.bw_dx, 'bol': g.bw_o,
              'bcs': g.bw_s, 'bmlt': g.bw_m, 'mlts': sal.c_mlts
             }

    return render_template('disp_image.html', sp_img=data, type='mosaic', p_data=p_data)

# Now looks like this
    c_data = sal.get_curve_dtl()
    i_data = sal.get_image_dtl(pg_ttl)
    p_data = {'bdx': g.bw_dx, 'bol': g.bw_o, 'bcs': g.bw_s,
              'bmlt': g.bw_m, 'mlts': sal.c_mlts
             }

    return render_template('disp_image.html', sp_img=data, type='mosaic', c_data=c_data, i_data = i_data, p_data=p_data)

Refactor Display Template

And finally a significant refactoring of the disp_image.html template. Decided to switch from paragraphs to lists to display the information. That did involve a touch of refactoring in the CSS stylesheet (which I am not going to show here).

The whole of the template now looks like this.

{% extends 'base.html' %}

{% block title %}{{ i_data['pttl'] }}{% endblock %}

{% block content %}
  <h2>{{ i_data['pttl'] }}</h2>

    <img src='data:image/png;base64,{{ sp_img }}'/>

    <p>
      {% if type == 'basic' %}
        <a href="{{ url_for('sp_basic') }}">Back</a>
      {% elif type == 'gnarly' %}
        <a href="{{ url_for('sp_gnarly') }}">Back</a>
      {% elif type == 'mosaic' %}
        <a href="{{ url_for('sp_mosaic') }}">Back</a>
      {% endif %}
    </p>
    
    <h3>Curve Parameters</h3>
      {% if c_data['agn']%}
      <p>The previous curve data is being reused for this image.</p>
      {% endif %}
      <ul class="dots">
        <li>Wheels: {{ c_data['n_whl'] }} wheels (shape(s): {{ c_data['shape'] }})</li>
        <li>Symmetry: k_fold = {{ c_data['k_f'] }}, congruency = {{ c_data['cgv'] }}</li>
        <li>Frequencies: {{ c_data['freqs'] }}</li>
        <li>Widths: {{ c_data['wds'] }}</li>
        <li>Heights: {{ c_data['hts'] }}</li>
      </ul>

    {% if type in ['gnarly', 'mosaic'] %}
    <h3>Image Type Parameters</h3>
      {% if type == 'gnarly' %}
      <ul class="dots">
        <li>Drop data rows: {{ p_data['d_nbr'] }} {{ 'datarows' if p_data['d_nbr'] > 1 else 'datarow' }}</li>
        <li>From: dropped from the '{{ p_data['d_end'] }}' of the curve dataset</li>
      </ul>
      {% endif %}

      {% if type == 'mosaic' %}
      {% set w_rows = "adjacent datarows" if p_data['bdx'] == 1 else "datarows {} apart".format(p_data['bdx']) %}
      <ul class="dots">
        <li>Colouring: between {{ w_rows }} {{ "with" if p_data['bol'] else "without" }} overlap</li>
        <li>Sections: {{ p_data['bcs'] }} colour sections per datarow pairing</li>
        {% if p_data['bmlt'] %}
        <li>Multipliers: {{ p_data['mlts'] }}</li>
        {% endif %}
      </ul>
      {% endif %}
    {% endif %}

    <h3>Drawing Parameters</h3>
    
    <ul class="dots">
      <li>Colour map: {{ i_data['cmap'] }}</li>
      <li>Line width (if used): {{ i_data['ln_sz'] }}</li>
    </ul>
{% endblock %}

And, it now looks like the following.

screen shot of refactored information show on image display page

Done

That’s enough for this one. Had planned to do something else before I decided to upgrade the image information shown on the display page. Will see next time.

Until then, keep those fingers dancing.