def plot_lengths(
        report: Report,
        coupling_data: dict
):
    """

    :param report:
    :param coupling_data:
    :param times:
    :param sampled:
    :return:
    """

    times = [e.time for e in coupling_data['lengths']]
    lengths = [e.value for e in coupling_data['lengths']]
    values, uncertainties = mstats.values.unzip(lengths)

    plot = plotting.make_line_data(
        times,
        values,
        uncertainties,
        name='Length'
    )

    report.add_plotly(
        data=plot['data'],
        layout=plotting.create_layout(
            plot['layout'],
            'Coupling Lengths',
            'Activity Cycle (#)',
            'Length (m)'
        )
    )
def add_header_section(
        report: reporting.Report,
        settings: dict,
        activity_phases: limb.Property
):
    """

    :param report:
    :param settings:
    :param activity_phases:
    :return:
    """

    activity_phases = activity_phases.values()
    support_phases = settings['support_phases']

    activity_phases = ['{}%'.format(round(100 * x)) for x in activity_phases]
    support_phases = ['{}%'.format(round(100 * x)) for x in support_phases]

    report.add_template(
        paths.resource('trial', 'header.html'),
        title=settings.get('name'),
        summary=settings.get('summary'),
        duty_cycle=round(100.0 * settings['duty_cycle']),
        activity_phases=activity_phases,
        support_phases=support_phases,
        date=datetime.utcnow().strftime("%m-%d-%Y %H:%M")
    )
def plot_deviations(
        report: Report,
        coupling_data: dict
):
    """

    :param report:
    :param coupling_data:
    :return:
    """

    times = [e.time for e in coupling_data['lengths']]
    deviations = []
    for dev in coupling_data['deviations']:
        deviations.append(100.0 * dev)

    values, uncertainties = mstats.values.unzip(deviations)

    plot = plotting.make_line_data(
        times,
        values,
        uncertainties,
        name='Deviation',
        color=plotting.get_color(1, as_string=True)
    )

    report.add_plotly(
        data=plot['data'],
        layout=plotting.create_layout(
            plot['layout'],
            'Coupling Length Median Deviations',
            'Activity Cycle (#)',
            'Median Deviation (%)'
        )
    )
def add_coupling_plots(
        report: reporting.Report,
        trials: typing.List[dict]
):
    """
    Generates coupling report data from the analyzed coupling data and the
    individual simulation trial results

    :param report:
        Grouped coupling data from the grouped simulation results
    :param trials:
        Simulation results for each trial run by the group
    """

    distribution_traces = []
    population_traces = []
    index = 0

    for trial in trials:
        trial_data = reader.trial(trial['id'], paths.results())

        index += 1
        coupling_data = trial_data['couplings']

        distribution_traces.append(dict(
            x=coupling_data['distribution_profile']['x'],
            y=coupling_data['distribution_profile']['y'],
            type='scatter',
            mode='lines',
            name='{}'.format(index)
        ))

        population_traces.append(dict(
            x=coupling_data['population'],
            type='box',
            name='{}'.format(index),
            boxpoints=False
        ))

    report.add_plotly(
        data=distribution_traces,
        layout=plotting.create_layout(
            title='Coupling Length Trial Distributions',
            x_label='Expectation Value (au)',
            y_label='Coupling Length (m)'
        )
    )

    report.add_plotly(
        data=population_traces,
        layout=plotting.create_layout(
            title='Coupling Length Trials',
            x_label='Coupling Length (m)',
            y_label='Trial Index (#)'
        )
    )
def plot_strides(
        report: Report,
        advancement_data: dict
):
    """

    :param report:
    :param advancement_data:
    :return:
    """

    keys = (
        (0, 'left_pes_strides'),
        (1, 'right_pes_strides'),
        (2, 'left_manus_strides'),
        (4, 'right_manus_strides')
    )

    traces = []
    layout = dict()

    for entry in keys:
        color_index = entry[0]
        key = entry[1]


        times = [e.time for e in advancement_data[key]]
        values = [e.value for e in advancement_data[key]]
        values, uncertainties = mstats.values.unzip(values)

        name = ' '.join(key.split('_')[:2]).capitalize()
        plot = plotting.make_line_data(
            times,
            values,
            uncertainties,
            name=name,
            color=plotting.get_color(color_index, 0.5, True),
            fill_color=plotting.get_color(color_index, 0.2, True)
        )
        traces.extend(plot['data'])
        layout.update(plot['layout'])

    report.add_plotly(
        data=traces,
        layout=plotting.create_layout(
            layout,
            'Stepping Distances',
            'Activity Cycle (#)',
            'Distance (m)'
        )
    )
