简体   繁体   English

如何更改 dash_table.DataTable 单元格并更新其他回调

[英]how to alter a dash_table.DataTable cell and update other callbacks

I have a Plotly-Dash dashboard here that is updated using the variable inputs on the left-hand side, as well as a few "fixed" variables.我在这里有一个 Plotly-Dash 仪表板,它使用左侧的变量输入以及一些“固定”变量进行更新。

These fixed variables are shown in the dash_table.DataTable at the bottom of image.这些固定变量显示在图像底部的 dash_table.DataTable 中。 Should the user choose to alter the value in the DataTable, I would like to update the callbacks that used these fixed values.如果用户选择更改 DataTable 中的值,我想更新使用这些固定值的回调。

As of now, the callbacks use the the dropdown and numeric inputs as [Input(' ', ' ')] and the fixed variables are stored as variables, and used in the relevant equations.截至目前,回调使用下拉菜单和数字输入作为 [Input(' ', ' ')] 并且固定变量存储为变量,并在相关方程中使用。

Is there a way to either:有没有办法:

  • use a callback to define these fixed variable values.使用回调来定义这些固定变量值。 And when the table is changed, so are these "fixed" variables,..当表发生变化时,这些“固定”变量也会发生变化,..
  • or, use a callback to search the table and if changes are made, update the fixed variable value(s).或者,使用回调来搜索表,如果进行了更改,则更新固定变量值。

A bit of a vague question I know, I've googled this just about every which way and most of the info has to do with filtering dataTables and displaying rows, less so selecting and storing cell values as variables.我知道一个有点模糊的问题,我几乎用谷歌搜索过这个问题,大部分信息都与过滤数据表和显示行有关,而不是选择和存储单元格值作为变量。

All I really need is an example of taking a cell numeric value, using as a callback [Input()], and that callback using the input in a basic algebraic formula.我真正需要的是一个使用单元格数值的示例,用作回调 [Input()],以及使用基本代数公式中的输入的回调。

I have attached the code, you will see I've been tinkering with the first callback, the rest of the code works fine.我附上了代码,你会看到我一直在修补第一个回调,其余的代码工作正常。

仪表盘输出

import dash
import dash_design_kit as ddk
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
import pandas as pd
import dash_daq as daq
import dash_table
from dash.dependencies import Input, Output
import math

import pandas as pd
import pathlib

from crunch_numbers import *
num_datacards = 5

# theme.js supplies some additional styling, generated using editor

# REQUIRED FOR DEPLOYMENT
app = dash.Dash(__name__, suppress_callback_exceptions=True) # keep suppress_ in production code
server = app.server # expose server variable for Procfile


app.layout = ddk.App(show_editor=True, children=[
    
    ddk.Header([
            ddk.Logo("assets/komatsuLogo.png",
                style={
                    "height": "30px",
                    "margin-right":"0px",
                    "width": "auto",
                },
            ),
            
            ddk.Title('Drivetrain Selection'),
        ]), # end of ddk.Header



  
    ddk.Block(width=20,children=[ # left-side (inputs)
        ddk.Card([ # machine Configuration
            ddk.CardHeader("Machine Configuration"),
            html.Br(),
            dcc.Dropdown(
                id='Platform',
                options=[
                        {'label': 'Badger', 'value': 'Badger'},
                        {'label': 'Weasel', 'value': 'Weasel'},
                    ],
                value='Badger',
                clearable=False,
                placeholder="Select Machine",
            ),
            html.Br(),
            dcc.Dropdown(
                id='battery_size',
                options=[
                        {'label': '5S1P ( 66kWh)', 'value': 66},
                        {'label': '5S2P (132kWh)', 'value': 132},
                    ],
                value=66,
                clearable=False,
                #placeholder="Battery Size (kWh)",
            ),
            html.Br(),
            dcc.Dropdown(
                id='Motor Selection',
                options=[
                        {'label': 'MD 2200', 'value': 'sumo_md_2200'},
                    ],
                value='sumo_md_2200',
                clearable=False,
                placeholder="Motor Selection",
            ),
        ]), # end of Machine Configuration

        ddk.Card([ # "Inputs"
            ddk.CardHeader("Inputs"),

            daq.NumericInput(
                id='ramp_angle',
                label='% Grade',
                labelPosition='top',
                value=0,
                min=0,
                max=18,
                size='auto',
            ),
            html.Br(),
            daq.NumericInput(
                id='ground_speed',
                label='Speed (kph)',
                labelPosition='top',
                value=0,
                min=0,
                max=15,
                size='auto',
            ),
            html.Br(),
            daq.NumericInput(
                id='parasitics',
                label='Parasitic Loads (kw)',
                labelPosition='top',
                value=0,
                min=0,
                max=30,
                size='auto',
            ),
            #html.Br(),

        ]), # end of "Inputs"
    
    ]), # end of left-side

    ddk.Block(width=80, children=[ # right side block
        ddk.Card([ # datacards and plot
            ddk.DataCard(
                width=100/num_datacards, # num_datacards is defined at top of file
                id='motor_speed',
                value=0,
                label="(RPM)",
            ),
            ddk.DataCard(
                width=100/num_datacards,
                id='motor_torque',
                value=0,
                label="(NM)",
            ),
            ddk.DataCard(
                width=100/num_datacards,
                id='traction_efficiency',
                value=0,
                label="(Tot. %)",
            ),
            ddk.DataCard(
                width=100/num_datacards,
                id='total_power',
                value=0,
                label="(kW)",
            ),
            ddk.DataCard(
                width=100/num_datacards,
                id='autonomy',
                value=0,
                label="(km)",
            ),
            dcc.Graph(id='plot'),
        ]), # end datacards and plot

        ddk.Card(width=100,children=[ # table card

            ddk.CardHeader("Machine Characteristics"),

            dcc.Markdown(
                    """
                    Update values in the table to modify machine performance.
                    """,
                    style={'textAlign': 'justify'}
            ),

            dash_table.DataTable(
                    id='machine_spec_table',
                    data=Badger.to_dict("rows"),
                    columns=[ # only 'Values' and 'Mechanical Efficiency' are editable!
                        {"name": i, "id": i,"editable":False,"selectable":True} 
                        if i == "Description" or i == "Units"
                        else  {"name": i, "id": i,"selectable":True} 
                        for i in Badger.columns
                        

                    ],
                    style_as_list_view=True,
                    style_header={"fontWeight": "bold", "textTransform": "capitalize"},
                    style_data_conditional=[
                        {
                            "if": {"row_index": "even"},
                            "backgroundColor": "var(--report_background_page)",
                        }
                    ],
                    editable=True,
            ),

        ]) # end of table card
    ]) # end of right side block
]) # end of ddk.App


