Доступ к редактируемым аннотациям - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть простое приложение Dash с графиком, который обновляется при нажатии кнопки «Обновить».Я добавил редактируемую аннотацию на этот график.Я хочу иметь возможность доступа к тому, что пользователь вводил в аннотацию, поэтому при обновлении графика аннотация остается прежней.Мне больше всего интересно, есть ли способ получить доступ к тому, как они его редактировали.

Я пытался сохранить текущую аннотацию в компоненте хранения, к которому обращаются при создании графика.Я пытался создать кнопку «Сохранить», которая изменяет данные хранилища на текущий текст аннотации. Я могу только предположить, что при редактировании аннотации новый текст не сохраняется в том же месте, где был текст по умолчанию.Это или что-то происходит у меня над головой, и я не понимаю этого.

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, State, Output
import random

app = dash.Dash(__name__)
app.config['suppress_callback_exceptions'] = True

app.layout = html.Div(
    id = 'top_level',
    children=[
        html.Div(
            id='plot_div',
            children=[],
        ),

        html.Button(
            id = 'update',
            children="Update",
        ),

        dcc.Store(
            id='annotation_storage',
            data='Editable Annotation',
        )
    ]
)
@app.callback(
    Output('plot_div', 'children'),
    [Input('update', 'n_clicks')],
    [State('annotation_storage', 'data')]
)
def plot_update(clicked, annotation):
    if clicked:
        x = random.sample(range(1,101), 20)
        y = random.sample(range(1,101), 20)
        figure = {'data': [{'x': x, 'y': y, 
                            'type': 'scatter', 'mode': 'markers'}],
                  'layout': {
                      'xaxis': {
                          'fixedrange': True,
                          'zeroline': False,
                      },
                      'yaxis': {
                          'fixedrange': True,
                          'zeroline': False,
                      },
                      'annotations': [{
                            'x': -0.05,
                            'y': 0.5,
                            'showarrow':False,
                            'text':annotation,
                            'xref':'paper',
                            'yref':'paper',
                            }],
                        }
                  }
        return [dcc.Graph(
            id = 'plot_output',
            figure = figure,
            config = {
                'editable': True,
                'edits': {
                    'axisTitleText': False,
                    'titleText': False,
                },
                'displayModeBar': False,
            },
        ),
        html.Button(
            id = 'save_annotation',
            children='Save',
        ),
        ]

@app.callback(
    Output('annotation_storage', 'data'),
    [Input('save_annotation', 'n_clicks')],
    [State('plot_output', 'figure')]
)
def save_annotation(clicked, figure):
    if clicked:
        annotation = figure['layout']['annotations'][0]['text']
        return annotation
if __name__ == '__main__':
    app.run_server(debug=True, port=1000)

В настоящее время аннотация просто возвращается к тексту по умолчанию «Редактируемая аннотация», когда график обновляется, даже когдапользователь редактирует это.Я хочу, чтобы аннотация оставалась неизменной даже при обновлении графика.Любое понимание будет с благодарностью!Спасибо!

1 Ответ

0 голосов
/ 17 февраля 2019

Как написано в руководстве пользователя Dash :

Компонент dcc.Graph имеет четыре атрибута, которые могут изменяться при взаимодействии с пользователем: hoverData, clickData,selectedData, relayoutData.

Это означает, что используемый вами атрибут figure не обновляется при взаимодействии пользователя с графиком.

Чтобы устранить проблему, обновитеваша функция обратного вызова для использования relayoutData вместо figure:

@app.callback(
    Output('annotation_storage', 'data'),
    [Input('save_annotation', 'n_clicks')],
    [State('plot_output', 'relayoutData')]
)
def save_annotation(clicked, relayout_data):
    if clicked:
        annotation = relayout_data['annotations[0].text']
        return annotation

Вы можете запустить свое приложение в режиме отладки и добавить точку останова внутри функции обратного вызова, чтобы изучить значения, заданныечетыре вышеупомянутых атрибута.Вот что я сделал, чтобы найти ключ для текста аннотации внутри relayout_data.

...