3. Number Lines - automated

The LaTeX in this section is for one number line diagram.
The values in the diagram can be randomly generated by python.

3.1. Number line diagrams with answers

nl_plus_q

nl_plus_ans

nl_minus_neg_q

nl_minus_neg_ans

nl_minus_q

nl_minus_ans

nl_minus_pos_q

nl_minus_pos_ans

nl_plus_neg_q

nl_plus_neg_ans

nl_random_q

nl_random_ans


3.2. Splitting the LaTeX and modifying it to be built by python

The LaTeX from a single number lines equation is used as a starting point, split into 2 and modified.
The document template contains the preamble and the scaffold for the document.
The Diagram template contains the backtacking diagram LaTeX.

3.2.1. document template

The LaTeX number lines worksheet template is below.
 1\documentclass[preview,12pt]{standalone}
 2\usepackage{tikz}
 3\usetikzlibrary{positioning}
 4\usetikzlibrary {arrows.meta}
 5\usetikzlibrary{bending}
 6\usepackage{ulem}
 7\usepackage[a4paper, portrait, margin=1cm]{geometry}
 8
 9\def\jumpheight{10}
10% % \def\qgap{\rule[-1pt]{1.0em}{.25pt}}
11\def\qgap{\raisebox{-1pt}{\dotuline{\phantom{X}}}}
12
13
14\begin{document}
15    <<diagram>>
16\end{document}
<<diagram>> is placeholder text for the text that python will use to add the LaTeX for the number line diagram.

3.2.2. diagram template

The LaTeX number line diagram template is below.
 1\begin{tikzpicture}[scale=0.67]
 2    % axis, arrow style to-to
 3    \draw[{To[scale=1.3]}-{To[scale=1.3]}, line width=1pt] (-10.4, 0) -- (10.4, 0);
 4    % tick marks
 5    \foreach \x in {-10,-9,...,10}
 6        \draw[shift={(\x,0)},color=black, line width=1pt] (0pt,-14pt) -- (0pt,0pt);
 7    % numbers along each axis
 8    \foreach \x in {-10}
 9        \draw[shift={(\x -0.3,-0.8)},color=black] node[font=\large,text height=12pt] {$\x$};
10    \foreach \x in {0,10}
11        \draw[shift={(\x,-0.8)},color=black] node[font=\large,text height=12pt] {$\x$};
12    % numbers for dots
13    \draw[shift={(<<startval>>,-0.8)},color=black] node[font=\large,text height=12pt] {$<<startvaltxt>>$};
14    \draw[shift={(<<endval>>,-0.8)},color=black] node[font=\large,text height=12pt] {$<<endvaltxt>>$};
15    % dots
16    \filldraw[black] (<<startval>>,0) circle (4pt) node[above,yshift=-2pt] (a) {};
17    \filldraw[black] (<<endval>>,0) circle (4pt) node[above,yshift=-2pt] (b) {};
18    % arrow
19    \draw[-{To[scale=1.3, bend]},line width=1pt, color=black] (a.north)  .. controls  +(north:\jumpheight mm) and +(north:\jumpheight mm) .. node[above=2pt,xshift=-6pt,font=\large,text height=10pt] {$<<changevaltxt>>$} (b.north); % for addition
20    % equation at right end
21    \node [font=\large, anchor=east] at (15,1.65){$<<equtxt>>$};
22\end{tikzpicture}
The line \draw[shift={(<<startval>>,-0.8)},color=black] node[font=\large,text height=12pt] {$<<startvaltxt>>$}; has a placeholder <<startval>> which is replaced by python.
Other placeholders are tagged by <<   >>.

3.2.3. Python to create a number line diagram

The Python to create a number line diagram is below.
This Python code is a script that generates a PDF file and PNG file with a number line diagram based on some random parameters. Here is an outline of the code:
  • It opens three template files for creating a tex file with a number line diagram and reads their contents.

  • It calls a function called make1_diagram that takes the diagram template text as an argument and returns two strings: one for the question and one for the answer. The function calls the btf.get_1step_process_dict function to get a dictionary with some keys and values for creating the diagram. The function then replaces the placeholders in the template text with the corresponding values from the dictionary, depending on whether it is for the answer or question version. The function uses a loop to iterate over the keys and values of the dictionary and perform the replacement.

  • It replaces a placeholder in the LaTeX template texts with the diagram texts and writes them to two output files: one for the question and one for the answer.

  • It waits for two seconds and then calls another function called convert_to_pdf that takes the output tex files and converts them to PDF files using the pdflatex command.

  • It waits for another second and then calls another function called convert_pdf_to_png from the magick_pdf_to_png module that takes the output PDF files and converts them to PNG files using the magick command.

  • It prints β€œstarting” before calling the main function and β€œfinished” after it.

Further details:
  • The code imports the modules pathlib, subprocess, time, random, and the file in the currectn directory magick_pdf_to_png.

  • The code defines the paths for the template and output files using the Path class from pathlib.

  • The code defines the function called btf.get_1step_process_dict that returns a dictionary with some keys and values for creating the number line diagram. The function uses a random integer to choose one of five possible cases, each corresponding to a different style of adding or subtracting numbers on the number line. The function calls another helper function called val_in_list_exclude_zero that returns a random integer from a range excluding zero.

  • The code defines the function called go_right_dict that takes an argument called add_style and returns a dictionary with some keys and values for creating a number line diagram where the arrow goes to the right. The function sets the end value, start value, and change value based on the argument and uses some formatting to display them as text.

  • The code defines a function called go_left_dict that takes an argument called sub_style and returns a dictionary with some keys and values for creating a number line diagram where the arrow goes to the left. The function sets the end value, start value, and change value based on the argument and uses some formatting to display them as text.

  • The code defines two lists called kv_keys_ans and kv_keys_q that contain the keys of the dictionary that are relevant for the answer and question versions of the diagram, respectively.

  • The code defines the function called trimkey that takes a key and removes the _q suffix if it has one.

