ubc_mds_helper is a project that helps students in the UBC Masters of Data Science (MDS) program better understand and plan their academic timeline.
With the large number of deadlines and the variability in workload across the 5 weeks within each block, it is difficult for students to get a sense of where they are in the program at a given time. This helper package provides date-based tools to describe a student’s academic position, program phase, and progress, and support planning for personal commitments, absences, late submissions, and meeting course-level requirements.
Status
We set up our date configuration to the 2025/2026 cycle, as shown in config.py.
If other years are needed, the config.py file would need to be updated.
from ubc_mds_helper.status import statusfrom ubc_mds_helper.config import PROGRAM_CONFIG_2025_2026status(PROGRAM_CONFIG_2025_2026, "January 15, 2026")
The late_assignment() function applies the UBC MDS late-submission policy.
It prints the late penalty applied to an assignment based on the number of days it is late, and returns the adjusted grade.
Inputs - raw_grade (float or int): original grade (0–100) - late_count (int): number of previous late submissions - is_lower_stakes (bool): if True, late submissions are not accepted for lower-stakes assignments (e.g., quizzes, labs)
Outputs - float: grade after the late-submission scaling is applied
from ubc_mds_helper.assessments import late_assignment# Example 1: on-time submissionprint("\nExample 1: on-time submission")adjusted_grade = late_assignment( raw_grade=85, late_count=0, is_lower_stakes=False)print("Adjusted grade:", adjusted_grade) # Expected: 85# Example 2: late submission with no prior late submissionsprint("\nExample 2: late submission with no prior late submissions")adjusted_grade = late_assignment( raw_grade=90, late_count=0, is_lower_stakes=False)print("Adjusted grade:", adjusted_grade) # Expected: 80.0
Example 1: on-time submission
Status: Late (1st occurrence)
Late count: 1
Scaling factor: 0.75
Adjusted grade: 63.75
Example 2: late submission with no prior late submissions
Status: Late (1st occurrence)
Late count: 1
Scaling factor: 0.75
Adjusted grade: 67.5
Grades
The needed_to_pass() function helps you answer a very practical question:
“Given the grades I already have, what minimum grade do I need on each remaining component to finish the course with at least 60%?”
It assumes you will earn the same grade on every remaining component, and returns that required grade for each remaining item.
What grading schemes are supported?
needed_to_pass() supports two course grading layouts, selected by course_type: 1. course_type=“quiz”
lab1, lab2, lab3, lab4 are 12.5% each quiz1, quiz2 are 25% each
course_type=“project”
Milestone1 - Milestone4 are 20% each IndividualAssignment1 - IndividualAssignment4 are 5% each
Inputs 1. course_type: string Must be exactly: “quiz” or “project”
grades: dictionary A dictionary of completed components → grade earned (0–100). Example: {“lab1”: 80, “quiz1”: 70}
Dictionary rules: - keys must be strings (component names) - values must be numbers (int/float) - grades must be between 0 and 100
Output The function returns a dict of remaining components mapped to the minimum grade needed on each (same value for all remaining components).
Example output: {“lab3”: 52.5, “lab4”: 52.5, “quiz2”: 52.5}
Usage examples:
Quiz based course
Input:
from ubc_mds_helper.grade import needed_to_passneeded_to_pass("quiz", {"lab1": 80, "lab2": 70, "quiz1": 60})
{'lab3': 52.5, 'lab4': 52.5, 'quiz2': 52.5}
Project based course
from ubc_mds_helper.grade import needed_to_passneeded_to_pass("project", {"Milestone1": 80})
The visualize_program_progress() function calculates how far along you are in the MDS program and saves a bar chart containing your progress to the img/ folder. Also returns: - capstone_progress_percentage: progress from program start to the capstone start (0 to 1) - completion_percentage: progress from program start to the total program end (0 to 1)
from ubc_mds_helper.progress import visualize_program_progressfrom ubc_mds_helper.config import PROGRAM_CONFIG_2025_2026# pull the key dates from the config file program_start = PROGRAM_CONFIG_2025_2026["program_start"]capstone_start = PROGRAM_CONFIG_2025_2026["capstone"]["start"]program_end = PROGRAM_CONFIG_2025_2026["program_end"]# Example 1: If the current date = program start date: Progress equals 0.print("\nExample 1: current_date = program_start")capstone_completion_pct, program_completion_pct = visualize_program_progress(current_date = program_start)print("Capstone progress:", capstone_completion_pct) # Expected: 0print("Program progress:", program_completion_pct) # Expected: 0# Example 2: If the current date = capstone start date: Capstone progress should equal 1 and program end progress should be less than 1.print("\nExample 2: current_date = capstone_start")capstone_completion_pct, program_completion_pct = visualize_program_progress(current_date = capstone_start)print("Capstone progress:", capstone_completion_pct) # Expected: 1print("Program progress:", program_completion_pct) # Expected: <FLOAT> < 1# Example 3: Passing in date strings (works the same as datetime.date)print("\nExample 3: passing date strings")capstone_completion_pct, program_completion_pct = visualize_program_progress( current_date ="January 1, 2026", program_start_date ="August 29, 2025", program_end_date ="June 30, 2026", capstone_start_date ="April 24, 2026")print("Capstone progress:", capstone_completion_pct) # Expected: <FLOAT> < 1print("Program progress:", program_completion_pct) # Expected: <FLOAT> < 1
Example 1: current_date = program_start
Capstone progress: 0
Program progress: 0
Example 2: current_date = capstone_start
Capstone progress: 1
Program progress: 0.7901639344262295
Example 3: passing date strings
Capstone progress: 0.5252100840336135
Program progress: 0.4098360655737705
Keep in mind, the function also saves the progress bar chart to the img/ folder with the timestamp of the current date appended.