MUSA Graderv0.1.0

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

NameKindDescription
HW2Graderclass

Constants

NameValueNotes
URL_REre.compile('https?://[^\\s\'\\"<>)]+', re.IGNORECASE)
LIBRARY_LABELS{MATPLOTLIB: 'matplotlib', SEABORN: 'seaborn', ALTAIR: 'Altair'}

Classes

class HW2Grader(AssignmentGrader) #[source]

registered grader

No description.

Class attributes

NameTypeDefaultNotes
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_csv fails, 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_each low_coverage_penalty max_error_penalty min_output_coverage no_outputs_penalty partial_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_penalty import_alternatives missing_read_penalty remote_read_penalty required_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: library not_rendered_credit_ratio required_count submitted_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: library not_rendered_credit_ratio required_count submitted_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_ratio library not_rendered_credit_ratio required_count submitted_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_patterns static_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_ratio source_patterns static_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: keywords library llm_criteria min_words partial_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: keywords library llm_criteria min_words partial_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: library provisional_ceiling_ratio weighted_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_charts llm_criteria min_words partial_words