Пример #1
0
    def update_faculty_fte_chart(dept):

        resp = table.query(
            KeyConditionExpression='PK = :pk AND SK BETWEEN :lower AND :upper',
            ExpressionAttributeValues={
                ':pk': f'DEPT#{dept}',
                ':lower': 'DATA#FACULTY_DATA#2005',
                ':upper': f'DATA#FACULTY_DATA#{int(MAX_FISCAL_YEAR) + 1}$',
            },
            ProjectionExpression='fte, ten_stat',
            ScanIndexForward=True,
        )

        data = resp['Items']

        chart_data = []
        x_axis = make_academic_year_range(0, MAX_YEAR_ID)

        # Categories determine filtering for the y-axis and obtaining a color
        category_names = {
            'Tenured': 'Tenured',
            'NTBOT': 'NTBOT',
            'NTBOT-professor-term': 'Term Asst. Prof',
            'Lecturers': 'Lecturers',
            'Other Full-Time': 'Other Full-Time',
            'Adjunct': 'Adjunct',
        }

        for cat in category_names.keys():

            y_axis = [
                item.get('fte') for item in data if item.get('ten_stat') == cat
            ]

            chart_data.append(
                go.Bar(
                    name=category_names.get(cat),
                    x=x_axis,
                    y=y_axis,
                    text=[f' {round(float(i))} ' for i in y_axis
                          ],  # pad with spaces to prevent labels from rotating
                    textposition='inside',
                    hovertext=[f'{cat}: {i}' for i in y_axis],
                    hoverinfo='text',
                    marker=dict(
                        color=faculty_colors.get(cat),
                        line=dict(color='floralwhite', width=1),
                    )))

        chart_layout = go.Layout(
            barmode='stack',
            xaxis=axes(),
            yaxis=axes(title='FTE for Faculty/Person Count for Adjuncts', ),
            legend={'traceorder': 'normal'},
            margin=margin(l=55),
        )

        return {'data': chart_data, 'layout': chart_layout}
Пример #2
0
    def update_student_ug_chart(dept):

        resp = table.query(
            KeyConditionExpression='PK = :pk AND SK BETWEEN :lower AND :upper',
            ExpressionAttributeValues={
                ':pk': f'DEPT#{dept}',
                ':lower': 'DATA#STUDENTS#UG#2005',
                ':upper': f'DATA#STUDENTS#UG#{int(MAX_FISCAL_YEAR) + 1}$',
            },
            ScanIndexForward=True,
        )

        data = resp['Items']

        chart_data = []
        x_axis = make_academic_year_range(0, MAX_YEAR_ID)

        # Categories determine filtering for the y-axis and obtaining a color
        categories = {
            'maj': 'Majors',
            'conc': 'Concentrations',
            'intdmaj': 'Interdepartmental Majors',
            'min': 'Minors'
        }

        for cat in categories.keys():

            y_axis = [item.get(cat) for item in data]

            chart_data.append(
                go.Bar(
                    name=categories.get(cat),
                    x=x_axis,
                    y=y_axis,
                    text=[i if len(i) > 1 else f' {i} ' for i in y_axis
                          ],  # pad single-digit numbers to prevent rotation
                    textposition='inside',
                    hovertext=[f'{categories.get(cat)}: {i}' for i in y_axis],
                    hoverinfo='text',
                    marker=dict(
                        color=students_ug_colors.get(cat),
                        line=dict(color='floralwhite', width=1),
                    )))

        chart_layout = go.Layout(
            barmode='stack',
            xaxis=axes(),
            yaxis=axes(title='Number of Students', ),
            legend={'traceorder': 'normal'},
            margin=margin(l=55),
        )

        return {'data': chart_data, 'layout': chart_layout}
Пример #3
0
    def update_classes_bar_chart(dept):

        # Use ExpressionAttributeNames because 'count' is a restricted keyword for ProjectionExpression
        resp = table.query(
            KeyConditionExpression='PK = :pk AND SK BETWEEN :lower AND :upper',
            ExpressionAttributeValues={
                ':pk': f'DEPT#{dept}',
                ':lower': 'DATA#AGG#CLASSES#2008',
                ':upper': f'DATA#AGG#CLASSES#{int(MAX_FISCAL_YEAR) + 1}$',
            },
            ProjectionExpression='#c, ten_stat',
            ExpressionAttributeNames={'#c': 'count'},
            ScanIndexForward=True,
        )

        data = resp['Items']

        chart_data = []
        x_axis = make_academic_year_range(3, MAX_YEAR_ID)

        for data_cat, chart_cat in tenure_categories.items():

            y_axis = [
                item.get('count') for item in data
                if item.get('ten_stat') == data_cat
            ]

            chart_data.append(
                go.Bar(name=chart_cat,
                       x=x_axis,
                       y=y_axis,
                       text=[f'{round(float(i)):,}' for i in y_axis],
                       textposition='inside',
                       hovertext=[
                           f'{chart_cat}: {round(float(i)):,}' for i in y_axis
                       ],
                       hoverinfo='text',
                       marker=dict(
                           color=classes_colors.get(data_cat),
                           line=dict(color='floralwhite', width=1),
                       )))

        chart_layout = go.Layout(
            barmode='stack',
            xaxis=axes(),
            yaxis=axes(title='Number of Classes', ),
            legend={'traceorder': 'normal'},
            margin=margin(l=70),
        )

        return {'data': chart_data, 'layout': chart_layout}
