Example #1
0
    def tornadoPlot(self, simId, scenario, resultName, tornadoType,
                    sliderValue, selectedData):
        corrDF = self.getCorrDF(simId, scenario, resultName)

        if tornadoType == 'normalized':
            squared = corrDF.spearman**2
            corrDF['normalized'] = squared / squared.sum()
            corrDF['sign'] = 1
            corrDF.ix[(corrDF.spearman < 0), 'sign'] = -1
            corrDF[
                'value'] = corrDF.normalized * corrDF.sign  # normalized squares with signs restored
            plotColumn = 'value'
            title = 'Normalized rank correlation'
        else:
            plotColumn = 'spearman'
            title = 'Rank correlation'

        title += ' of {} for scenario {}'.format(resultName, scenario)

        varCount = min(
            20, len(corrDF)
        )  # if sliderValue is None else len(corrDF[corrDF['abs'] >= sliderValue]))
        varNames = list(reversed(corrDF.index[:varCount]))
        values = list(reversed(corrDF[plotColumn][:varCount]))

        plotData = go.Bar(
            orientation='h',
            x=values,
            y=varNames,
            width=0.6,
            marker=dict(
                color=getColor('TornadoPlotBar'),
                line=dict(color=getColor('TornadoPlotLine'), width=0),
            ),
            textposition='none',
            name='Rank correlation',
            hoverinfo='skip',  # prevents hover events
        )

        layout = updateStyle('Plot',
                             title=title,
                             margin=updateStyle('PlotMargin', l=300),
                             xaxis=dict(range=[-1, 1]),
                             dragmode='select')

        figure = dict(data=[plotData], layout=layout)
        return figure
Example #2
0
    def showDistribution(project, simId, scenario, outputName, sliderInfo,
                         distOptions, selectedData):
        _logger.debug('showDistribution(%s, %s, %s, %s, %s)' %
                      (project, simId, scenario, outputName, selectedData))

        # Clear selectedData if context changes
        context = (project, simId, scenario, outputName)
        if not data.histogramContext or context != data.histogramContext:
            _logger.debug('showDistribution: clearing context')
            selectedData = sliderInfo = None
            data.histogramContext = context

        # if called before values are known, return an empty plot
        if not (project and scenario and outputName) or simId is None:
            plotData = {'x': []}
            title = 'Please select a model output to plot'
            annotations = None
        else:
            plotData, title, annotations = data.distPlot(
                simId, scenario, outputName, sliderInfo, distOptions,
                selectedData)
        # TBD: generalize this
        if Oct16:
            if outputName == 'percent-change':
                xtitle = 'Change from baseline fuel'
                xticksuffix = '%'
            else:
                # latex formatting is broken, but HTML works fine
                # xtitle = '$g CO_2 MJ^{-1}$' if Oct16 else ''
                xtitle = 'g CO<sub>2</sub> MJ<sup>-1</sup>'
                xticksuffix = None
        else:
            xtitle = data.db.getOutputUnits(outputName)
            xticksuffix = ''

        layout = updateStyle('Plot',
                             title=title,
                             yaxis={
                                 'title': 'Probability density',
                                 'tickvals': []
                             },
                             xaxis={
                                 'title': xtitle,
                                 'ticksuffix': xticksuffix,
                             },
                             margin=getStyle('PlotMarginWithXTitle'),
                             dragmode='select',
                             showLegend=True,
                             legend=dict(x=0.0,
                                         y=1.0,
                                         bgcolor=getColor('PlotBg')))

        if annotations:
            layout['annotations'] = annotations

        figure = dict(data=plotData, layout=layout)
        return figure