number_lines_diagram_maker.py

  1from pathlib import Path
  2import subprocess
  3import os
  4import time
  5import random
  6import magick_pdf_to_png
  7import number_lines_functions as nlf
  8
  9
 10currfile_dir = Path(__file__).parent
 11tex_template_path = currfile_dir / "number_lines_template.tex"
 12texans_template_path = currfile_dir / "number_lines_template.tex"
 13tex_diagram_template_path = currfile_dir / "number_lines_diagram_template.tex"
 14
 15
 16def convert_to_pdf(tex_path, outputdir):
 17    tex_path = Path(tex_path).resolve()
 18    outputdir = Path(outputdir).resolve()
 19    # for testing
 20    # print(f"tex_path: {tex_path}")
 21    # print(f"outputdir: {outputdir}")
 22    try:
 23        # Generate the PDF
 24        subprocess.run(["latexmk", "-pdf", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 25        # # Clean auxiliary files after successful PDF generation
 26        subprocess.run(["latexmk", "-c", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 27        # for hosted remove stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL for debugging any errors
 28        # Remove the .tex file manually
 29        # if tex_path.exists():
 30        #     os.remove(tex_path)
 31    except subprocess.CalledProcessError as e:
 32        print(f"Error: {e}")
 33
 34
 35
 36kv_keys_ans = ["startval", "endval", "startvaltxt", "endvaltxt", "changevaltxt", "equtxt"]
 37kv_keys_q = ["startval", "endval", "startvaltxt_q", "endvaltxt_q", "changevaltxt_q", "equtxt_q"]
 38
 39
 40def trimkey(key):
 41    key = key.replace("_q", "")
 42    return key
 43
 44
 45def make1_diagram(tex_diagram_template_txt, num):
 46    tex_diagram_template_txt_ans = tex_diagram_template_txt
 47    kv = nlf.getprocess_dict(num)
 48    for key, value in kv.items():
 49        # show answers
 50        if key in kv_keys_ans:
 51            tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace("<<" + key + ">>", value)
 52    for key, value in kv.items():
 53        # don't show answers, use ___ for gaps
 54        if key in kv_keys_q:
 55            tex_diagram_template_txt = tex_diagram_template_txt.replace("<<" + trimkey(key) + ">>", value)
 56    return tex_diagram_template_txt, tex_diagram_template_txt_ans
 57
 58
 59def main():
 60    num = input("Enter 1,2,3,4,5 or 6 for plus,minus_neg,minus,minus_pos,plus_neg,random \n")
 61    if num.strip().isdigit():
 62        num = int(num)
 63        if not num in [1, 2, 3, 4, 5, 6]:
 64            num = 6  # random by default
 65    else:
 66        num = 6  # random by default
 67    filename = input("Enter the base filename to be added to the prefix nl_: \n")
 68    if not filename:
 69        filename = "1"  # "nl_1st_q and nl_1st_ans as default file"
 70    # set names of files that are made
 71    # questions
 72    # questions
 73    tex_output_path = currfile_dir / f"nl_{filename}_q.tex"
 74    pdf_path = currfile_dir / f"nl_{filename}_q.pdf"
 75    png_path = currfile_dir / f"nl_{filename}_q.png"
 76
 77    # answers
 78    tex_output_path_ans = currfile_dir / f"nl_{filename}_ans.tex"
 79    pdf_path_ans = currfile_dir / f"nl_{filename}_ans.pdf"
 80    png_path_ans = currfile_dir / f"nl_{filename}_ans.png"
 81    # Read in the LaTeX template file
 82    with open(tex_template_path, "r") as infile:
 83        tex_template_txt = infile.read()
 84    # Read in the LaTeX template file for answers
 85    with open(texans_template_path, "r") as infile:
 86        tex_template_txt_ans = infile.read()
 87    # Read in the LaTeX diagram template file
 88    with open(tex_diagram_template_path, "r") as infile:
 89        tex_diagram_template_txt = infile.read()
 90
 91    # Generate the <<diagram>> replacement tex
 92    diagram_text, diagram_text_ans = make1_diagram(tex_diagram_template_txt, num)
 93    # Replace the <<diagram>> placeholder in the LaTeX template
 94    tex_template_txt = tex_template_txt.replace("<<diagram>>", diagram_text)
 95    tex_template_txt_ans = tex_template_txt_ans.replace("<<diagram>>", diagram_text_ans)
 96    # Write the question diagram tex to an output file
 97    with open(tex_output_path, "w") as outfile:
 98        outfile.write(tex_template_txt)
 99    # Write the answer diagram tex to an output file
100    with open(tex_output_path_ans, "w") as outfile:
101        outfile.write(tex_template_txt_ans)
102
103    # # Wait for the file to be created
104    time.sleep(2)
105
106    # convert to pdf
107    convert_to_pdf(tex_output_path_ans, currfile_dir)
108    convert_to_pdf(tex_output_path, currfile_dir)
109
110    time.sleep(1)
111    # convert to png
112    magick_pdf_to_png.convert_pdf_to_png(pdf_path, png_path)
113    magick_pdf_to_png.convert_pdf_to_png(pdf_path_ans, png_path_ans)
114
115
116if __name__ == "__main__":
117    print("starting")
118    main()
119    print("finished")