Пример #4
0
    def update_classes_tree_chart(dept, slider_year):

        chart_year = YEARS.get(slider_year).academic
        data_year = YEARS.get(slider_year).fiscal

        resp = table.query(
            KeyConditionExpression='PK = :pk AND SK BETWEEN :lower AND :upper',
            ExpressionAttributeValues={
                ':pk': f'DEPT#{dept}',
                ':lower': f'DATA#AGG#CLASSES#{data_year}',
                ':upper': f'DATA#AGG#CLASSES#{int(data_year) + 1}$',
            },
            ProjectionExpression='#c, ten_stat',
            ExpressionAttributeNames={'#c': 'count'},
            ScanIndexForward=True,
        )

        data = resp['Items']

        labels, parents, values = [], [], []
        for data_cat, chart_cat in tenure_categories.items():
            labels.append(chart_cat)
            parents.append(chart_year)
            value = [
                int(float(item.get('count'))) for item in data
                if item.get('ten_stat') == data_cat
            ]
            values.append(value[0])

        chart_data = []
        chart_data.append(
            go.Treemap(
                labels=labels,
                parents=parents,
                values=values,
                texttemplate='%{label}<br>%{percentRoot} (%{value})',
            ))

        chart_layout = go.Layout(margin=margin(l=70), )

        return {'data': chart_data, 'layout': chart_layout}
Пример #5
0
    def update_student_phd_chart(dept):

        resp = table.query(
            KeyConditionExpression='PK = :pk AND SK BETWEEN :lower AND :upper',
            ExpressionAttributeValues={
                ':pk': f'DEPT#{dept}',
                ':lower': 'DATA#STUDENTS#PHD#2005',
                ':upper': f'DATA#STUDENTS#PHD#{int(MAX_FISCAL_YEAR) + 1}$',
            },
            ScanIndexForward=True,
        )

        data = resp['Items']

        if is_blank_grad(data):
            return [], {'display': 'none'}

        chart_data = []
        x_axis = make_academic_year_range(0, MAX_YEAR_ID)

        # Categories determine filtering for the y-axis and obtaining a color
        categories = {
            'cohort': 'Entering Cohort<br>(starting 2009/10)',
            'existing': 'Existing Students',
        }

        for cat in categories.keys():

            y_axis = [item.get(cat) for item in data]

            chart_data.append(
                go.Bar(
                    name=categories.get(cat),
                    x=x_axis,
                    y=y_axis,
                    text=[i if len(i) > 1 else f' {i} ' for i in y_axis
                          ],  # pad single-digit numbers to prevent rotation
                    textposition='inside',
                    hovertext=[f'{categories.get(cat)}: {i}' for i in y_axis],
                    hoverinfo='text',
                    marker=dict(
                        color=students_grad_colors.get(cat),
                        line=dict(color='floralwhite', width=1),
                    )))

        if dept not in ['AS', 'HUM', 'NS', 'SS']:
            # Do not add selectivity/yield for aggregates
            for cat in ('selectivity', 'yield'):

                y_axis_selectivity = [
                    round(float(item.get(cat)) *
                          100) if item.get(cat) is not None else None
                    for item in data
                ]
                hover_labels = [
                    f'{i}%' if i is not None else None
                    for i in y_axis_selectivity
                ]
                text_labels = make_text_labels(hover_labels)

                chart_data.append(
                    go.Scatter(
                        name=f'{cat.title()}',
                        x=x_axis,
                        y=y_axis_selectivity,
                        mode='lines+markers+text',
                        text=text_labels,
                        textposition='top center',
                        textfont=dict(color=students_grad_colors.get(cat), ),
                        hovertext=hover_labels,
                        hoverinfo='text',
                        marker=dict(color=students_grad_colors.get(cat), ),
                        yaxis='y2'))

            chart_layout = go.Layout(
                barmode='stack',
                xaxis=axes(),
                yaxis=axes(title='Number of Students', ),
                yaxis2=axes(
                    title='% Selectivity or Yield',
                    overlaying='y',
                    side='right',
                    rangemode='tozero',
                    showgrid=False,
                ),
                legend={
                    'traceorder': 'normal',
                    'x': 1.05
                },  # By default x is 1.02 which will make it overlap with the 2nd y-axis
                margin=margin(l=55),
            )

        else:

            chart_layout = go.Layout(
                barmode='stack',
                xaxis=axes(),
                yaxis=axes(title='Number of Students', ),
                legend={
                    'traceorder': 'normal',
                    'x': 1.05
                },  # By default x is 1.02 which will make it overlap with the 2nd y-axis
                margin=margin(l=55),
            )

        return {
            'data': chart_data,
            'layout': chart_layout
        }, {
            'display': 'inline'
        }
