API reference · assignments/hw2.py · 926 lines
assignments.hw2
Assignment 2 autograder — exploratory visualization with matplotlib, seaborn and altair.
Students choose their own dataset, so there is no answer key: nothing about the content of a chart can be checked. What can be checked is what the code demonstrably did, and the split runs straight down the middle of the assignment text:
- Mechanical, graded automatically. An Altair chart compiles to a Vega-Lite specification and the notebook's own output carries it, so a mean/count/bin transformation and an interval brush are read out of the spec rather than guessed from source text. Whether a matplotlib or seaborn chart was drawn, and whether it rendered, is likewise a fact.
- Judgement, graded by a person. The assignment says the matplotlib chart is marked on "colour choices and clarity", and asks for written reasoning under each chart. A picture's quality and a paragraph's substance are not machine facts. Those items come back as
manual_review— always, whatever they score — carrying a provisional score built from real signals plus the evidence behind it, so a TA confirms or adjusts instead of starting from a blank box.
Students hand in a notebook without their dataset, so the grading run has nothing to read: it fails at read_csv and draws nothing. The charts are therefore read out of the outputs the student already saved in the notebook they submitted (grader/charts.py merges the two sources cell by cell, so this still uses a freshly executed chart wherever one exists). What is being marked is that the student can produce these elements — the correctness of their numbers was never checkable with a dataset of their own choosing.
Where a check cannot see the work at all — no notebook, no outputs — it says so and asks for a human, rather than recording a zero the student would have to appeal (design.md §19, §25).
Summary
| Name | Kind | Description |
|---|---|---|
HW2Grader | class |
Constants
| Name | Value | Notes |
|---|---|---|
URL_RE | re.compile('https?://[^\\s\'\\"<>)]+', re.IGNORECASE) | |
LIBRARY_LABELS | {MATPLOTLIB: 'matplotlib', SEABORN: 'seaborn', ALTAIR: 'Altair'} |
Classes
No description.
Class attributes
| Name | Type | Default | Notes |
|---|---|---|---|
assignment_id | | 'hw2' |
Methods
- evidence(ctx: GradingContext) -> ChartEvidence #[source]
Charts found in this submission, read once and reused by every check.
- required_count(library: str, default: int = 1) -> int #[source]
How many charts of a library the rubric asks for.
Read back off the rubric so the conclusions check cannot drift out of step with the chart checks when a TA edits the YAML.
- evidence_note(evidence: ChartEvidence) -> dict[str, Any] #[source]
No description.
- no_evidence_result(item: RubricItem, ctx: GradingContext, evidence: ChartEvidence) -> RubricItemResult #[source]
No notebook could be read for charts — never an automatic zero.
Rubric checks 12
Each check_<rubric_id> method grades the rubric item with that id and returns one RubricItemResult.
- check_notebook_execution(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
10 ptsexecutionNotebook was run and submitted with its outputsrubrics/hw2.yaml
Did the student run their notebook through before handing it in?
The grader has no copy of the dataset, so it cannot answer this by running the notebook: without the data every cell after
read_csvfails, and a failure caused by the missing file says nothing about the student. What it can read is the state the notebook was saved in — which cells carry output, and which carry an error — and that is exactly the question the assignment cares about here.If an instructor does supply the data, a clean execution in this run is the stronger answer and takes over.
Config keys:
error_penalty_eachlow_coverage_penaltymax_error_penaltymin_output_coverageno_outputs_penaltypartial_credit_ratio
- check_data_loading(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
10 ptsstructuralDataset loaded from a relative pathrubrics/hw2.yaml
Is a dataset loaded, and loaded the way the instructions ask?
Deliberately narrow. Students pick their own dataset and do not hand it in, so there is nothing to compare against and nothing about the data's contents is graded — only that the notebook reads one, with pandas, through a relative path.
Config keys:
absolute_path_penaltyimport_alternativesmissing_read_penaltyremote_read_penaltyrequired_imports
- check_matplotlib_chart(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
10 ptsdeterministicMatplotlib chart present and renderedrubrics/hw2.yaml
At least one chart drawn with matplotlib (or pandas/geopandas .plot).
Config keys:
librarynot_rendered_credit_ratiorequired_countsubmitted_only_confidence
- check_seaborn_chart(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
10 ptsdeterministicSeaborn chart present and renderedrubrics/hw2.yaml
At least one chart drawn with seaborn, distinct from the matplotlib chart.
Config keys:
librarynot_rendered_credit_ratiorequired_countsubmitted_only_confidence
- check_altair_charts(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
15 ptsdeterministicThree Altair chartsrubrics/hw2.yaml
Three distinct Altair charts, each of which rendered.
Config keys:
distinctness_penalty_ratiolibrarynot_rendered_credit_ratiorequired_countsubmitted_only_confidence
- check_altair_transformation(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
8 ptsdeterministicAltair transformation usedrubrics/hw2.yaml
At least one Altair chart applies a transformation — mean, count, binning, time unit, window — either as transform_*() or inside an encoding.
Config keys:
source_patternsstatic_only_credit_ratio
- check_altair_brush_selection(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
7 ptsdeterministicBrush selection usedrubrics/hw2.yaml
An interval (brush) selection is added to at least one Altair chart.
Config keys:
point_selection_credit_ratiosource_patternsstatic_only_credit_ratio
- check_altair_dashboard_extra_credit(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
0 ptsdeterministicExtra credit: cross-filtered two-chart Altair dashboardrubrics/hw2.yaml
Two Altair charts composed together where a selection on one filters the other via transform_filter(). Worth no points in the rubric total; when it is found, the item is flagged so a TA can award the bonus by hand.
Config keys:
suggested_points
- check_matplotlib_rationale(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
5 ptsqualitativeReasoning for using matplotlibrubrics/hw2.yaml
A written explanation of what aspect of the data is shown and why matplotlib suits it.
Config keys:
keywordslibraryllm_criteriamin_wordspartial_words
- check_seaborn_rationale(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
5 ptsqualitativeMotivation for the seaborn plot typerubrics/hw2.yaml
A written motivation for the type of seaborn plot chosen and why it fits the data.
Config keys:
keywordslibraryllm_criteriamin_wordspartial_words
- check_matplotlib_aesthetics(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
5 ptsqualitativeMatplotlib chart aesthetics (colour and clarity)rubrics/hw2.yaml
The assignment grades colour choices and clarity. Labelling and colour signals are extracted automatically; the picture is judged by a person.
Config keys:
libraryprovisional_ceiling_ratioweighted_signals
- check_chart_conclusions(ctx: GradingContext, item: RubricItem) -> RubricItemResult #[source]
15 ptsqualitativeWritten conclusion below each chartrubrics/hw2.yaml
A short discussion of the main conclusion in a markdown cell below each chart. Coverage and position are checked automatically; whether each discussion actually says something is judged by a person.
Config keys:
expected_chartsllm_criteriamin_wordspartial_words