Example #1
0
def render(element_html, data):
    element = lxml.html.fragment_fromstring(element_html)

    # Get the number of digits to output
    digits = pl.get_integer_attrib(element, 'digits', 2)
    # Get the presentation type
    presentation_type = pl.get_string_attrib(element, 'presentation-type', 'f')

    var_name = pl.get_string_attrib(element, 'params-name')
    # Get value of variable, raising exception if variable does not exist
    var_data = data['params'].get(var_name, None)

    if var_data is None:
        raise Exception('No value in data["params"] for variable %s in pl-matrix-latex element' % var_name)

    # If the variable is in a format generated by pl.to_json, convert it
    # back to a standard type (otherwise, do nothing)
    var_data = pl.from_json(var_data)

    if not np.isscalar(var_data):
        var_data = np.array(var_data)
        # Check if numpy array type is numeric (integer, float or complex)
        if np.issubdtype(var_data.dtype, np.number):
            # Check shape of variable
            if var_data.ndim != 2:
                raise Exception('Value in data["params"] for variable %s in pl-matrix-latex element must be 2D array or scalar' % var_name)
        else:
            raise Exception('Value in data["params"] for variable %s in pl-matrix-latex element must be numeric' % var_name)

    # Create string for latex matrix format
    html = pl.latex_from_2darray(var_data, presentation_type=presentation_type, digits=digits)

    return html
