Team Ai
Apppublic

TangibleAI/mathtext-fastapi

sourceHugging Faceagpl-3.0updated 3y agoView on Hugging Face
1likes
curriculum_mapper.py184 linesDownload Raw Back to mathtext_fastapi
1import numpy as np2import pandas as pd3import re4 5from pathlib import Path6 7 8def read_and_preprocess_spreadsheet(file_name):9    """ Creates a pandas dataframe from the curriculum overview spreadsheet """10    DATA_DIR = Path(__file__).parent.parent / "mathtext_fastapi" / "data" / file_name11    script_df = pd.read_excel(DATA_DIR, engine='openpyxl')12    # Ensures the grade level columns are integers instead of floats13    script_df.columns = script_df.columns[:2].tolist() + script_df.columns[2:11].astype(int).astype(str).tolist() + script_df.columns[11:].tolist()14    script_df.fillna('', inplace=True)15    return script_df16 17 18def extract_skill_code(skill):19    """ Looks within a curricular skill description for its descriptive code20 21    Input22    - skill: str - a brief description of a curricular skill23 24    >>> extract_skill_code('A3.3.4 - Solve inequalities')25    'A3.3.4'26    >>> extract_skill_code('A3.3.2 - Graph linear equations, and identify the x- and y-intercepts or the slope of a line')27    'A3.3.2'28    """29    pattern = r'[A-Z][0-9]\.\d+\.\d+'30    result = re.search(pattern, skill)31    return result.group()32 33 34def build_horizontal_transitions(script_df):35    """ Build a list of transitional relationships within a curricular skill36 37    Inputs38    - script_df: pandas dataframe - an overview of the curriculum skills by grade level39 40    Output41    - horizontal_transitions: array of arrays - transition data with label, from state, and to state42 43    >>> script_df = read_and_preprocess_spreadsheet('curriculum_framework_for_tests.xlsx')44    >>> build_horizontal_transitions(script_df)45    [['right', 'N1.1.1_G1', 'N1.1.1_G2'], ['right', 'N1.1.1_G2', 'N1.1.1_G3'], ['right', 'N1.1.1_G3', 'N1.1.1_G4'], ['right', 'N1.1.1_G4', 'N1.1.1_G5'], ['right', 'N1.1.1_G5', 'N1.1.1_G6'], ['left', 'N1.1.1_G6', 'N1.1.1_G5'], ['left', 'N1.1.1_G5', 'N1.1.1_G4'], ['left', 'N1.1.1_G4', 'N1.1.1_G3'], ['left', 'N1.1.1_G3', 'N1.1.1_G2'], ['left', 'N1.1.1_G2', 'N1.1.1_G1'], ['right', 'N1.1.2_G1', 'N1.1.2_G2'], ['right', 'N1.1.2_G2', 'N1.1.2_G3'], ['right', 'N1.1.2_G3', 'N1.1.2_G4'], ['right', 'N1.1.2_G4', 'N1.1.2_G5'], ['right', 'N1.1.2_G5', 'N1.1.2_G6'], ['left', 'N1.1.2_G6', 'N1.1.2_G5'], ['left', 'N1.1.2_G5', 'N1.1.2_G4'], ['left', 'N1.1.2_G4', 'N1.1.2_G3'], ['left', 'N1.1.2_G3', 'N1.1.2_G2'], ['left', 'N1.1.2_G2', 'N1.1.2_G1']]46    """47    horizontal_transitions = []48    for index, row in script_df.iterrows():     49        skill_code = extract_skill_code(row['Knowledge or Skill'])50 51        rightward_matches = []52        for i in range(9):53            # Grade column54            current_grade = i+155            if row[current_grade].lower().strip() == 'x':56                rightward_matches.append(i)57            58        for match in rightward_matches:59            if rightward_matches[-1] != match:60                horizontal_transitions.append([61                    "right",62                    f"{skill_code}_G{match}",63                    f"{skill_code}_G{match+1}"64                ])65 66        leftward_matches = []67        for i in reversed(range(9)):68            current_grade = i69            if row[current_grade].lower().strip() == 'x':70                leftward_matches.append(i)71 72        for match in leftward_matches:73            if leftward_matches[0] != match:74                horizontal_transitions.append([75                    "left",76                    f"{skill_code}_G{match}",77                    f"{skill_code}_G{match-1}"78                ])79 80    return horizontal_transitions81 82 83def gather_all_vertical_matches(script_df):84    """ Build a list of transitional relationships within a grade level across skills85 86    Inputs87    - script_df: pandas dataframe - an overview of the curriculum skills by grade level88 89    Output90    - all_matches: array of arrays - represents skills at each grade level91 92    >>> script_df = read_and_preprocess_spreadsheet('curriculum_framework_for_tests.xlsx')93    >>> gather_all_vertical_matches(script_df)94    [['N1.1.1', '1'], ['N1.1.2', '1'], ['N1.1.1', '2'], ['N1.1.2', '2'], ['N1.1.1', '3'], ['N1.1.2', '3'], ['N1.1.1', '4'], ['N1.1.2', '4'], ['N1.1.1', '5'], ['N1.1.2', '5'], ['N1.1.1', '6'], ['N1.1.2', '6']]95    """96    all_matches = []97    columns = ['1', '2', '3', '4', '5', '6', '7', '8', '9']98 99    for column in columns:100        for index, value in script_df[column].iteritems():101            row_num = index + 1102            if value == 'x':103                # Extract skill code104                skill_code = extract_skill_code(105                    script_df['Knowledge or Skill'][row_num-1]106                )107 108                all_matches.append([skill_code, column])109    return all_matches110 111 112def build_vertical_transitions(script_df):113    """ Build a list of transitional relationships within a grade level across skills114 115    Inputs116    - script_df: pandas dataframe - an overview of the curriculum skills by grade level117 118    Output119    - vertical_transitions: array of arrays - transition data with label, from state, and to state120 121    >>> script_df = read_and_preprocess_spreadsheet('curriculum_framework_for_tests.xlsx')122    >>> build_vertical_transitions(script_df)123    [['down', 'N1.1.1_G1', 'N1.1.2_G1'], ['down', 'N1.1.2_G1', 'N1.1.1_G1'], ['down', 'N1.1.1_G2', 'N1.1.2_G2'], ['down', 'N1.1.2_G2', 'N1.1.1_G2'], ['down', 'N1.1.1_G3', 'N1.1.2_G3'], ['down', 'N1.1.2_G3', 'N1.1.1_G3'], ['down', 'N1.1.1_G4', 'N1.1.2_G4'], ['down', 'N1.1.2_G4', 'N1.1.1_G4'], ['down', 'N1.1.1_G5', 'N1.1.2_G5'], ['down', 'N1.1.2_G5', 'N1.1.1_G5'], ['down', 'N1.1.1_G6', 'N1.1.2_G6'], ['up', 'N1.1.2_G6', 'N1.1.1_G6'], ['up', 'N1.1.1_G6', 'N1.1.2_G6'], ['up', 'N1.1.2_G5', 'N1.1.1_G5'], ['up', 'N1.1.1_G5', 'N1.1.2_G5'], ['up', 'N1.1.2_G4', 'N1.1.1_G4'], ['up', 'N1.1.1_G4', 'N1.1.2_G4'], ['up', 'N1.1.2_G3', 'N1.1.1_G3'], ['up', 'N1.1.1_G3', 'N1.1.2_G3'], ['up', 'N1.1.2_G2', 'N1.1.1_G2'], ['up', 'N1.1.1_G2', 'N1.1.2_G2'], ['up', 'N1.1.2_G1', 'N1.1.1_G1']]124    """125    vertical_transitions = []126 127    all_matches = gather_all_vertical_matches(script_df)128 129    # Downward130    for index, match in enumerate(all_matches):131        skill = match[0]132        row_num = match[1]133        if all_matches[-1] != match:134            vertical_transitions.append([135                "down",136                f"{skill}_G{row_num}",137                f"{all_matches[index+1][0]}_G{row_num}"138            ])139 140    # Upward141    for index, match in reversed(list(enumerate(all_matches))):142        skill = match[0]143        row_num = match[1]144        if all_matches[0] != match:145            vertical_transitions.append([146                "up",147                f"{skill}_G{row_num}",148                f"{all_matches[index-1][0]}_G{row_num}"149            ])150    151    return vertical_transitions152 153 154def build_all_states(all_transitions):155    """ Creates an array with all state labels for the curriculum156 157    Input158    - all_transitions: list of lists - all possible up, down, left, or right transitions in curriculum159 160    Output161    - all_states: list - a collection of state labels (skill code and grade number)162    163    >>> all_transitions = [['right', 'N1.1.1_G1', 'N1.1.1_G2'], ['right', 'N1.1.1_G2', 'N1.1.1_G3'], ['right', 'N1.1.1_G3', 'N1.1.1_G4'], ['right', 'N1.1.1_G4', 'N1.1.1_G5'], ['right', 'N1.1.1_G5', 'N1.1.1_G6'], ['left', 'N1.1.1_G6', 'N1.1.1_G5'], ['left', 'N1.1.1_G5', 'N1.1.1_G4'], ['left', 'N1.1.1_G4', 'N1.1.1_G3'], ['left', 'N1.1.1_G3', 'N1.1.1_G2'], ['left', 'N1.1.1_G2', 'N1.1.1_G1'], ['right', 'N1.1.2_G1', 'N1.1.2_G2'], ['right', 'N1.1.2_G2', 'N1.1.2_G3'], ['right', 'N1.1.2_G3', 'N1.1.2_G4'], ['right', 'N1.1.2_G4', 'N1.1.2_G5'], ['right', 'N1.1.2_G5', 'N1.1.2_G6'], ['left', 'N1.1.2_G6', 'N1.1.2_G5'], ['left', 'N1.1.2_G5', 'N1.1.2_G4'], ['left', 'N1.1.2_G4', 'N1.1.2_G3'], ['left', 'N1.1.2_G3', 'N1.1.2_G2'], ['left', 'N1.1.2_G2', 'N1.1.2_G1'], ['down', 'N1.1.1_G1', 'N1.1.2_G1'], ['down', 'N1.1.2_G1', 'N1.1.1_G1'], ['down', 'N1.1.1_G2', 'N1.1.2_G2'], ['down', 'N1.1.2_G2', 'N1.1.1_G2'], ['down', 'N1.1.1_G3', 'N1.1.2_G3'], ['down', 'N1.1.2_G3', 'N1.1.1_G3'], ['down', 'N1.1.1_G4', 'N1.1.2_G4'], ['down', 'N1.1.2_G4', 'N1.1.1_G4'], ['down', 'N1.1.1_G5', 'N1.1.2_G5'], ['down', 'N1.1.2_G5', 'N1.1.1_G5'], ['down', 'N1.1.1_G6', 'N1.1.2_G6'], ['up', 'N1.1.2_G6', 'N1.1.1_G6'], ['up', 'N1.1.1_G6', 'N1.1.2_G6'], ['up', 'N1.1.2_G5', 'N1.1.1_G5'], ['up', 'N1.1.1_G5', 'N1.1.2_G5'], ['up', 'N1.1.2_G4', 'N1.1.1_G4'], ['up', 'N1.1.1_G4', 'N1.1.2_G4'], ['up', 'N1.1.2_G3', 'N1.1.1_G3'], ['up', 'N1.1.1_G3', 'N1.1.2_G3'], ['up', 'N1.1.2_G2', 'N1.1.1_G2'], ['up', 'N1.1.1_G2', 'N1.1.2_G2'], ['up', 'N1.1.2_G1', 'N1.1.1_G1']]164    >>> build_all_states(all_transitions)165    ['N1.1.1_G1', 'N1.1.1_G2', 'N1.1.1_G3', 'N1.1.1_G4', 'N1.1.1_G5', 'N1.1.1_G6', 'N1.1.2_G1', 'N1.1.2_G2', 'N1.1.2_G3', 'N1.1.2_G4', 'N1.1.2_G5', 'N1.1.2_G6']166    """167    all_states = []168    for transition in all_transitions:169        for index, state in enumerate(transition):170            if index == 0:171                continue   172            if state not in all_states:173                all_states.append(state)174    return all_states175 176 177def build_curriculum_logic():178    script_df = read_and_preprocess_spreadsheet('Rori_Framework_v1.xlsx')179    horizontal_transitions = build_horizontal_transitions(script_df)180    vertical_transitions = build_vertical_transitions(script_df)181    all_transitions = horizontal_transitions + vertical_transitions182    all_states = build_all_states(all_transitions)183    return all_states, all_transitions184