Example #3
0
    def layout(self):
        layout = html.Div(
            [
                dataStore(id='paraCoords-vars'),
                dataStore(id='dist-selected'),
                html.H1('Monte Carlo Simulation Explorer', className='title'),
                html.Table(
                    [
                        html.Tr([
                            html.Th('Project'),
                            html.Th('Simulation'),
                            html.Th('Scenario'),
                            html.Th('Model Output'),
                        ]),
                        html.Tr([
                            html.Td(self.projectChooser()),
                            html.Td(self.simChooser()),
                            html.Td(self.scenarioChooser()),
                            html.Td(self.outputChooser())
                        ])
                    ],
                    style={
                        'width': '100%',
                        'border': '1px solid black',
                        'table-layout': 'fixed',
                        'background-color': getColor('ChooserBgColor')
                    }),
                html.Div(
                    [
                        # distribution cluster and tornado chart
                        html.Div([
                            html.Div(self.distributionSectionLayout(),
                                     className='cell twocol'),
                            html.Div(self.tornadoSectionLayout(),
                                     className='cell twocol')
                        ],
                                 className='row'),

                        # parallel coordinates section
                        html.Div([
                            html.Div([
                                html.P([
                                    'Brush vertically over ranges to filter; click outside the selected range to reset. ',
                                    'Drag variable names below to reorder. Slider sets the number of vars to plot'
                                ],
                                       style=getStyle('HelpText')),
                                html.Div(
                                    [
                                        dcc.Slider(
                                            id='paraCoords-slider',
                                            min=1,
                                            max=10,
                                            step=1,
                                            marks={
                                                value:
                                                sliderLabel(value)
                                                for value in range(1, 11, 1)
                                            },
                                            updatemode='drag',
                                            value=6),
                                    ],
                                    style={
                                        'margin-bottom': 30,
                                        'margin-left': 'auto',
                                        'margin-right': 'auto',
                                        'width': 400
                                    }),
                                html.Div(dcc.Graph(id='paraCoords')),
                            ],
                                     className='cell onecol')
                        ],
                                 className='row'),

                        # Correlation convergence section
                        html.Div([
                            html.Div([
                                html.Span('Correlation convergence',
                                          style=getStyle('Label')),
                                html.Div('', style={'height': 15}),
                                html.Div(dcc.Graph(id='corr-convergence')),
                            ],
                                     className='cell onecol')
                        ],
                                 className='row'),

                        # Scatterplot section
                        html.Div([
                            html.Div([
                                html.Div([
                                    html.Div(style={'height': 15}),
                                    html.Span(
                                        'Model Inputs (random variables)',
                                        style=getStyle('Label')),
                                    html.Div(style={'height': 15}),
                                    self.inputChooser(multi=True)
                                ],
                                         style=updateStyle('Chooser',
                                                           width=900)),
                                html.Div(style={'height': 15}),
                                html.Div([
                                    html.Span('Model Outputs',
                                              style=getStyle('Label')),
                                    self.multiOutputChooser()
                                ],
                                         style=updateStyle('Chooser',
                                                           width=900)),
                                html.Div([
                                    html.Button('Create scatterplot',
                                                id='scatterplot-button',
                                                style=getStyle('Button'))
                                ],
                                         style={'margin': 5}),
                                html.Div([dcc.Graph(id='scatter-matrix')],
                                         style=updateStyle('AutoMargins'))
                            ],
                                     className='cell onecol')
                        ],
                                 className='row'),
                    ],
                    className='table',
                    style={
                        'width': 1200,
                        'margin-left': 'auto',
                        'margin-right': 'auto'
                    }),
            ],
            style=getStyle('Page'))

        return layout
Example #4
0
    def scatterPlots(self, simId, scenario, inputs, outputs):
        """
        Plot a set of small scatterplots showing correlation between chosen
        model inputs and outputs.

        :param simId: (int) simulation id
        :param scenario: (str) scenario name
        :param inputs: (iterable of str) names of inputs to plot
        :param outputs: (iterable of str) names of outputs to plot

        :return: dash 'figure' data.
        """
        allInputs = self.getParameterValues(simId)
        inputsDF = allInputs[inputs]

        outputsDF = pd.DataFrame(columns=outputs)
        for output in outputs:
            outputsDF[output] = self.getOutValues(simId, scenario, output)

        inputsDF = inputsDF.iloc[
            outputsDF.index]  # select only trials for which we have results

        numIns = len(inputs)
        numOuts = len(outputs)
        fig = tools.make_subplots(rows=numOuts,
                                  cols=numIns,
                                  vertical_spacing=0.01,
                                  shared_xaxes=True,
                                  shared_yaxes=True)
        layout = fig['layout']
        for row, output in enumerate(outputs):
            yAxisNum = row + 1
            xAxisNum = 0

            for col, input in enumerate(inputs):
                xAxisNum += 1

                trace = go.Scatter(
                    x=inputsDF[input],
                    y=outputsDF[output],
                    hoverinfo='skip',  # don't show or fire events
                    mode='markers',
                    marker=dict(size=1,
                                opacity=0.9,
                                color=getColor('ScatterPoints')))

                fig.append_trace(trace, row + 1, col + 1)

                # Compute the names of the corresponding axes
                xaxis = "xaxis{}".format(xAxisNum)
                yaxis = "yaxis{}".format(yAxisNum)

                layout[xaxis].update(title=input,
                                     showgrid=False,
                                     zeroline=False)
                layout[yaxis].update(title=output,
                                     showgrid=False,
                                     zeroline=False)

        layout.update(
            margin=dict(l=50, r=30, t=30, b=30),
            height=140 * numOuts + 20,
            #width= 130 * numIns,
            showlegend=False,
            font=dict(size=9, family=getFont('PlotText')))
        return fig