Example #2
0
def render(element_html, data):
    element = lxml.html.fragment_fromstring(element_html)
    # get the name of the element, in this case, the name of the array
    name = pl.get_string_attrib(element, 'answers-name')
    label = pl.get_string_attrib(element, 'label', None)
    allow_partial_credit = pl.get_boolean_attrib(element,
                                                 'allow-partial-credit', False)
    allow_feedback = pl.get_boolean_attrib(element, 'allow-feedback',
                                           allow_partial_credit)

    if data['panel'] == 'question':
        editable = data['editable']

        # Get true answer
        a_tru = pl.from_json(data['correct_answers'].get(name, None))
        if a_tru is None:
            raise Exception(
                'No value in data["correct_answers"] for variable %s in pl-matrix-component-input element'
                % name)
        else:
            if np.isscalar(a_tru):
                raise Exception(
                    'Value in data["correct_answers"] for variable %s in pl-matrix-component-input element cannot be a scalar.'
                    % name)
            else:
                a_tru = np.array(a_tru)

        if a_tru.ndim != 2:
            raise Exception(
                'Value in data["correct_answers"] for variable %s in pl-matrix-component-input element must be a 2D array.'
                % name)
        else:
            m, n = np.shape(a_tru)

        input_array = createTableForHTMLDisplay(m, n, name, label, data,
                                                'input')

        # Get comparison parameters and info strings
        comparison = pl.get_string_attrib(element, 'comparison', 'relabs')
        if comparison == 'relabs':
            rtol = pl.get_float_attrib(element, 'rtol', 1e-2)
            atol = pl.get_float_attrib(element, 'atol', 1e-8)
            if (rtol < 0):
                raise ValueError(
                    'Attribute rtol = {:g} must be non-negative'.format(rtol))
            if (atol < 0):
                raise ValueError(
                    'Attribute atol = {:g} must be non-negative'.format(atol))
            info_params = {
                'format': True,
                'relabs': True,
                'rtol': '{:g}'.format(rtol),
                'atol': '{:g}'.format(atol)
            }
        elif comparison == 'sigfig':
            digits = pl.get_integer_attrib(element, 'digits', 2)
            if (digits < 0):
                raise ValueError(
                    'Attribute digits = {:d} must be non-negative'.format(
                        digits))
            info_params = {
                'format': True,
                'sigfig': True,
                'digits': '{:d}'.format(digits),
                'comparison_eps': 0.51 * (10**-(digits - 1))
            }
        elif comparison == 'decdig':
            digits = pl.get_integer_attrib(element, 'digits', 2)
            if (digits < 0):
                raise ValueError(
                    'Attribute digits = {:d} must be non-negative'.format(
                        digits))
            info_params = {
                'format': True,
                'decdig': True,
                'digits': '{:d}'.format(digits),
                'comparison_eps': 0.51 * (10**-(digits - 0))
            }
        else:
            raise ValueError(
                'method of comparison "%s" is not valid (must be "relabs", "sigfig", or "decdig")'
                % comparison)

        with open('pl-matrix-component-input.mustache', 'r',
                  encoding='utf-8') as f:
            info = chevron.render(f, info_params).strip()
        with open('pl-matrix-component-input.mustache', 'r',
                  encoding='utf-8') as f:
            info_params.pop('format', None)
            info_params['shortformat'] = True
            shortinfo = chevron.render(f, info_params).strip()

        html_params = {
            'question': True,
            'name': name,
            'label': label,
            'editable': editable,
            'info': info,
            'shortinfo': shortinfo,
            'input_array': input_array,
            'inline': True,
            'uuid': pl.get_uuid()
        }

        partial_score = data['partial_scores'].get(name, {'score': None})
        score = partial_score.get('score', None)
        if score is not None:
            try:
                score = float(score)
                if score >= 1:
                    html_params['correct'] = True
                elif score > 0:
                    html_params['partial'] = math.floor(score * 100)
                else:
                    html_params['incorrect'] = True
            except Exception:
                raise ValueError('invalid score' + score)

        with open('pl-matrix-component-input.mustache', 'r',
                  encoding='utf-8') as f:
            html = chevron.render(f, html_params).strip()

    elif data['panel'] == 'submission':

        parse_error = data['format_errors'].get(name, None)
        html_params = {
            'submission': True,
            'label': label,
            'parse_error': parse_error,
            'uuid': pl.get_uuid()
        }

        a_tru = pl.from_json(data['correct_answers'].get(name, None))
        m, n = np.shape(a_tru)

        partial_score = data['partial_scores'].get(name, {'score': None})
        score = partial_score.get('score', None)
        if score is not None:
            try:
                score = float(score)
                if score >= 1:
                    html_params['correct'] = True
                elif score > 0:
                    html_params['partial'] = math.floor(score * 100)
                else:
                    html_params['incorrect'] = True
            except Exception:
                raise ValueError('invalid score' + score)

        if parse_error is None:
            # Get submitted answer, raising an exception if it does not exist
            a_sub = data['submitted_answers'].get(name, None)
            if a_sub is None:
                raise Exception('submitted answer is None')
            # If answer is in a format generated by pl.to_json, convert it back to a standard type (otherwise, do nothing)
            a_sub = pl.from_json(a_sub)
            # Wrap answer in an ndarray (if it's already one, this does nothing)
            a_sub = np.array(a_sub)
            # Format submitted answer as a latex string
            sub_latex = '$' + pl.latex_from_2darray(
                a_sub, presentation_type='g', digits=12) + '$'
            # When allowing feedback, display submitted answers using html table
            sub_html_table = createTableForHTMLDisplay(m, n, name, label, data,
                                                       'output-feedback')
            if allow_feedback and score is not None:
                if score < 1:
                    html_params['a_sub_feedback'] = sub_html_table
                else:
                    html_params['a_sub'] = sub_latex
            else:
                html_params['a_sub'] = sub_latex
        else:
            # create html table to show submitted answer when there is an invalid format
            html_params['raw_submitted_answer'] = createTableForHTMLDisplay(
                m, n, name, label, data, 'output-invalid')

        with open('pl-matrix-component-input.mustache', 'r',
                  encoding='utf-8') as f:
            html = chevron.render(f, html_params).strip()

    elif data['panel'] == 'answer':

        # Get true answer - do nothing if it does not exist
        a_tru = pl.from_json(data['correct_answers'].get(name, None))
        if a_tru is not None:
            a_tru = np.array(a_tru)

            # Get comparison parameters and create the display data
            comparison = pl.get_string_attrib(element, 'comparison', 'relabs')
            if comparison == 'relabs':
                rtol = pl.get_float_attrib(element, 'rtol', 1e-2)
                atol = pl.get_float_attrib(element, 'atol', 1e-8)
                # FIXME: render correctly with respect to rtol and atol
                latex_data = '$' + pl.latex_from_2darray(
                    a_tru, presentation_type='g', digits=12) + '$'
            elif comparison == 'sigfig':
                digits = pl.get_integer_attrib(element, 'digits', 2)
                latex_data = '$' + pl.latex_from_2darray(
                    a_tru, presentation_type='sigfig', digits=digits) + '$'
            elif comparison == 'decdig':
                digits = pl.get_integer_attrib(element, 'digits', 2)
                latex_data = '$' + pl.latex_from_2darray(
                    a_tru, presentation_type='f', digits=digits) + '$'
            else:
                raise ValueError(
                    'method of comparison "%s" is not valid (must be "relabs", "sigfig", or "decdig")'
                    % comparison)

            html_params = {
                'answer': True,
                'label': label,
                'latex_data': latex_data,
                'uuid': pl.get_uuid()
            }

            with open('pl-matrix-component-input.mustache',
                      'r',
                      encoding='utf-8') as f:
                html = chevron.render(f, html_params).strip()
        else:
            html = ''

    else:
        raise Exception('Invalid panel type: %s' % data['panel'])

    return html
