1. Coordinatesο
The python below requires the following .tex files:
The custom python module required is:
1"""
2Module of functions to return diagram dictionary for LaTeX
3"""
4
5import random
6
7
8def get_coordinates_dict(num=None):
9 coord_dict = get_points_dict(num)
10 coords_sections_dict = dict()
11 coords_sections_dict["points_to_list"] = format_latex_coordinates_for_listing(coord_dict)
12 coords_sections_dict["points_to_plot"] = format_latex_coordinates_for_plotting(coord_dict)
13 return coords_sections_dict
14
15
16
17def get_points_dict(num=None):
18 # limit to max of 20
19 if num is None or num > 20:
20 num = random.randint(5, 20) # Randomly choose how many points to generate
21 coord_labels_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
22 coord_dict = {}
23 used_x_values = set() # Track used x-values
24 used_y_values = set() # Track used y-values
25 for i in range(num):
26 label = coord_labels_list[i] # Get the next available letter
27 x, y = random_coordinate(used_x_values, used_y_values) # Ensure unique values
28 coord_dict[label] = (x, y)
29 return coord_dict
30
31
32def random_coordinate(used_x_values, used_y_values):
33 while True:
34 x = random.randint(-10, 10)
35 y = random.randint(-10, 10)
36 # Check constraints
37 if y == -1: # Avoid y = -1
38 continue
39 if y % 2 == 0 and (x == -1 or x == -2): # Avoid x = 1 or -2 when y is even
40 continue
41 if y in used_y_values: # Avoid reused y-values
42 continue
43 if x in used_x_values: # Avoid reused x-values
44 continue
45
46 # If valid, mark x and y as used
47 used_x_values.add(x)
48 used_y_values.add(y)
49 break
50 return x, y
51
52
53def format_latex_coordinates_for_listing(coord_dict):
54 latex_str = r"\[" + "\n"
55 latex_str += r"\begin{array}{lllll}" + "\n" # Define 5 columns
56 # Create list of formatted points
57 items = [f"{key}({x}, {y})" for key, (x, y) in coord_dict.items()]
58 # Split items into rows of 5 points
59 rows = [items[i : i + 5] for i in range(0, len(items), 5)]
60 # Add rows to LaTeX string with `\quad` spacing
61 for row in rows:
62 latex_str += " \quad & ".join(row) + r" \\" + "\n"
63 latex_str += r"\end{array}" + "\n"
64 latex_str += r"\]"
65 return latex_str
66
67
68
69def format_latex_coordinates_for_plotting(coord_dict):
70 latex_str = ""
71 for name, (x, y) in coord_dict.items():
72 latex_str += f"\\fill ({x},{y}) circle (4pt);\n"
73 latex_str += f"\\node[xshift=1.9em, yshift=7pt] at ({x},{y}) {{\\small {name}({x},{y})}};\n"
74 return latex_str
75
76# print(get_coordinates_dict(20)["points_to_plot"])
The Python to create booklets of questions involving coordinates, is below.
1from pathlib import Path
2import subprocess
3import os
4import time
5
6# import magick_pdf_to_png
7import coordinates_functions as coordf
8
9currfile_dir = Path(__file__).parent
10tex_template_path = currfile_dir / "coordinates_booklet_template.tex"
11texans_template_path = currfile_dir / "coordinates_booklet_ans_template.tex"
12tex_diagram_template_path = currfile_dir / "coordinates_booklet_diagram_template.tex"
13
14
15def convert_to_pdf(tex_path, outputdir):
16 tex_path = Path(tex_path).resolve()
17 outputdir = Path(outputdir).resolve()
18 # for testing
19 # print(f"tex_path: {tex_path}")
20 # print(f"outputdir: {outputdir}")
21 try:
22 # Generate the PDF
23 subprocess.run(["latexmk", "-pdf", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
24 # # Clean auxiliary files after successful PDF generation
25 subprocess.run(["latexmk", "-c", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
26 # for hosted remove stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL for debugging any errors
27 # Remove the .tex file manually
28 # if tex_path.exists():
29 # os.remove(tex_path)
30 except subprocess.CalledProcessError as e:
31 print(f"Error: {e}")
32
33
34kv_keys_q = ["points_to_list"]
35kv_keys_ans = ["points_to_list", "points_to_plot"]
36ky_keys_to_clear = ["points_to_plot"]
37
38
39def make1_diagram(tex_diagram_template_txt, nump):
40 tex_diagram_template_txt_ans = tex_diagram_template_txt
41 kv = coordf.get_coordinates_dict(nump)
42 for key, value in kv.items():
43 # show answers
44 if key in kv_keys_ans:
45 tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace(
46 "<<" + key + ">>", value)
47 for key, value in kv.items():
48 # don't show answers
49 if key in kv_keys_q:
50 tex_diagram_template_txt = tex_diagram_template_txt.replace(
51 "<<" + key + ">>", value)
52
53 if key in ky_keys_to_clear:
54 tex_diagram_template_txt = tex_diagram_template_txt.replace(
55 "<<" + key + ">>", "")
56 return tex_diagram_template_txt, tex_diagram_template_txt_ans
57
58
59def main():
60 numq = input("Enter the number of graphs from 1 to 10 \n")
61 if numq.strip().isdigit():
62 numq = int(numq)
63 if not numq in range(1, 11):
64 numq = 2 # default
65 else:
66 numq = 2 # default
67 #
68 nump = input("Enter the number of points to plot from 1 to 20 \n")
69 if nump.strip().isdigit():
70 nump = int(nump)
71 if not nump in range(1, 21):
72 nump = 5 # default
73 else:
74 nump = 5 # default
75 #
76
77 filename = input(
78 "Enter the base filename to be added to the prefix coordinates_Bk_: \n"
79 )
80 if not filename:
81 filename = "1" # "coordinates_Bk_1_q and coordinates_Bk_1_ans as default file"
82 # set names of files that are made
83 # questions
84 tex_output_path = currfile_dir / f"coordinates_Bk_{filename}_q.tex"
85 pdf_path = currfile_dir / f"coordinates_Bk_{filename}_q.pdf"
86
87 # answers
88 tex_output_path_ans = currfile_dir / f"coordinates_Bk_{filename}_ans.tex"
89 pdf_path_ans = currfile_dir / f"coordinates_Bk_{filename}_ans.pdf"
90
91 # Read in the LaTeX template file
92 with open(tex_template_path, "r") as infile:
93 tex_template_txt = infile.read()
94 # Read in the LaTeX template file for answers
95 with open(texans_template_path, "r") as infile:
96 tex_template_txt_ans = infile.read()
97 # Read in the LaTeX diagram template file
98 with open(tex_diagram_template_path, "r") as infile:
99 tex_diagram_template_txt = infile.read()
100
101 # Generate the <<diagram>> replacement tex
102 # diagram_text, diagram_text_ans = make1_diagram(tex_diagram_template_txt)
103
104 # <<diagrams>>
105 # generate diagrams text and text for answers
106 diagrams_text = ""
107 diagrams_text_ans = ""
108 # add the headtext; disabled for now using r"" wno needed as numbers in minipage itself
109 posttext = r"\pagebreak ~ \newline ~ \newline"
110 for i in range(1, numq + 1):
111 img_tex, img_tex_ans = make1_diagram(tex_diagram_template_txt, nump)
112
113 diagrams_text += img_tex
114 diagrams_text_ans += img_tex_ans
115 if i < numq:
116 diagrams_text += posttext
117 diagrams_text_ans += posttext
118
119 # Replace the <<diagrams>> placeholder in the LaTeX template
120 tex_template_txt = tex_template_txt.replace("<<diagrams>>", diagrams_text)
121 tex_template_txt_ans = tex_template_txt_ans.replace(
122 "<<diagrams>>", diagrams_text_ans)
123 # Write the question diagrams tex to an output file
124 with open(tex_output_path, "w") as outfile:
125 outfile.write(tex_template_txt)
126 # Write the answer diagrams tex to an output file
127 with open(tex_output_path_ans, "w") as outfile:
128 outfile.write(tex_template_txt_ans)
129
130 # Wait for the files to be created
131 time.sleep(1)
132 # convert to pdf
133 convert_to_pdf(tex_output_path, currfile_dir)
134 convert_to_pdf(tex_output_path_ans, currfile_dir)
135
136 # Wait for the files to be created
137 # time.sleep(1)
138 # convert to png
139 # magick_pdf_to_png.convert_pdf_to_png(pdf_path, png_path)
140 # magick_pdf_to_png.convert_pdf_to_png(pdf_path_ans, png_path_ans)
141
142
143if __name__ == "__main__":
144 print("starting")
145 main()
146 print("finished")