def plot_advance(report: Report, coupling_data: dict):
    """

    :param report:
    :param coupling_data:
    :param times:
    :return:
    """

    traces = []

    sources = dict(
        rear_advance={
            'name': 'Rear',
            'index': 0
        },
        forward_advance={
            'name': 'Forward',
            'index': 1
        }
    )

    for key, data in sources.items():
        events = coupling_data[key]

        times = [e.time for e in events]
        values, uncertainties = mstats.values.unzip([e.value for e in events])

        plot = plotting.make_line_data(
            x=times,
            y=values,
            y_unc=uncertainties,
            name=data['name'],
            color=plotting.get_color(data['index'], 0.6, as_string=True),
            fill_color=plotting.get_color(data['index'], 0.2, as_string=True)
        )
        traces += plot['data']

    report.add_plotly(
        data=traces,
        layout=plotting.create_layout(
            title='Coupler Rate of Advancement',
            x_label='Activity Cycle (#)',
            y_label='Advance Rate (m/cycle)'
        )
    )
def add_svg(
        sim_id: str,
        report: reporting.Report,
        track_definition: trackway.TrackwayDefinition,
        foot_positions: limb.Property
):
    """

    :param sim_id:
    :param report:
    :param track_definition:
    :param foot_positions:
    :return:
    """

    drawer = svg.SvgWriter(padding=5)
    svg_settings = draw.trackway_positions(
        limb_positions=track_definition.limb_positions,
        positions=foot_positions,
        drawer=drawer
    )

    dom_template = """
        <div class="svg-box">
          <div class="svg-box-inner">{{ svg }}</div>
          <div class="svg-controls-box" style="display:none">
            <div>
                <div>Activity: <span class="activity-status"></span></div>
                <div>Support: <span class="support-status"></span></div>
            </div>
            <div class="spacer"></div>
          </div>
        </div>
        """

    report.add_svg(
        drawer.dumps(),
        filename='{}.svg'.format(sim_id),
        dom_template=dom_template
    )

    return svg_settings
def add_info(report: reporting.Report, settings: dict, coupling_data: dict):
    """
    Adds the info section to the report, which is an existing html template
    that is pre-populated with data by rendering it with Jinja2

    :param report:
        The report being created
    :param settings:
        Configuration settings for the trial simulation
    :param coupling_data:
        Coupling analysis data
    :return:
    """

    bounds = coupling_data['bounds']
    bounds = [mstats.value.round_significant(b, 4) for b in bounds]

    report.add_template(
        paths.resource('trial', 'info.html'),
        coupling_length=coupling_data['value'].html_label,
        coupling_bounds=bounds
    )
def plot_distribution(
        report: Report,
        coupling_data: dict
):
    """

    :param report:
    :param coupling_data:
    :return:
    """

    report.add_plotly(
        data=[go.Scatter(
            x=coupling_data['distribution_profile']['x'],
            y=coupling_data['distribution_profile']['y'],
            mode='lines'
        )],
        layout=plotting.create_layout(
            title='Coupling Length Distribution',
            x_label='Coupling Distance (m)',
            y_label='Expectation (au)'
        )
    )
def add_header_section(
        report: reporting.Report,
        settings: dict,
        trials: typing.List[dict]
):
    trial_data = []
    for t in trials:
        color = plotting.get_color(t['index'] - 1, as_string=True)

        trial_data.append(dict(
            index=t['index'],
            id=t['id'],
            name=t['settings']['name'],
            summary=t['settings'].get('summary', ''),
            back_color=color
        ))

    report.add_template(
        path=paths.resource('group', 'header.html'),
        title=settings['name'],
        date=datetime.utcnow().strftime("%m-%d-%Y %H:%M"),
        summary=settings.get('summary'),
        trials=trial_data
    )
def add_length_plot(report: Report, separation_data: dict, times:dict):
    """

    :param report:
    :param separation_data:
    :param times:
    :return:
    """

    sources = [
        dict(
            layout=plotting.create_layout(
                title='Left &amp; Right Separations',
                x_label='Activity Cycle (#)',
                y_label='Separation (m)'
            ),
            items=[
                dict(
                    name='Left',
                    data=separation_data['left_lengths'],
                    index=2
                ),
                dict(
                    name='Right',
                    data=separation_data['right_lengths'],
                    index=4
                )
            ]
        ),

        dict(
            layout=plotting.create_layout(
                title='Forward &amp; Rear Separations',
                x_label='Activity Cycle (#)',
                y_label='Separation (m)'
            ),
            items=[
                dict(
                    name='Forward',
                    data=separation_data['forward_lengths'],
                    index=1
                ),
                dict(
                    name='Rear',
                    data=separation_data['rear_lengths'],
                    index=0
                )
            ]
        )
    ]

    for source in sources:
        traces = []

        for item in source['items']:
            values, uncertainties = mstats.values.unzip(item['data'])
            color = plotting.get_color(item['index'], 0.7, as_string=True)
            fill = plotting.get_color(item['index'], 0.2, as_string=True)

            plot = plotting.make_line_data(
                x=times['cycles'],
                y=values,
                y_unc=uncertainties,
                name=item['name'],
                color=color,
                fill_color=fill
            )
            traces += plot['data']

        report.add_plotly(data=traces, layout=source['layout'])