Example #5
0
    def distPlot(self, simId, scenario, outputName, sliderInfo, distOptions,
                 selectedData):
        """
        Generate the plot data for the distribution plot. Return three items:
        the plot data, title, and annotations (might be empty list).
        """
        annotations = []
        colors = []

        values = self.getOutValues(simId, scenario, outputName)

        if values is None:
            title = 'Please select a model output to plot'
            plotData = [
                dict(
                    type='bar',
                    x=[],
                    y=[],
                    name=outputName,
                    showlegend=False,
                )
            ]
            return plotData, title, annotations

        title = 'Distribution of %s for scenario %s' % (outputName, scenario)

        bins = min(
            100,
            len(values)) or 1  # 1 for corner case of no data; bins must be > 0

        # Generate histogram data to be able to color bars directly
        counts, edges = np.histogram(values, bins, density=True)
        barCount = len(counts)

        # Plot the counts on x-axis at the mean of each pair of edges
        barValues = [np.mean(edges[i:i + 1]) for i in range(barCount)]

        if sliderInfo:
            minQ, maxQ = sliderInfo
            minX = values.quantile(q=minQ / 100.0, interpolation='linear')
            maxX = values.quantile(q=maxQ / 100.0, interpolation='linear')
        else:
            minX, maxX = selectedData['range']['x'] if selectedData else (
                edges[0], edges[-1])

        # Sub-select trials based on selection range to show in parallel coords plot
        self.selectedResults = values[values.between(minX,
                                                     maxX,
                                                     inclusive=True)]

        # highlight selected bars by desaturating non-selected items
        active = getColor('DistBarsActive')
        inactive = getColor('DistBarsInactive')
        for i in range(barCount):
            colors.append(active if minX <= barValues[i] <= maxX else inactive)

        distPlot = ff.create_distplot([values], [outputName],
                                      bin_size=1,
                                      show_hist=False,
                                      show_rug=False,
                                      curve_type='kde')

        # TBD: generalize this
        if outputName == 'percent-change':
            tickvalues = ['%d%%' % int(value) for value in barValues]
        else:
            tickvalues = ['%.2f' % value for value in barValues]

        plotData = [
            dict(type='bar',
                 x=barValues,
                 y=list(counts),
                 name=outputName,
                 histnorm='probability density',
                 marker=dict(color=colors),
                 showlegend=False,
                 text=tickvalues,
                 hoverinfo='text')
        ]

        if 'kde' in distOptions:
            distData = distPlot.data[0]
            plotData.append(
                dict(
                    type='scatter',
                    x=distData['x'],
                    y=distData['y'],
                    marker=dict(color=getColor('KDE')),
                    hoverinfo='skip',  # prevents hover events
                    showlegend=False,
                ))

        showMean = 'mean' in distOptions
        showMedian = 'median' in distOptions

        if showMean or showMedian:
            info = values.describe()
            maxY = max(counts)
            labelSize = 12
            bgcolor = getColor('PlotBg')

            mean = info['mean']
            median = info['50%']

            def lineData(name, x, maxY, color):
                d = dict(type='scatter',
                         mode='lines',
                         name=name,
                         x=[x, x],
                         y=[0.0000001, maxY],
                         marker=dict(color=color))
                return d

            def notation(x, y, xanchor, color):
                # TBD: generalize this
                if outputName == 'percent-change':
                    text = '%d%%' % x
                else:
                    text = '%.2f' % x

                d = dict(x=x,
                         y=y,
                         text=text,
                         xanchor=xanchor,
                         yanchor='top',
                         showarrow=False,
                         bgcolor=bgcolor,
                         opacity=0.7,
                         font=dict(family='Lato', size=labelSize, color=color))
                return d

            if showMean:
                color = getColor('MeanLineColor')
                xanchor = 'right' if mean <= median else 'left'
                plotData.append(lineData('mean', mean, maxY, color))
                annotations.append(notation(mean, 0.95 * maxY, xanchor, color))

            if showMedian:
                color = getColor('MedianLineColor')
                xanchor = 'right' if median < mean else 'left'
                plotData.append(lineData('median', median, maxY, color))
                annotations.append(notation(median, maxY, xanchor, color))

        return plotData, title, annotations