""" 
Example of how to manage column width, should the need arise
    style_cell_conditional=[   
        {
            'if': {'column_id': 'Units'},
            'width': 25
        } for c in ['Units']
    ],
"""

############################# TABLE CALLBACKS ##################################################
################################################################################################

def find_fixed_variables(dict_list,var):
    return dict_list[]
    


############################# DRIVETRAIN SELECTION CALLBACKS ###################################
################################################################################################

@app.callback(
    Output('motor_speed', 'value'),
    [Input('ground_speed', 'value'),
     Input('machine_spec_table','data')] # , Input('tire_rr', 'value'), Input('diff_ratio', 'value'), Input('transfer_ratio', 'value')
)
def update_output(ground_speed,dict_list): #tire_rr, diff_ratio, transfer_ratio

    return math.floor((ground_speed*1000)/60/(2*math.pi*tire_rr)*diff_ratio*transfer_ratio)

@app.callback(
        Output('total_power', 'value'),
        [Input('ground_speed', 'value'), 
         Input('ramp_angle', 'value')] #, Input('parasitics', 'value')] # Input('GVW', 'value'), Input('RR', 'value'),, Input('traction_efficiency', 'value')
)
def update_output(ground_speed, ramp_angle): #, traction_efficiency

    power = math.floor(((RR/100)*(ground_speed*0.278) * GVW * gravity_cnst * math.cos(math.atan(ramp_angle/100))
                        / 0.9 / 1000)
                       + ((ground_speed * 0.278) * GVW * gravity_cnst * math.sin(math.atan(ramp_angle / 100))
                          / 0.9 / 1000)
                       )

    if ground_speed == 0:
        return 0
    else:
        return power

@app.callback(
    Output('motor_torque', 'value'),
    [Input('ground_speed', 'value'), 
     Input('motor_speed', 'value'), 
     Input('total_power', 'value'),]
)
def update_output(ground_speed, motor_speed, total_power):
    if ground_speed == 0:
        return 0
    elif math.floor(9.5488*total_power*1000/motor_speed) < 50:
        return 50
    else:
        return math.floor(9.5488*total_power*1000/motor_speed)

