input_file = '_input.yaml'core
In order to avoid tqdm’s experimental warning
Command-line arguments
The function below just parses command-line arguments and pass them to the build function below.
main
main ()
Parses command-line arguments to be passed to build
Auxiliary functions
A function to obtain the __init__ parameters for a class from the corresponding settings.
init_parameters_from_settings
init_parameters_from_settings (cls_settings:dict)
Returns a dictionary with the initialization parameters for a question
| Type | Details | |
|---|---|---|
| cls_settings | dict | Settings for the class, which should include statement, feedback and, optionally, time |
| Returns | dict | Exact parameters that must be passed when instantiating the class. |
The name for a testing file
output file: quiz.yaml
pictures base directory: tc/midterm3
categories:
- name: Test category
classes:
- name: TestClass
question base name: Test class
init parameters:
distribution: Gaussian
statement: |
Consider a random variable, $X$, with mean $ \mu = !mean $ and variance...
feedback: |
Clearly, $Y$ is...
time: 15
number of instances: 2Overwriting _input.yaml
The initialization parameters for the first class in the first category can be obtained as
input_data = py2gift.util.yaml_to_dict(input_file)
init_parameters_from_settings(input_data['categories'][0]['classes'][0]){'statement': un-filled template:
Consider a random variable, $$X$$, with mean $$ \mu = $mean $$ and variance...,
'feedback': Clearly, $Y$ is...,
'time': 15,
'distribution': 'Gaussian'}
If init_parameters is absent,
no_init_input_file = '_input2.yaml'output file: quiz.yaml
pictures base directory: tc/midterm3
categories:
- name: Test category
classes:
- name: TestClass
question base name: Test class
statement: |
Consider a random variable, $X$, with mean $ \mu = !mean $ and variance...
feedback: |
Clearly, $Y$ is...
time: 15
number of instances: 2Overwriting _input2.yaml
, then only basic parameters will be passed when instatiating the class
input_data = py2gift.util.yaml_to_dict(no_init_input_file)
init_parameters_from_settings(input_data['categories'][0]['classes'][0]){'statement': un-filled template:
Consider a random variable, $$X$$, with mean $$ \mu = $mean $$ and variance...,
'feedback': Clearly, $Y$ is...,
'time': 15}
Processing of a bunch of questions
Building a GIFT file from generators’ settings
The workhorse of the library.
build
build (settings:str|dict, local_run:bool, questions_module:module, parameters_file:str|dict='parameters.yaml', no_checks:bool=False, embed_images:bool=False)
Generates a GIFT file
| Type | Default | Details | |
|---|---|---|---|
| settings | str | dict | Settings for all the questions (generators) | |
| local_run | bool | If True, pictures will not be copied to a remote host |
|
| questions_module | module | A module or structure to hold the classes referenced in the settings | |
| parameters_file | str | dict | parameters.yaml | Parameters to be passed to “gift-wrapper” |
| no_checks | bool | False | If True LaTeX formulas are not be checked |
| embed_images | bool | False | If True, images will be embedded in the questions (rather than linked) |
| Returns | None |
This function expects, among other things, an input file (defined above), a module implementing the classes referenced in the latter, and a parameters file.
Module with questions
This can be used in the same way as a module would.
class FakeModule:
class TestClass(py2gift.question.NumericalQuestionGenerator):
"Dumb testing class"
def __init__(
self,
statement: py2gift.question.TemplatedLatexText, # Statement of the question
feedback: py2gift.question.TemplatedLatexText, # Feedback of the question
distribution: str, # ?
time: int | None = None, # Expectated time required to carry out the question
prng: np.random.RandomState = np.random.RandomState(42) # Pseudo-random numbers generator
) -> None:
super().__init__(statement, feedback, time, prng)
self.distribution = distribution
def setup(self):
mean = np.random.rand()
self.statement.fill(mean=mean)
self.solution = 42
self.error = '10%'Parameters file
parameters_file = '_parameters.yaml'images hosting:
ssh:
user: mvazquez
# below, one should specify either a password for the user or "public key" file but NOT both of them
password:
# "~" stands for the user's home directory (in Linux for one...)
public_key: ~/.ssh/id_rsa_mymachine.pub
copy:
# machine into which files will be copied
host: hidra1
# the path that in the remote machine acts as root of the publicly visible directories hierarchy (hence it's not
# visible from outside); it *should* exist ("." stands for the working directory when you ssh into the machine)
public filesystem root: ./public_html
# public address from which the images will hang
public URL: http://www.tsc.uc3m.es/~mvazquez/
latex:
# auxiliary TeX file that will be created to check that formulas can be compiled
auxiliary file: __latex_check.texOverwriting _parameters.yaml
build(input_file, local_run=True, questions_module=FakeModule, parameters_file=parameters_file, no_checks=True)file "quiz.gift.txt" created
The file actually created underneath by build (the name, quiz.yaml, was set above in the input_file)
pictures base directory: tc/midterm3
categories:
- name: Test category
questions:
- class: Numerical
statement: "Consider a random variable, $X$, with mean $ \\mu = 0.713 $ and
variance...\n"
feedback: "Clearly, $Y$ is...\n"
time: '15'
solution:
value: 42
error: 10%
name: Test class I
- class: Numerical
statement: "Consider a random variable, $X$, with mean $ \\mu = 0.946 $ and
variance...\n"
feedback: "Clearly, $Y$ is...\n"
time: '15'
solution:
value: 42
error: 10%
name: Test class II
is ultimately processed by gift_wrapper to yield
$CATEGORY: $course$/Test category
::Test class I::[html]Consider a random variable, \\(X\\), with mean \\( \\mu \= 0.713 \\) and variance...<br><br><br><i>Estimated time\: 15 minutes</i><br>{
# =%100%42:4.2#
####Clearly, \\(Y\\) is...
}
::Test class II::[html]Consider a random variable, \\(X\\), with mean \\( \\mu \= 0.946 \\) and variance...<br><br><br><i>Estimated time\: 15 minutes</i><br>{
# =%100%42:4.2#
####Clearly, \\(Y\\) is...
}
This is the file that is actually imported from Moodle, and quiz.yaml is mostly a side effect.
!rm quiz.yaml quiz.gift.txtOne can also pass directly the dict with the settings.
settings = py2gift.util.yaml_to_dict(input_file)
build(settings, local_run=True, questions_module=FakeModule, parameters_file=parameters_file, no_checks=True)file "quiz.gift.txt" created
pictures base directory: tc/midterm3
categories:
- name: Test category
questions:
- class: Numerical
statement: "Consider a random variable, $X$, with mean $ \\mu = 0.428 $ and
variance...\n"
feedback: "Clearly, $Y$ is...\n"
time: '15'
solution:
value: 42
error: 10%
name: Test class I
- class: Numerical
statement: "Consider a random variable, $X$, with mean $ \\mu = 0.63 $ and
variance...\n"
feedback: "Clearly, $Y$ is...\n"
time: '15'
solution:
value: 42
error: 10%
name: Test class II
Processing a single question
This is mostly intended for previewing a question in a jupyter notebook.
Building a single question
This function returns settings that allow building a question using gift-wrapper.
build_question
build_question (question_generator:py2gift.question.QuestionGenerator, category_name:str, settings:dict, n_question:int=0)
Returns the settings for building a question using “gift-wrapper”
| Type | Default | Details | |
|---|---|---|---|
| question_generator | QuestionGenerator | The question generator that will generate the appropirate settings | |
| category_name | str | The name of category the class belongs to | |
| settings | dict | User settings | |
| n_question | int | 0 | The number of instances to be returned |
| Returns | dict | Settings that allow building the question using “gift-wrapper” |
For testing, we need some settings. It is more natural to read and write them in a file.
settings_file = '_settings.yaml'output file: quiz.yaml
pictures base directory: pics
categories:
- name: Category 1
classes:
- name: A
question base name: A numerical question
statement: What is...
feedback: Well...
parameters:
- a: 5
b: 3
- name: A
question base name: Another numerical question
statement: What is...
feedback: Well...
number of instances: 2
# -----------------------------
- name: Category 2
classes:
- name: B
question base name: A multiple-choice question
init parameters:
nodes: ['S1', 'S2']
statement: |
Consider...
feedback: |
We must...
parameters: &dijkstra_parameters
- n: 0
- n: 1
- name: Category 3
classes:
- name: C
question base name: Another numerical question
statement: What is...
feedback: Well...
number of instances: 2Overwriting _settings.yaml
Next, we need to define the classes referenced above (A, B and C)
class A(py2gift.question.NumericalQuestionGenerator):
def setup(self, a: int, b:int):
self.solution = 42
self.error = '10%'
class B(py2gift.question.MultipleChoiceQuestionGenerator):
def __init__(
self, statement: py2gift.question.TemplatedLatexText, feedback: py2gift.question.TemplatedLatexText,
nodes: list,
time: int | None = None, prng: np.random.RandomState = np.random.RandomState(42)) -> None:
super().__init__(statement, feedback, time, prng)
self.nodes = nodes
def setup(self, n:int):
self.wrong_answers = [
['yes', 50],
['no', -50],
['nope', -50],
['yessss!!!', 50]
]
class C(py2gift.question.NumericalQuestionGenerator):
def setup(self):
self.solution = 52
self.error = '10%'build_question(A, category_name='Category 1', settings=py2gift.util.yaml_to_dict(settings_file)){'class': 'Numerical',
'statement': 'What is...',
'feedback': 'Well...',
'solution': {'value': 42, 'error': '10%'}}
build_question(C, category_name='Category 3', settings=py2gift.util.yaml_to_dict(settings_file)){'class': 'Numerical',
'statement': 'What is...',
'feedback': 'Well...',
'solution': {'value': 52, 'error': '10%'}}
Previewing
The settings of a question (in the form of a dictionary),
question_settings = {
'class': 'Numerical',
'statement': 'What is the value of $\\pi$?',
'solution': {'value': 3.14, 'error': '50%'},
'feedback': 'well, $\\pi$'
}, can be turned into a markdown string by py2gift.markdown.settings_to_markdown
py2gift.util.render_latex(py2gift.markdown.settings_to_markdown(question_settings))Statement
What is the value of \(\Large \pi\)?
Feedback
well, \(\Large \pi\)
Solution
3.14 (error: .57)
generator_to_markdown
generator_to_markdown (settings:str|pathlib.Path|dict, category:str, cls: <module'py2gift.question'from'/home/runner/work/py 2gift/py2gift/py2gift/question.py'>)
Returns markdown text from a generator
| Type | Details | |
|---|---|---|
| settings | str | pathlib.Path | dict | Settings |
| category | str | Category of the question |
| cls | py2gift.question | Class implementing the generator |
| Returns | str | Markdown text |
py2gift.util.render_latex(generator_to_markdown(settings_file, category='Category 1', cls=A))Statement
What is…
Feedback
Well…
Solution
42 (error: .2)
Preprocessing tex files
Function to turn a \(\TeX\) file into an svg. It returns a markdown string that allows to visualize it in a cell.
latex_to_markdown
latex_to_markdown (input_file:str|pathlib.Path, delete_input_file_afterwards:bool=False)
Returns markdown text that shows the result of compiling a TeX file
| Type | Default | Details | |
|---|---|---|---|
| input_file | str | pathlib.Path | TeX file | |
| delete_input_file_afterwards | bool | False | If True the TeX file is deleted after conversion to svg |
| Returns | str | Markdown text |
A sample \(\TeX\) file,
tex_file = '_sample.tex', is written
\documentclass[]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\node[draw, text width=60, align=center,font=\small,minimum height=80] {The Ingenious Gentleman Don Quixote of La Mancha};
\end{tikzpicture}
\end{document}Overwriting _sample.tex
However, you can only run the cell below if you have a \(\LaTeX\) installation with TikZ
#py2gift.util.render_latex(latex_to_markdown(tex_file, delete_input_file_afterwards=True))