def render(element_html, data):
    element = lxml.html.fragment_fromstring(element_html)
    # get the name of the element, in this case, the name of the array
    name = pl.get_string_attrib(element, 'answers-name')
    label = pl.get_string_attrib(element, 'label', None)
    allow_partial_credit = pl.get_boolean_attrib(element, 'allow-partial-credit', False)
    allow_feedback = pl.get_boolean_attrib(element, 'allow-feedback', allow_partial_credit)

    if data['panel'] == 'question':
        editable = data['editable']

        # Get true answer
        a_tru = pl.from_json(data['correct_answers'].get(name, None))
        if a_tru is None:
            raise Exception('No value in data["correct_answers"] for variable %s in pl-matrix-component-input element' % name)
        else:
            if np.isscalar(a_tru):
                raise Exception('Value in data["correct_answers"] for variable %s in pl-matrix-component-input element cannot be a scalar.' % name)
            else:
                a_tru = np.array(a_tru)

        if a_tru.ndim != 2:
            raise Exception('Value in data["correct_answers"] for variable %s in pl-matrix-component-input element must be a 2D array.' % name)
        else:
            m, n = np.shape(a_tru)

        input_array = createTableForHTMLDisplay(m, n, name, label, data, 'input')

        # Get comparison parameters and info strings
        comparison = pl.get_string_attrib(element, 'comparison', 'relabs')
        if comparison == 'relabs':
            rtol = pl.get_float_attrib(element, 'rtol', 1e-2)
            atol = pl.get_float_attrib(element, 'atol', 1e-8)
            if (rtol < 0):
                raise ValueError('Attribute rtol = {:g} must be non-negative'.format(rtol))
            if (atol < 0):
                raise ValueError('Attribute atol = {:g} must be non-negative'.format(atol))
            info_params = {'format': True, 'relabs': True, 'rtol': '{:g}'.format(rtol), 'atol': '{:g}'.format(atol)}
        elif comparison == 'sigfig':
            digits = pl.get_integer_attrib(element, 'digits', 2)
            if (digits < 0):
                raise ValueError('Attribute digits = {:d} must be non-negative'.format(digits))
            info_params = {'format': True, 'sigfig': True, 'digits': '{:d}'.format(digits), 'comparison_eps': 0.51 * (10**-(digits - 1))}
        elif comparison == 'decdig':
            digits = pl.get_integer_attrib(element, 'digits', 2)
            if (digits < 0):
                raise ValueError('Attribute digits = {:d} must be non-negative'.format(digits))
            info_params = {'format': True, 'decdig': True, 'digits': '{:d}'.format(digits), 'comparison_eps': 0.51 * (10**-(digits - 0))}
        else:
            raise ValueError('method of comparison "%s" is not valid (must be "relabs", "sigfig", or "decdig")' % comparison)

        with open('pl-matrix-component-input.mustache', 'r', encoding='utf-8') as f:
            info = chevron.render(f, info_params).strip()
        with open('pl-matrix-component-input.mustache', 'r', encoding='utf-8') as f:
            info_params.pop('format', None)
            info_params['shortformat'] = True
            shortinfo = chevron.render(f, info_params).strip()

        html_params = {
            'question': True,
            'name': name,
            'label': label,
            'editable': editable,
            'info': info,
            'shortinfo': shortinfo,
            'input_array': input_array,
            'inline': True,
            'uuid': pl.get_uuid()
        }

        partial_score = data['partial_scores'].get(name, {'score': None})
        score = partial_score.get('score', None)
        if score is not None:
            try:
                score = float(score)
                if score >= 1:
                    html_params['correct'] = True
                elif score > 0:
                    html_params['partial'] = math.floor(score * 100)
                else:
                    html_params['incorrect'] = True
            except Exception:
                raise ValueError('invalid score' + score)

        with open('pl-matrix-component-input.mustache', 'r', encoding='utf-8') as f:
            html = chevron.render(f, html_params).strip()

    elif data['panel'] == 'submission':

        parse_error = data['format_errors'].get(name, None)
        html_params = {
            'submission': True,
            'label': label,
            'parse_error': parse_error,
            'uuid': pl.get_uuid()
        }

        a_tru = pl.from_json(data['correct_answers'].get(name, None))
        m, n = np.shape(a_tru)

        partial_score = data['partial_scores'].get(name, {'score': None})
        score = partial_score.get('score', None)
        if score is not None:
            try:
                score = float(score)
                if score >= 1:
                    html_params['correct'] = True
                elif score > 0:
                    html_params['partial'] = math.floor(score * 100)
                else:
                    html_params['incorrect'] = True
            except Exception:
                raise ValueError('invalid score' + score)

        if parse_error is None:
            # Get submitted answer, raising an exception if it does not exist
            a_sub = data['submitted_answers'].get(name, None)
            if a_sub is None:
                raise Exception('submitted answer is None')
            # If answer is in a format generated by pl.to_json, convert it back to a standard type (otherwise, do nothing)
            a_sub = pl.from_json(a_sub)
            # Wrap answer in an ndarray (if it's already one, this does nothing)
            a_sub = np.array(a_sub)
            # Format submitted answer as a latex string
            sub_latex = '$' + pl.latex_from_2darray(a_sub, presentation_type='g', digits=12) + '$'
            # When allowing feedback, display submitted answers using html table
            sub_html_table = createTableForHTMLDisplay(m, n, name, label, data, 'output-feedback')
            if allow_feedback and score is not None:
                if score < 1:
                    html_params['a_sub_feedback'] = sub_html_table
                else:
                    html_params['a_sub'] = sub_latex
            else:
                html_params['a_sub'] = sub_latex
        else:
            # create html table to show submitted answer when there is an invalid format
            html_params['raw_submitted_answer'] = createTableForHTMLDisplay(m, n, name, label, data, 'output-invalid')

        with open('pl-matrix-component-input.mustache', 'r', encoding='utf-8') as f:
            html = chevron.render(f, html_params).strip()

    elif data['panel'] == 'answer':

        # Get true answer - do nothing if it does not exist
        a_tru = pl.from_json(data['correct_answers'].get(name, None))
        if a_tru is not None:
            a_tru = np.array(a_tru)

            # Get comparison parameters and create the display data
            comparison = pl.get_string_attrib(element, 'comparison', 'relabs')
            if comparison == 'relabs':
                rtol = pl.get_float_attrib(element, 'rtol', 1e-2)
                atol = pl.get_float_attrib(element, 'atol', 1e-8)
                # FIXME: render correctly with respect to rtol and atol
                latex_data = '$' + pl.latex_from_2darray(a_tru, presentation_type='g', digits=12) + '$'
            elif comparison == 'sigfig':
                digits = pl.get_integer_attrib(element, 'digits', 2)
                latex_data = '$' + pl.latex_from_2darray(a_tru, presentation_type='sigfig', digits=digits) + '$'
            elif comparison == 'decdig':
                digits = pl.get_integer_attrib(element, 'digits', 2)
                latex_data = '$' + pl.latex_from_2darray(a_tru, presentation_type='f', digits=digits) + '$'
            else:
                raise ValueError('method of comparison "%s" is not valid (must be "relabs", "sigfig", or "decdig")' % comparison)

            html_params = {
                'answer': True,
                'label': label,
                'latex_data': latex_data,
                'uuid': pl.get_uuid()
            }

            with open('pl-matrix-component-input.mustache', 'r', encoding='utf-8') as f:
                html = chevron.render(f, html_params).strip()
        else:
            html = ''

    else:
        raise Exception('Invalid panel type: %s' % data['panel'])

    return html