Пример #6
0
    def update_student_sps_chart(dept):

        resp = table.query(
            KeyConditionExpression='PK = :pk AND SK BETWEEN :lower AND :upper',
            ExpressionAttributeValues={
                ':pk': f'DEPT#{dept}',
                ':lower': 'DATA#STUDENTS#SPS#2005',
                ':upper': f'DATA#STUDENTS#SPS#{int(MAX_FISCAL_YEAR) + 1}$',
            },
            ScanIndexForward=True,
        )

        data = resp['Items']

        if is_blank_grad(data):
            return [], {'display': 'none'}

        chart_data = []
        x_axis = make_academic_year_range(0, MAX_YEAR_ID)

        # Categories determine filtering for the y-axis and obtaining a color
        categories = {
            'cohort': 'Entering Cohort<br>(starting 2009/10)',
            'existing': 'Existing Students',
        }

        for cat in categories.keys():

            y_axis = [item.get(cat) for item in data]

            chart_data.append(
                go.Bar(
                    name=categories.get(cat),
                    x=x_axis,
                    y=y_axis,
                    text=[i if len(i) > 1 else f' {i} ' for i in y_axis
                          ],  # pad single-digit numbers to prevent rotation
                    textposition='inside',
                    hovertext=[f'{categories.get(cat)}: {i}' for i in y_axis],
                    hoverinfo='text',
                    marker=dict(
                        color=students_grad_colors.get(cat),
                        line=dict(color='floralwhite', width=1),
                    )))

        chart_layout = go.Layout(
            barmode='stack',
            xaxis=axes(),
            yaxis=axes(title='Number of Students', ),
            legend={
                'traceorder': 'normal',
                'x': 1.05
            },  # By default x is 1.02 which will make it overlap with the 2nd y-axis
            margin=margin(l=55),
        )

        return {
            'data': chart_data,
            'layout': chart_layout
        }, {
            'display': 'inline'
        }
Пример #7
0
    def update_faculty_demo_chart(dept):

        resp = table.query(
            KeyConditionExpression='PK = :pk AND SK BETWEEN :lower AND :upper',
            ExpressionAttributeValues={
                ':pk': f'DEPT#{dept}',
                ':lower': 'DATA#FACULTY_DATA#2005',
                ':upper': f'DATA#FACULTY_DATA#{int(MAX_FISCAL_YEAR) + 1}$',
            },
            FilterExpression=Attr('ten_stat').eq('Tenured')
            | Attr('ten_stat').eq('NTBOT'),
            ProjectionExpression='fte, ten_stat, percent_fem, percent_urm',
            ScanIndexForward=True,
        )

        data = resp['Items']
        chart_data = []
        x_axis = make_academic_year_range(0, MAX_YEAR_ID)

        # Construct charts without a loop to preserve y values for further calculation

        y_axis_bar_t = [
            item.get('fte') for item in data
            if item.get('ten_stat') == 'Tenured'
        ]

        chart_data.append(
            go.Bar(
                name='Tenured',
                x=x_axis,
                y=y_axis_bar_t,
                text=[f' {round(float(i))} ' for i in y_axis_bar_t
                      ],  # pad with spaces to prevent labels from rotating
                textposition='inside',
                hovertext=[f'Tenured: {i}' for i in y_axis_bar_t],
                hoverinfo='text',
                marker=dict(
                    color=faculty_colors.get('Tenured'),
                    line=dict(color='floralwhite', width=1),
                )))

        y_axis_bar_nt = [
            item.get('fte') for item in data if item.get('ten_stat') == 'NTBOT'
        ]

        chart_data.append(
            go.Bar(
                name='NTBOT',
                x=x_axis,
                y=y_axis_bar_nt,
                text=[f' {round(float(i))} ' for i in y_axis_bar_nt
                      ],  # pad with spaces to prevent labels from rotating
                textposition='inside',
                hovertext=[f'NTBOT: {i}' for i in y_axis_bar_nt],
                hoverinfo='text',
                marker=dict(
                    color=faculty_colors.get('NTBOT'),
                    line=dict(color='floralwhite', width=1),
                )))

        # LINE PLOTS

        y_axis_line_t = [
            round(float(item.get('percent_fem')) *
                  100) if item.get('percent_fem') is not None else None
            for item in data if item.get('ten_stat') == 'Tenured'
        ]
        hover_labels = [
            f'{i}%' if i is not None else None for i in y_axis_line_t
        ]
        text_labels = make_text_labels(hover_labels)

        chart_data.append(
            go.Scatter(name='% Tenured Female',
                       x=x_axis,
                       y=y_axis_line_t,
                       mode='lines+markers+text',
                       text=text_labels,
                       textposition='top center',
                       textfont=dict(color=colors.get('orange2'), ),
                       hovertext=hover_labels,
                       hoverinfo='text',
                       marker=dict(color=colors.get('orange2'), ),
                       yaxis='y2'))

        y_axis_line_nt = [
            round(float(item.get('percent_fem')) *
                  100) if item.get('percent_fem') is not None else None
            for item in data if item.get('ten_stat') == 'NTBOT'
        ]
        hover_labels = [
            f'{i}%' if i is not None else None for i in y_axis_line_nt
        ]
        text_labels = make_text_labels(hover_labels)

        chart_data.append(
            go.Scatter(name='% NTBOT Female',
                       x=x_axis,
                       y=y_axis_line_nt,
                       mode='lines+markers+text',
                       text=text_labels,
                       textposition='top center',
                       textfont=dict(color=colors.get('red1'), ),
                       hovertext=hover_labels,
                       hoverinfo='text',
                       marker=dict(color=colors.get('red1'), ),
                       yaxis='y2'))

        # URM line calculation
        # (Tenured FTE * Tenured % URM + NTBOT FTE * NTBOT% URM) / (Tenured FTE + NTBOT FTE)

        urm_t = [
            float(item.get('percent_urm'))
            if item.get('percent_urm') is not None else None for item in data
            if item.get('ten_stat') == 'Tenured'
        ]

        urm_nt = [
            float(item.get('percent_urm'))
            if item.get('percent_urm') is not None else None for item in data
            if item.get('ten_stat') == 'NTBOT'
        ]

        y_axis_line_urm = []

        for t_fte, nt_fte, t_urm, nt_urm in zip(y_axis_bar_t, y_axis_bar_nt,
                                                urm_t, urm_nt):

            calc = None
            if t_urm is not None and nt_urm is not None:
                calc = (float(t_fte) * t_urm + float(nt_fte) * nt_urm) / (
                    float(t_fte) + float(nt_fte))
            elif t_urm is not None and nt_urm is None:
                calc = (float(t_fte) * t_urm +
                        float(nt_fte) * 0) / (float(t_fte) + float(nt_fte))
            elif nt_urm is not None and t_urm is None:
                calc = (float(t_fte) * 0 + float(nt_fte) * nt_urm) / (
                    float(t_fte) + float(nt_fte))

            if calc is None:
                y_axis_line_urm.append(None)
            else:
                y_axis_line_urm.append(round(calc * 100))

        hover_labels = [
            f'{i}%' if i is not None else None for i in y_axis_line_urm
        ]
        text_labels = make_text_labels(hover_labels)

        chart_data.append(
            go.Scatter(name='% NTBOT and Tenured URM',
                       x=x_axis,
                       y=y_axis_line_urm,
                       mode='lines+markers+text',
                       text=text_labels,
                       textposition='top center',
                       textfont=dict(color=colors.get('teal1'), ),
                       hovertext=hover_labels,
                       hoverinfo='text',
                       marker=dict(color=colors.get('teal1'), ),
                       yaxis='y2'))

        chart_layout = go.Layout(
            barmode='stack',
            xaxis=axes(),
            yaxis=axes(title='FTE', ),
            yaxis2=axes(
                title='% FTE',
                overlaying='y',
                side='right',
                rangemode='tozero',
                showgrid=False,
            ),
            legend={
                'traceorder': 'normal',
                'x': 1.05
            },  # By default x is 1.02 which will make it overlap with the 2nd y-axis
            margin=margin(),
        )

        return {'data': chart_data, 'layout': chart_layout}