2. Coordinates2ο
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_plot_without_xy"] = format_latex_coordinates_for_plotting_without_xy(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_plotting_without_xy(coord_dict):
54 latex_str = ""
55 for name, (x, y) in coord_dict.items():
56 latex_str += f"\\fill ({x},{y}) circle (4pt);\n"
57 latex_str += f"\\node[xshift=1.9em, yshift=7pt] at ({x},{y}) {{\\small {name}(\\hspace{{0.6cm}},\\hspace{{0.6cm}})}};\n"
58 return latex_str
59
60
61
62
63def format_latex_coordinates_for_plotting(coord_dict):
64 latex_str = ""
65 for name, (x, y) in coord_dict.items():
66 latex_str += f"\\fill ({x},{y}) circle (4pt);\n"
67 latex_str += f"\\node[xshift=1.9em, yshift=7pt] at ({x},{y}) {{\\small {name}({x},{y})}};\n"
68 return latex_str
69
70# 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_plot_without_xy"]
35ky_keys_q_to_clear = ["points_to_plot"]
36kv_keys_ans = ["points_to_plot"]
37ky_keys_ans_to_clear = ["points_to_plot_without_xy"]
38
39
40def make1_diagram(tex_diagram_template_txt, nump):
41 tex_diagram_template_txt_ans = tex_diagram_template_txt
42 kv = coordf.get_coordinates_dict(nump)
43 for key, value in kv.items():
44 # show answers
45 if key in kv_keys_ans:
46 tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace(
47 "<<" + key + ">>", value)
48 if key in ky_keys_ans_to_clear:
49 tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace(
50 "<<" + key + ">>", "")
51 for key, value in kv.items():
52 # show questions
53 if key in kv_keys_q:
54 tex_diagram_template_txt = tex_diagram_template_txt.replace(
55 "<<" + key + ">>", value)
56
57 if key in ky_keys_q_to_clear:
58 tex_diagram_template_txt = tex_diagram_template_txt.replace(
59 "<<" + key + ">>", "")
60 return tex_diagram_template_txt, tex_diagram_template_txt_ans
61
62
63def main():
64 numq = input("Enter the number of graphs from 1 to 10 \n")
65 if numq.strip().isdigit():
66 numq = int(numq)
67 if not numq in range(1, 11):
68 numq = 2 # default
69 else:
70 numq = 2 # default
71 #
72 nump = input("Enter the number of points to plot from 1 to 20 \n")
73 if nump.strip().isdigit():
74 nump = int(nump)
75 if not nump in range(1, 21):
76 nump = 5 # default
77 else:
78 nump = 5 # default
79 #
80
81 filename = input(
82 "Enter the base filename to be added to the prefix coordinates_Bk_: \n"
83 )
84 if not filename:
85 filename = "1" # "coordinates_Bk_1_q and coordinates_Bk_1_ans as default file"
86 # set names of files that are made
87 # questions
88 tex_output_path = currfile_dir / f"coordinates_Bk_{filename}_q.tex"
89 pdf_path = currfile_dir / f"coordinates_Bk_{filename}_q.pdf"
90
91 # answers
92 tex_output_path_ans = currfile_dir / f"coordinates_Bk_{filename}_ans.tex"
93 pdf_path_ans = currfile_dir / f"coordinates_Bk_{filename}_ans.pdf"
94
95 # Read in the LaTeX template file
96 with open(tex_template_path, "r") as infile:
97 tex_template_txt = infile.read()
98 # Read in the LaTeX template file for answers
99 with open(texans_template_path, "r") as infile:
100 tex_template_txt_ans = infile.read()
101 # Read in the LaTeX diagram template file
102 with open(tex_diagram_template_path, "r") as infile:
103 tex_diagram_template_txt = infile.read()
104
105 # Generate the <<diagram>> replacement tex
106 # diagram_text, diagram_text_ans = make1_diagram(tex_diagram_template_txt)
107
108 # <<diagrams>>
109 # generate diagrams text and text for answers
110 diagrams_text = ""
111 diagrams_text_ans = ""
112 # add the headtext; disabled for now using r"" wno needed as numbers in minipage itself
113 posttext = r"\pagebreak ~ \newline ~ \newline"
114 for i in range(1, numq + 1):
115 img_tex, img_tex_ans = make1_diagram(tex_diagram_template_txt, nump)
116
117 diagrams_text += img_tex
118 diagrams_text_ans += img_tex_ans
119 if i < numq:
120 diagrams_text += posttext
121 diagrams_text_ans += posttext
122
123 # Replace the <<diagrams>> placeholder in the LaTeX template
124 tex_template_txt = tex_template_txt.replace("<<diagrams>>", diagrams_text)
125 tex_template_txt_ans = tex_template_txt_ans.replace(
126 "<<diagrams>>", diagrams_text_ans)
127 # Write the question diagrams tex to an output file
128 with open(tex_output_path, "w") as outfile:
129 outfile.write(tex_template_txt)
130 # Write the answer diagrams tex to an output file
131 with open(tex_output_path_ans, "w") as outfile:
132 outfile.write(tex_template_txt_ans)
133
134 # Wait for the files to be created
135 time.sleep(1)
136 # convert to pdf
137 convert_to_pdf(tex_output_path, currfile_dir)
138 convert_to_pdf(tex_output_path_ans, currfile_dir)
139
140 # Wait for the files to be created
141 # time.sleep(1)
142 # convert to png
143 # magick_pdf_to_png.convert_pdf_to_png(pdf_path, png_path)
144 # magick_pdf_to_png.convert_pdf_to_png(pdf_path_ans, png_path_ans)
145
146
147if __name__ == "__main__":
148 print("starting")
149 main()
150 print("finished")