@app.callback(
    Output('plot', 'figure'),
    [Input('motor_speed', 'value'), 
     Input('motor_torque', 'value')] #Input('Motor Selection', 'value')
)
def update_output(motor_speed, motor_torque): # , Motor_Selection

    fig = go.Figure(
        layout=go.Layout(
            # title="Motor Efficiency Plot",
            # autosize=False,
            # width=500,
            paper_bgcolor="rgba(0,0,0,0)",
            plot_bgcolor="rgba(0,0,0,0)",
            yaxis=dict(title="Motor Torque (Nm)"),
            xaxis=dict(title="Motor Speed (RPM)"),
        )
    )
    fig.update_layout(legend=dict(
        orientation="h",
        yanchor="bottom",
        y=1,
        xanchor="left",
        x=0
    )
    )

    fig.add_trace(go.Scatter(
        x=TM4_BoundaryCurve['Speed (rpm)'],
        y=TM4_BoundaryCurve['Peak Torque (Nm)'],
        name="Peak Torque",
    )
    )
    fig.add_trace(go.Scatter(
        x=TM4_BoundaryCurve['Speed (rpm)'],
        y=TM4_BoundaryCurve['Continuous Torque (Nm)'],
        name="Cont. Torque",
    )
    )

    fig.add_trace(go.Contour(
        z=[TM4_EfficiencyMap['0'], TM4_EfficiencyMap['280'], TM4_EfficiencyMap['420'], TM4_EfficiencyMap['560'],
           TM4_EfficiencyMap['700'],
           TM4_EfficiencyMap['840'], TM4_EfficiencyMap['980'], TM4_EfficiencyMap['1120'], TM4_EfficiencyMap['1260'],
           TM4_EfficiencyMap['1400'],
           TM4_EfficiencyMap['1540'], TM4_EfficiencyMap['1680'], TM4_EfficiencyMap['1820'], TM4_EfficiencyMap['1960'],
           TM4_EfficiencyMap['2100'],
           TM4_EfficiencyMap['2240'], TM4_EfficiencyMap['2380'], TM4_EfficiencyMap['2520'], TM4_EfficiencyMap['2660'],
           TM4_EfficiencyMap['2800'],
           TM4_EfficiencyMap['2940'], TM4_EfficiencyMap['3080'], TM4_EfficiencyMap['3220'], TM4_EfficiencyMap['3360'],
           TM4_EfficiencyMap['3500'], ],
        x=TM4_EfficiencyMap['Speed'],
        y=TM4_EfficiencyMap['Torque'],
        transpose=True,
        colorscale='Blues',
        ncontours=20,
        opacity=0.5,
        showscale=False,
        contours=dict(
            showlabels=True,  # show labels on contours
            labelfont=dict(  # label font properties
                size=12,
                color='white',
            )
        )
    )
    )

    fig.add_trace(go.Scatter(
        x=[motor_speed],
        y=[motor_torque],
        name="Actual",
        mode="markers",
        marker=dict(size=20, color='black', symbol="x"),
    )
    )
    return fig

@app.callback(
    Output('autonomy', 'value'),
    [Input('ground_speed', 'value'), 
     Input('total_power', 'value'), 
     Input('battery_size', 'value')]
)
def update_output(ground_speed, total_power, battery_size):
    if ground_speed == 0 or total_power == 0:
        return 0
    else:
        return round((battery_size * DOD / total_power) * ground_speed, 2)
    
@app.callback(
    Output('traction_efficiency', 'value'),
    [Input('motor_speed', 'value'), 
     Input('motor_torque', 'value')]
)
def update_output(motor_speed, motor_torque):
    df = pd.DataFrame(TM4_EfficiencyMap)
    if motor_speed <= 280:
        speed = str(0)
        torque = 50
    else:
        speed = str(int((round(motor_speed / 140, 0) / 2) * 280))
        torque = round(motor_torque / 50, 0) * 50

    z = sum(round(df.loc[df['Torque'] == torque, speed] / 100 * diff_eff * transfer_eff * driveshaft_mt * driveshaft_td, 2))
    return z





################################# MANDATORY SERVER CODE ##################################
if __name__ == '__main__':
    app.run_server(debug=True)

Alright so easy fix, nothing a few print() test statements can't fix lol.好吧,这么简单的修复,没有什么是一些 print() 测试语句无法修复的,哈哈。 Essentially depending on the type of callback input you use for Input('machine_spec_table','data')基本上取决于您用于 Input('machine_spec_table','data') 的回调输入类型

Here I used 'data', there are plenty of others available and explained in documentation,在这里我使用了“数据”,还有很多其他可用的并在文档中进行了解释,

the input to the function is as follows:该函数的输入如下:

your_var = [
    {'Description': 'Gross Vehicle Weight', 'Values': 29500, 'Units': 'kg', 'Mechanical Efficiency': '-'}, 
    {'Description': 'Weight Distribution', 'Values': '60/40', 'Units': '', 'Mechanical Efficiency': '-'}, 
    {'Description': 'Tire Rolling Radius', 'Values': 0.589, 'Units': 'm', 'Mechanical Efficiency': '-'}, 
    {'Description': 'Differential Ratio', 'Values': 20.65, 'Units': '', 'Mechanical Efficiency': 0.93}, 
    {'Description': 'Transfer Case Ratio', 'Values': 2.48, 'Units': '', 'Mechanical Efficiency': 0.98}, 
    {'Description': 'Rolling Resistance', 'Values': 0.02, 'Units': '', 'Mechanical Efficiency': '-'}, 
    {'Description': 'Drive Shaft', 'Values': '-', 'Units': '', 'Mechanical Efficiency': 0.98}
]

A list of dictionaries!字典列表! Easy to access, something along the lines of table[0]['Values] does just fine :) (0 being a the list index,'Values' the dictionary key).易于访问,类似于table[0]['Values]做得很好:)(0 是列表索引,'Values' 是字典键)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM