def charts_layout(df, settings, **inputs): """ Builds main dash inputs with dropdown options populated with the columns of the dataframe associated with the page. Inputs included are: chart tabs, query, x, y, z, group, aggregation, rolling window/computation, chart per group toggle, bar sort, bar mode, y-axis range editors :param df: dataframe to drive the charts built on page :type df: :class:`pandas:pandas.DataFrame` :param settings: global settings associated with this dataframe (contains properties like "query") :type param: dict :return: dash markup """ chart_type, x, y, z, group, agg = ( inputs.get(p) for p in ['chart_type', 'x', 'y', 'z', 'group', 'agg']) y = y or [] show_input = show_input_handler(chart_type) show_cpg = show_chart_per_group(**inputs) show_yaxis = show_yaxis_ranges(**inputs) bar_style = bar_input_style(**inputs) animate_style, animate_by_style, animate_opts = animate_styles( df, **inputs) options = build_input_options(df, **inputs) x_options, y_multi_options, y_single_options, z_options, group_options, barsort_options, yaxis_options = options query_placeholder = ("Enter pandas query (ex: col1 == 1)") query_value = inputs.get('query') or inner_build_query( settings, settings.get('query')) query_label = html.Div([ html.Span('Query'), html. A(html.I(className='fa fa-info-circle ml-4'), href= 'https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#indexing-query', target='_blank', style={'color': 'white'}) ], className='input-group-addon', style={'minWidth': '7em'}) yaxis_type = (inputs.get('yaxis') or {}).get('type') or 'default' yaxis_type_style = { 'borderRadius': '0 0.25rem 0.25rem 0' } if yaxis_type == 'default' else None show_map = chart_type == 'maps' map_props = ['map_type', 'loc_mode', 'loc', 'lat', 'lon', 'map_val'] map_type, loc_mode, loc, lat, lon, map_val = (inputs.get(p) for p in map_props) map_scope, proj = (inputs.get(p) for p in ['scope', 'proj']) loc_options, lat_options, lon_options, map_val_options = build_map_options( df, type=map_type, loc=loc, lat=lat, lon=lon, map_val=map_val) cscale_style = colorscale_input_style(**inputs) default_cscale = 'Greens' if chart_type == 'heatmap' else 'Reds' group_val_style, main_input_class = main_inputs_and_group_val_display( inputs) group_val = [json.dumps(gv) for gv in inputs.get('group_val') or []] def show_style(show): return {'display': 'block' if show else 'none'} def show_map_style(show): return {} if show else {'display': 'none'} return html.Div([ dcc.Store(id='query-data', data=inputs.get('query')), dcc.Store(id='input-data', data={ k: v for k, v in inputs.items() if k not in ['cpg', 'barmode', 'barsort'] }), dcc.Store(id='chart-input-data', data={ k: v for k, v in inputs.items() if k in ['cpg', 'barmode', 'barsort'] }), dcc.Store(id='map-input-data', data={ k: v for k, v in inputs.items() if k in [ 'map_type', 'map_code', 'lat', 'lon', 'map_val', 'scope', 'proj' ] }), dcc.Store(id='range-data'), dcc.Store(id='yaxis-data', data=inputs.get('yaxis')), dcc.Store(id='last-chart-input-data', data=inputs), dcc.Input(id='chart-code', type='hidden'), html.Div(html.Div(dcc.Tabs( id='chart-tabs', value=chart_type or 'line', children=[ build_tab(t.get('label', t['value'].capitalize()), t['value']) for t in CHARTS ], style=dict(height='36px')), className='col-md-12'), className='row pt-3 pb-3 charts-filters'), html.Div(html.Div([ html.Div([ query_label, dcc.Input(id='query-input', type='text', placeholder=query_placeholder, className='form-control', value=query_value, style={'lineHeight': 'inherit'}) ], className='input-group mr-3') ], className='col'), className='row pt-3 pb-3 charts-filters'), html.Div([ html.Div([ html.Div([ build_input( [html.Div('X'), html.Small('(Agg By)')], dcc.Dropdown( id='x-dropdown', options=x_options, placeholder='Select a column', value=x, style=dict(width='inherit'), ), label_class='input-group-addon d-block pt-1 pb-0'), build_input('Y', dcc.Dropdown(id='y-multi-dropdown', options=y_multi_options, multi=True, placeholder='Select a column(s)', style=dict(width='inherit'), value=y if show_input( 'y', 'multi') else None), className='col', id='y-multi-input', style=show_style(show_input('y', 'multi'))), build_input( [html.Div('Y'), html.Small('(Agg By)')], dcc.Dropdown(id='y-single-dropdown', options=y_single_options, placeholder='Select a column', style=dict(width='inherit'), value=y[0] if show_input('y') and len(y) else None), className='col', label_class='input-group-addon d-block pt-1 pb-0', id='y-single-input', style=show_style(show_input('y'))), build_input('Z', dcc.Dropdown(id='z-dropdown', options=z_options, placeholder='Select a column', style=dict(width='inherit'), value=z), className='col', id='z-input', style=show_style(show_input('z'))), build_input('Group', dcc.Dropdown( id='group-dropdown', options=group_options, multi=True, placeholder='Select a group(s)', value=group, style=dict(width='inherit'), ), className='col', id='group-input', style=show_style(show_input('group'))) ], id='non-map-inputs', style={} if not show_map else {'display': 'none'}, className='row pt-3 pb-3 charts-filters'), html.Div([ build_map_type_tabs(map_type), html.Div([ html.Div( [ build_loc_mode_hover(loc_mode), dcc.Dropdown(id='map-loc-mode-dropdown', options=[ build_option(v) for v in [ "ISO-3", "USA-states", "country names" ] ], style=dict(width='inherit'), value=loc_mode) ], className='input-group mr-3', ) ], id='map-loc-mode-input', style=show_map_style(map_type == 'choropleth'), className='col-auto'), build_input( [html.Div('Locations'), html.Small('(Agg By)')], dcc.Dropdown( id='map-loc-dropdown', options=loc_options, placeholder='Select a column', value=loc, style=dict(width='inherit'), ), id='map-loc-input', label_class='input-group-addon d-block pt-1 pb-0', style=show_map_style(map_type == 'choropleth')), build_input( [html.Div('Lat'), html.Small('(Agg By)')], dcc.Dropdown( id='map-lat-dropdown', options=lat_options, placeholder='Select a column', value=lat, style=dict(width='inherit'), ), id='map-lat-input', label_class='input-group-addon d-block pt-1 pb-0', style=show_map_style(map_type == 'scattergeo')), build_input( [html.Div('Lon'), html.Small('(Agg By)')], dcc.Dropdown(id='map-lon-dropdown', options=lon_options, placeholder='Select a column', style=dict(width='inherit'), value=lon), id='map-lon-input', label_class='input-group-addon d-block pt-1 pb-0', style=show_map_style(map_type == 'scattergeo')), build_input( 'Scope', dcc.Dropdown(id='map-scope-dropdown', options=[build_option(v) for v in SCOPES], style=dict(width='inherit'), value=map_scope or 'world'), id='map-scope-input', style=show_map_style(map_type == 'scattergeo')), html.Div([ html.Div( [ build_proj_hover(proj), dcc.Dropdown(id='map-proj-dropdown', options=[ build_option(v) for v in PROJECTIONS ], style=dict(width='inherit'), value=proj) ], className='input-group mr-3', ) ], id='map-proj-input', style=show_map_style(map_type == 'scattergeo'), className='col-auto'), build_input( 'Value', dcc.Dropdown(id='map-val-dropdown', options=map_val_options, placeholder='Select a column', style=dict(width='inherit'), value=map_val)), build_input('Group', dcc.Dropdown( id='map-group-dropdown', options=group_options, multi=True, placeholder='Select a group(s)', value=inputs.get('map_group'), style=dict(width='inherit'), ), className='col', id='map-group-input') ], id='map-inputs', className='row pt-3 pb-3 charts-filters', style={} if show_map else {'display': 'none'}), html.Div([ build_input( 'Aggregation', dcc.Dropdown( id='agg-dropdown', options=[ build_option(v, AGGS[v]) for v in [ 'count', 'nunique', 'sum', 'mean', 'rolling', 'corr', 'first', 'last', 'median', 'min', 'max', 'std', 'var', 'mad', 'prod', 'raw' ] ], placeholder='Select an aggregation', style=dict(width='inherit'), value=agg or 'raw', )), html.Div([ build_input( 'Window', dcc.Input(id='window-input', type='number', placeholder='Enter days', className='form-control text-center', style={'lineHeight': 'inherit'}, value=inputs.get('window'))), build_input( 'Computation', dcc.Dropdown(id='rolling-comp-dropdown', options=[ build_option( 'corr', 'Correlation'), build_option('count', 'Count'), build_option('cov', 'Covariance'), build_option('kurt', 'Kurtosis'), build_option('max', 'Maximum'), build_option('mean', 'Mean'), build_option('median', 'Median'), build_option('min', 'Minimum'), build_option('skew', 'Skew'), build_option( 'std', 'Standard Deviation'), build_option('sum', 'Sum'), build_option('var', 'Variance'), ], placeholder='Select an computation', style=dict(width='inherit'), value=inputs.get('rolling_comp'))) ], id='rolling-inputs', style=show_style(agg == 'rolling')) ], className='row pt-3 pb-3 charts-filters'), html.Div([ build_input('Chart Per\nGroup', html.Div(daq.BooleanSwitch(id='cpg-toggle', on=inputs.get('cpg') or False), className='toggle-wrapper'), id='cpg-input', style=show_style(show_cpg), className='col-auto'), build_input('Barmode', dcc.Dropdown( id='barmode-dropdown', options=[ build_option('group', 'Group'), build_option('stack', 'Stack'), build_option('relative', 'Relative'), ], value=inputs.get('barmode') or 'group', placeholder='Select a mode', ), className='col-auto addon-min-width', style=bar_style, id='barmode-input'), build_input('Barsort', dcc.Dropdown(id='barsort-dropdown', options=barsort_options, value=inputs.get('barsort')), className='col-auto addon-min-width', style=bar_style, id='barsort-input'), html.Div(html.Div( [ html.Span('Y-Axis', className='input-group-addon'), html.Div(dcc.Tabs( id='yaxis-type', value=yaxis_type, children=get_yaxis_type_tabs(y), ), id='yaxis-type-div', className='form-control col-auto pt-3', style=yaxis_type_style), dcc.Dropdown(id='yaxis-dropdown', options=yaxis_options), html.Span('Min:', className='input-group-addon col-auto', id='yaxis-min-label'), dcc.Input(id='yaxis-min-input', type='number', className='form-control col-auto', style={'lineHeight': 'inherit'}), html.Span('Max:', className='input-group-addon col-auto', id='yaxis-max-label'), dcc.Input(id='yaxis-max-input', type='number', className='form-control col-auto', style={'lineHeight': 'inherit'}) ], className='input-group', id='yaxis-min-max-options', ), className='col-auto addon-min-width', id='yaxis-input', style=show_style(show_yaxis)), build_input( 'Colorscale', dcc.Dropdown( id='colorscale-dropdown', options=[build_option(o) for o in COLORSCALES], value=inputs.get('colorscale') or default_cscale), className='col-auto addon-min-width', style=cscale_style, id='colorscale-input'), build_input('Animate', html.Div(daq.BooleanSwitch( id='animate-toggle', on=inputs.get('animate') or False), className='toggle-wrapper'), id='animate-input', style=animate_style, className='col-auto'), build_input('Animate By', dcc.Dropdown(id='animate-by-dropdown', options=animate_opts, value=inputs.get('animate_by')), className='col-auto addon-min-width', style=animate_style, id='animate-by-input'), ], className='row pt-3 pb-5 charts-filters') ], id='main-inputs', className=main_input_class), build_input('Group(s)', dcc.Dropdown( id='group-val-dropdown', multi=True, placeholder='Select a group value(s)', value=group_val, style=dict(width='inherit'), ), className='col-md-4 pt-3 pb-5', id='group-val-input', style=group_val_style) ], className='row'), dcc.Loading(html.Div(id='chart-content', style={'height': '69vh'}), type='circle'), dcc.Textarea(id="copy-text", style=dict(position='absolute', left='-110%')) ], className='charts-body')
def charts_layout(df, settings, **inputs): """ Builds main dash inputs with dropdown options populated with the columns of the dataframe associated with the page. Inputs included are: chart tabs, query, x, y, z, group, aggregation, rolling window/computation, chart per group toggle, bar sort, bar mode, y-axis range editors :param df: dataframe to drive the charts built on page :type df: :class:`pandas:pandas.DataFrame` :param settings: global settings associated with this dataframe (contains properties like "query") :type param: dict :return: dash markup """ [chart_type, x, y, z, group, agg] = [inputs.get(p) for p in ['chart_type', 'x', 'y', 'z', 'group', 'agg']] y = y or [] show_input = show_input_handler(chart_type) show_cpg = show_chart_per_group(**inputs) show_yaxis = show_yaxis_ranges(**inputs) bar_style = bar_input_style(**inputs) options = build_input_options(df, **inputs) x_options, y_multi_options, y_single_options, z_options, group_options, barsort_options, yaxis_options = options query_placeholder = ( "Enter pandas query (ex: col1 == 1)" ) query_value = inputs.get('query') or inner_build_query(settings, settings.get('query')) query_label = html.Div([ html.Span('Query'), html.A(html.I(className='fa fa-info-circle ml-4'), href='https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#indexing-query', target='_blank', style={'color': 'white'}) ], className='input-group-addon', style={'minWidth': '7em'}) yaxis_type = (inputs.get('yaxis') or {}).get('type') or 'default' yaxis_type_style = {'borderRadius': '0 0.25rem 0.25rem 0'} if yaxis_type == 'default' else None return html.Div([ dcc.Store(id='query-data', data=inputs.get('query')), dcc.Store(id='input-data', data={k: v for k, v in inputs.items() if k not in ['cpg', 'barmode', 'barsort']}), dcc.Store(id='chart-input-data', data={k: v for k, v in inputs.items() if k in ['cpg', 'barmode', 'barsort']}), dcc.Store(id='range-data'), dcc.Store(id='yaxis-data', data=inputs.get('yaxis')), dcc.Store(id='last-chart-input-data', data=inputs), dcc.Input(id='chart-code', type='hidden'), html.Div(html.Div(dcc.Tabs( id='chart-tabs', value=chart_type or 'line', children=[build_tab(t.get('label', t['value'].capitalize()), t['value']) for t in CHARTS], style=dict(height='36px') ), className='col-md-12'), className='row pt-3 pb-3 charts-filters'), html.Div(html.Div([ html.Div([ query_label, dcc.Input( id='query-input', type='text', placeholder=query_placeholder, className='form-control', value=query_value, style={'lineHeight': 'inherit'}) ], className='input-group mr-3')], className='col' ), className='row pt-3 pb-3 charts-filters'), html.Div([ build_input('X', dcc.Dropdown( id='x-dropdown', options=x_options, placeholder='Select a column', value=x, style=dict(width='inherit'), )), build_input('Y', dcc.Dropdown( id='y-multi-dropdown', options=y_multi_options, multi=True, placeholder='Select a column(s)', style=dict(width='inherit'), value=y if show_input('y', 'multi') else None ), className='col', id='y-multi-input', style={'display': 'block' if show_input('y', 'multi') else 'none'}), build_input('Y', dcc.Dropdown( id='y-single-dropdown', options=y_single_options, placeholder='Select a column', style=dict(width='inherit'), value=y[0] if show_input('y') and len(y) else None ), className='col', id='y-single-input', style={'display': 'block' if show_input('y') else 'none'}), build_input('Z', dcc.Dropdown( id='z-dropdown', options=z_options, placeholder='Select a column', style=dict(width='inherit'), value=z ), className='col', id='z-input', style={'display': 'block' if show_input('z') else 'none'}), build_input('Group', dcc.Dropdown( id='group-dropdown', options=group_options, multi=True, placeholder='Select a group(s)', value=group, style=dict(width='inherit'), ), className='col', id='group-input', style={'display': 'block' if show_input('group') else 'none'}), ], className='row pt-3 pb-3 charts-filters'), html.Div([ build_input('Aggregation', dcc.Dropdown( id='agg-dropdown', options=[build_option(v, AGGS[v]) for v in ['count', 'nunique', 'sum', 'mean', 'rolling', 'corr', 'first', 'last', 'median', 'min', 'max', 'std', 'var', 'mad', 'prod']], placeholder='Select an aggregation', style=dict(width='inherit'), value=agg, )), html.Div([ build_input('Window', dcc.Input( id='window-input', type='number', placeholder='Enter days', className='form-control text-center', style={'lineHeight': 'inherit'}, value=inputs.get('window') )), build_input('Computation', dcc.Dropdown( id='rolling-comp-dropdown', options=[ build_option('corr', 'Correlation'), build_option('count', 'Count'), build_option('cov', 'Covariance'), build_option('kurt', 'Kurtosis'), build_option('max', 'Maximum'), build_option('mean', 'Mean'), build_option('median', 'Median'), build_option('min', 'Minimum'), build_option('skew', 'Skew'), build_option('std', 'Standard Deviation'), build_option('sum', 'Sum'), build_option('var', 'Variance'), ], placeholder='Select an computation', style=dict(width='inherit'), value=inputs.get('rolling_comp') )) ], id='rolling-inputs', style=dict(display='block' if agg == 'rolling' else 'none')) ], className='row pt-3 pb-3 charts-filters'), html.Div( [ build_input('Chart Per\nGroup', html.Div(daq.BooleanSwitch(id='cpg-toggle', on=inputs.get('cpg') or False), className='toggle-wrapper'), id='cpg-input', style={'display': 'block' if show_cpg else 'none'}, className='col-auto'), build_input('Barmode', dcc.Dropdown( id='barmode-dropdown', options=[ build_option('group', 'Group'), build_option('stack', 'Stack'), build_option('relative', 'Relative'), ], value=inputs.get('barmode') or 'group', placeholder='Select a mode', ), className='col-auto addon-min-width', style=bar_style, id='barmode-input'), build_input('Barsort', dcc.Dropdown( id='barsort-dropdown', options=barsort_options, value=inputs.get('barsort') ), className='col-auto addon-min-width', style=bar_style, id='barsort-input'), html.Div( html.Div( [ html.Span('Y-Axis', className='input-group-addon'), html.Div(dcc.Tabs( id='yaxis-type', value=yaxis_type, children=get_yaxis_type_tabs(y), ), id='yaxis-type-div', className='form-control col-auto pt-3', style=yaxis_type_style), dcc.Dropdown(id='yaxis-dropdown', options=yaxis_options), html.Span('Min:', className='input-group-addon col-auto', id='yaxis-min-label'), dcc.Input( id='yaxis-min-input', type='number', className='form-control col-auto', style={'lineHeight': 'inherit'} ), html.Span('Max:', className='input-group-addon col-auto', id='yaxis-max-label'), dcc.Input( id='yaxis-max-input', type='number', className='form-control col-auto', style={'lineHeight': 'inherit'} ) ], className='input-group', id='yaxis-min-max-options', ), className='col-auto addon-min-width', id='yaxis-input', style=dict(display='block' if show_yaxis else 'none') ), ], className='row pt-3 pb-5 charts-filters' ), dcc.Loading(html.Div(id='chart-content', style={'height': '69vh'}), type='circle'), dcc.Textarea(id="copy-text", style=dict(position='absolute', left='-110%')) ], className='charts-body')