3. Number Lines - automatedο
3.1. Number line diagrams with answersο
3.2. Splitting the LaTeX and modifying it to be built by pythonο
3.2.1. document templateο
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ο
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}
\draw[shift={(<<startval>>,-0.8)},color=black] node[font=\large,text height=12pt] {$<<startvaltxt>>$}; has a placeholder <<startval>> which is replaced by python.<< >>.3.2.3. Python to create a number line diagramο
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_diagramthat takes the diagram template text as an argument and returns two strings: one for the question and one for the answer. The function calls thebtf.get_1step_process_dictfunction 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_pdfthat takes the output tex files and converts them to PDF files using thepdflatexcommand.It waits for another second and then calls another function called
convert_pdf_to_pngfrom themagick_pdf_to_pngmodule that takes the output PDF files and converts them to PNG files using themagickcommand.It prints βstartingβ before calling the main function and βfinishedβ after it.
The code imports the modules
pathlib,subprocess,time,random, and the file in the currectn directorymagick_pdf_to_png.The code defines the paths for the template and output files using the
Pathclass frompathlib.The code defines the function called
btf.get_1step_process_dictthat 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 calledval_in_list_exclude_zerothat returns a random integer from a range excluding zero.The code defines the function called
go_right_dictthat takes an argument calledadd_styleand 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_dictthat takes an argument calledsub_styleand 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_ansandkv_keys_qthat 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
trimkeythat takes a key and removes the_qsuffix if it has one.
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")