Criação de Painéis - Consumidor de Dash
Objetivos
O objetivo deste tutorial é criar um consumidor de dashboards, com filtros para que o usuário gere diferentes respostas baseadas nesses filtros.
Índice
- O que é um consumidor de dashboards?
- O que é possível criar com um consumidor de dashboards?
- Preparando o consumer dash basic
- Criando um consumidor de dash
O que é um consumidor de dashboards?
O consumidor de dashboards é uma interface integrada diretamente ao portal, ela permite a exibição de dados de diferentes naturezas conforme o usuário seleciona filtros na interface, oque permite vizualizar diferentes resultados de forma dinâmica.
O que é possível criar com um consumidor de dashboards?
Diferente do consumidor de perguntas, o consumidor de dashboards fornece respostas visuais para os filtros aplicados de forma dinâmica, por meio de uma interface gráfica. Aqui vão algumas demonstrações do potencial da ferramenta:
Filtros com dropdown:

Filtros com slider:

Filtros com checkbox:

Tabelas:

Mapas Cloropléticos:

Além disso, é possível inserir qualquer gráfico visto no tutorial anterior.
Preparando o consumer dash basic
Atenção: Para que que a aplicação funcione, todos arquivos devem estar na pasta geoprocess, criada no primeiro tutorial!
Para este tutorial iremos realizar uma cópia do módulo pgst-consumer-dash-basic. Primeiramente, copie o projeto pgst-consumer-basic para um novo projeto chamado consumer-dash-tutorial, utilizando o comando abaixo:
Em seguida, vá até dashboards.json e faça as seguintes alterações:
Atenção: Substitua a parte abaixo e mantenha o restante, não exclua nenhuma linha.
{
"projects": [
{
"consumer_project_id": "TUTORIAL",
"version": "1.0.0",
"title": "Projetos Tutoriais",
"role_tag": "TUTORIAL"
}
],
"dashboards": [
{
"id": "DASHT",
"version": 1.0,
"consumer_project_id": "TUTORIAL",
"role_tag": "DASHT",
Após copiar a pasta, vá até geoprocess-install/dev_consumers/configs/portal.ini na linha 46 faça as seguintes alterações:
Como você já fez o tutorial 1 um conjunto de recursos já foram instalados no docker. Em seguida abra o terminal e acesse:
No terminal faça as seguintes operações:
Atenção: Verifique se a instalação ocorreu de forma desejada antes de processeguir no tutorial, antes de executar os próximos passos o docker (gerado pelo dev_consumers) todas as aplicações devem estar executando.
Abra um terminal na pasta consumer-dash-tutorial, copie o arquivo de configuração do ambiente:
Abra o arquivo env.conf e atualize o nome do consumidor (propriedade CONSUMER_CODE) para o nome tutorial3. Verique se está igual após a linha 9:
MESSAGE_BROKER_HOST=localhost
MESSAGE_BROKER_PORT=5672
MESSAGE_BROKER_USER=admin
MESSAGE_BROKER_PASSWORD=password
CACHE_HOST=localhost
CACHE_PORT=6379
Instale o ambiente virtual para isolar as dependências do Python. Utilize o comando abaixo:
Ative o ambiente virtual no seu computador utilizando o comando abaixo:
Instale as dependências do projeto.
Instale as dependências do projeto pgst-lib dentro do projeto consumidor.
Para executar a aplicação, abra um terminal na pasta e digite:
Abra a aplicação através da URL: http://localhost:8000/.
A seguinte tela deve ser exibida:

Atenção: Se não mostrar a tela acima, no docker pare a aplicação dc_portal e dc_gateway.
Criando um consumidor de dash
Faça o download do arquivo dados.csv localizado na pasta docs e crie uma pasta chamada data no raiz do projeto, insira o arquivo nesta pasta.
O arquivo dados.csvcontém dados sobre a covid-19 por região e ano. Vamos criar uma seção introdutória e em seguida criaremos gráficos.
Para realizar alterações no consumer iremos trabalhar com dois arquivos dashboards.json e consumer_dash/basic/service.py.
O arquivo dashboards.json define as entradas e saídas do consumer além de definir a organização da tela e os valores dos filtros. Já service.py configura os dados e gráficos que serão exibidos.
Em dashboards.jsonsubstitua todo conteúdo do código pelo seguinte trecho:
{
"projects": [
{
"consumer_project_id": "TUTORIAL",
"version": "1.0.0",
"title": "Projeto Dashboard Tutorial",
"role_tag": "TUTORIAL"
}
],
"dashboards": [
{
"id": "DASHT",
"version": 1.0,
"consumer_project_id": "TUTORIAL",
"role_tag": "DASHT",
"title": "Dashboard covid-19",
"description": "Painel didático com dados sobre a covid-19",
"components": [
{
"type": "div",
"components": [
{
"type": "markdown",
"id": "markdown_1"
}
]
}
],
"callbacks": [
{
"outputs": [
"markdown_1"
]
}
]
}
]
}
Agora vá até consumer_dash/basic/service.py e substitua todo código pelo seguinte trecho:
from baseconsumer.dash_worker import DashWorker, dashProcess
from loguru import logger
import pandas as pd
import requests
import plotly.express as px
class Service(DashWorker):
@dashProcess(componentId="markdown_1")
def process1(self, input):
logger.info("Processando markdown_1")
answer = f'''
#### Sobre:
Este painel utiliza dados fictícios sobre a covid-19 para fins didáticos.
___
'''
return answer
Para executar em modo teste de contrato inclua o trecho em tests/test_001:
from loguru import logger
from consumer_dash.basic.service import Service
class Test001():
service = Service()
def test(self):
logger.info("Testando o método test do módulo test_001.py")
service = Service()
answer = service.test("markdown_1", [])
assert type(answer) == str
Abra o terminal e execute:
Para visualizar os resultados digite (executar modo DASH_DEBUG):Acesse a URL [http://0.0.0.0:8050/]
Em dashboards.json incremente o número das versões de DASHT e reinicie o container dc_portal no docker.
Execute o comando no terminal:
Acesse a URL abaixo para visualizar o resultado:
Resultado esperado:

Cada div possui um tipo, nesta div criamos um markdown, cada componente deve receber uma id que será chamado na seção callback. Em service.py definimos qual será o conteúdo do markdown através da variável answer, que retorna o conteúdo no portal.
Agora, iremos inserir um mapa cloroplético que relaciona dados da covid com um filtro selecionado.
Em dashboards.json, insira o contéudo a partir da linha 27:
,
{
"type": "div",
"style": {
"width": "49%",
"display": "inline-block",
"marginRight": "10px"
},
"components": [
{
"type": "dropdown",
"title": "Selecione um ano:",
"id": "data_1",
"properties": {
"options": [
{
"label": "2025",
"value": 2025
},
{
"label": "2024",
"value": 2024
},
{
"label": "2023",
"value": 2023
},
{
"label": "2022",
"value": 2022
},
{
"label": "2021",
"value": 2021
},
{
"label": "2020",
"value": 2020
}
],
"default": 2020
}
},
{
"type": "graph",
"id": "graph_1"
}
]
}
callbacks, na linha 82 insira o seguinte trecho:
Agora em service.py insira o trecho após o fim de process1:
@dashProcess(componentId="graph_1")
def process2(self, input):
logger.info("Processando graph_1",input)
# Ano selecionado no dropdown
if input[0] is None:
ano_selecionado = 2020
else:
ano_selecionado = int(input[0])
# Ler CSV
path = "../data/dados.csv"
if not os.path.exists(path):
path = "data/dados.csv"
df = pd.read_csv(path)
df_filtrado = df[df["ano"] == ano_selecionado]
# Carregar GeoJSON dos estados do Brasil
url = "https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/brazil-states.geojson"
geojson = requests.get(url).json()
# Construir gráfico no formato dict
answer = dict({
"data": [
{
"type": "choropleth",
"geojson": geojson,
"locations": df_filtrado["estado"].tolist(),
"z": df_filtrado["casos covid-19"].tolist(),
"featureidkey": "properties.name", # precisa bater com o GeoJSON
"colorscale": "rdylgn_r",
"colorbar": {"title": "Casos"},
"hovertext": df_filtrado["estado"].tolist(),
"hoverinfo": "location+z+text"
}
],
"layout": {
"title": f"Casos de Covid-19 no Brasil - {ano_selecionado}",
"geo": {
"fitbounds": "locations",
"visible": False
},
"plot_bgcolor": "#F5F6F9",
"paper_bgcolor": "#F5F6F9"
},
"frames": []
})
return answer
No início de service.pydigite:
Para executar em modo teste de contrato inclua o trecho em tests/test_002:
from loguru import logger
from consumer_dash.basic.service import Service
class Test002():
service = Service()
def test(self):
logger.info("Testando o método test do módulo test_002.py")
service = Service()
answer = service.test("graph_1", ["2021"])
assert type(answer) == dict
Abra o terminal e execute:
Para visualizar os resultados digite (executar modo DASH_DEBUG):
Acesse a URL [http://0.0.0.0:8050/]
Em dashboards.json, incremente o número das versões de DASHT e reinicie o container dc_portal no docker.
Execute o comando no terminal:
Acesse a URL abaixo para visualizar o resultado:
Resultado esperado:

Em dashboards.json, definimos uma nova div para inserir o mapa cloroplético, dentro dessa div definimos dois componentes: um dropdown de ano com suas opções e um gráfico, em callbacks definimos um entrada data_1 e uma saída graph_1. Agora em service.pydefinimos o tipo de gŕafico a ser retornado, os parâmetros a serem inseridos em answer variam conforme o tipo de gráfico selecionado, a resposta é passada em formato de dicionário.
Agora, iremos inserir um gráfico de bolhas que possui região e ano como parâmetros e em seguida relaciona o número de casos, óbitos e taxa de vacinação para cada estado da região no ano escolhido.
Vá até dashboards.json e insira o seguinte trecho na linha 75:
,
{
"type": "div",
"style": {
"width": "49%",
"display": "inline-block"
},
"components": [
{
"type": "dropdown",
"title": "Selecione um ano:",
"id": "data_2",
"properties": {
"options": [
{
"label": "2025",
"value": 2025
},
{
"label": "2024",
"value": 2024
},
{
"label": "2023",
"value": 2023
},
{
"label": "2022",
"value": 2022
},
{
"label": "2021",
"value": 2021
},
{
"label": "2020",
"value": 2020
}
],
"default": 2020
}
},
{
"type": "dropdown",
"title": "Selecione uma região:",
"id": "data_3",
"properties": {
"options": [
{
"label": "Norte",
"value": "Norte"
},
{
"label": "Nordeste",
"value": "Nordeste"
},
{
"label": "Centro-Oeste",
"value": "Centro-Oeste"
},
{
"label": "Sudeste",
"value": "Sudeste"
},
{
"label": "Sul",
"value": "Sul"
}
],
"default": "Nordeste"
}
},
{
"type": "graph",
"id": "graph_2"
}
]
}
Em callbacks, insira o conteúdo na linha 167:
Agora em service.py insira o seguinte conteúdo após process2:
@dashProcess(componentId="graph_2")
def process3(self, input):
logger.info("Processando graph_2", input)
# Input esperado: [região, ano]
if input[0] is None:
ano = 2020
else:
ano = int(input[0])
if input[1] is None:
regiao = "Nordeste"
else:
regiao = input[1]
path = "../data/dados.csv"
if not os.path.exists(path):
path = "data/dados.csv"
df = pd.read_csv(path)
# Filtrar por ano e região
df["casos_100k"] = df["casos covid-19"] / (df["população"] / 100000)
df["obitos_100k"] = df["óbitos covid"] / (df["população"] / 100000)
df_filtro = df[df["ano"] == ano]
df_filtro = df_filtro[df_filtro["regiao"] == regiao]
data = []
# Criar uma bolha para cada estado
for _, row in df_filtro.iterrows():
data.append({
"type": "scatter",
"mode": "markers",
"x": [row["casos_100k"]],
"y": [row["obitos_100k"]],
"text": row["estado"],
"marker": {
"size": [row["taxa vacina"]],
"sizemode": "area",
"sizeref": 2. * df_filtro["taxa vacina"].max() / (40. ** 2),
"sizemin": 4,
"opacity": 0.7
},
"name": row["estado"], # cor diferente por estado
"hovertemplate": (
f"<b>{row['estado']}</b><br>"
f"Ano: {ano}<br>"
f"Vacinação: {row['taxa vacina']}%<br>"
f"Casos/100k: {row['casos_100k']:.1f}<br>"
f"Óbitos/100k: {row['obitos_100k']:.1f}<extra></extra>"
)
})
# Layout
answer = {
"data": data,
"layout": {
"title": f"Região {regiao} - Ano {ano} (Bolhas por estado)",
"xaxis": {"title": "Casos por 100k"},
"yaxis": {"title": "Óbitos por 100k"},
"autosize": True,
"legend": {"title": "Estado"}
},
"frames": []
}
return answer
Para executar em modo teste de contrato inclua o trecho em tests/test_003:
from loguru import logger
from consumer_dash.basic.service import Service
class Test003():
service = Service()
def test(self):
logger.info("Testando o método test do módulo test_003.py")
service = Service()
answer = service.test("graph_2", ["2020", "Nordeste"])
assert type(answer) == dict
Abra o terminal e execute:
Para visualizar os resultados digite (executar modo DASH_DEBUG):
Acesse a URL [http://0.0.0.0:8050/]
Em dashboards.json, incremente o número das versões de DASHT e reinicie o container dc_portal no docker.
Execute o comando no terminal:
Acesse a URL abaixo para visualizar o resultado:
Resultado esperado:

Em todos gráficos, realizamos uma filtragem na base de dados com base no input passado, input é uma lista que possuirá como tamanho o número de parâmetros passados como input no callback. É necessário realizar um tratamento condicional selecionando um valor padrão caso o usuário não escolha nenhuma opção a fim de evitar erros na exibição.
Agora, iremos inserir um gráfico de barras que realiza a filtragem dos dados conforme dois parâmetros: Número de casos ou número de óbitos e exibe para cada ano, o total de casos ou óbitos e mostra através de uma escala de cores a taxa de vacinação daquele ano.
Em dashboards.json, insira o seguinte trecho na linha 152:
,
{
"type": "div",
"style": {
"width": "100%",
"display": "inline-block"
},
"components": [
{
"type": "dropdown",
"title": "Selecione um parâmetro:",
"id": "data_4",
"properties": {
"options": [
{
"label": "Casos",
"value": "Casos"
},
{
"label": "Óbitos",
"value": "Óbitos"
}
],
"default": "Casos"
}
},
{
"type": "graph",
"id": "graph_3"
}
]
}
Em callbacks, na linha 207 insira o seguinte trecho:
Vá até service.pye insira o contéudo após process3:
@dashProcess(componentId="graph_3")
def process4(self, input):
logger.info("Processando graph_3", input)
# input esperado: ["casos"] ou ["obitos"]
if input[0] is None:
metrica = "casos"
else:
metrica = input[0].lower()
path = "../data/dados.csv"
if not os.path.exists(path):
path = "data/dados.csv"
df = pd.read_csv(path)
# Seleciona a métrica (y do gráfico)
if metrica == "casos":
ycol = "casos covid-19"
else:
ycol = "óbitos covid"
# Agrupamento: soma casos/óbitos, média da taxa de vacina
df_agg = (
df.groupby("ano")
.agg({
"casos covid-19": "sum",
"óbitos covid": "sum",
"taxa vacina": "mean"
})
.reset_index()
)
answer = {
"data": [
{
"type": "bar",
"x": df_agg['ano'].tolist(),
"y": df_agg[ycol].tolist(),
"marker": {
"color": df_agg['taxa vacina'].tolist(),
"colorscale": "Viridis",
"colorbar": {
"title": {
"text": "Taxa Vacina"
}
}
},
"hovertemplate": "Ano=%{x}<br>Casos de COVID=%{y}<br>Taxa de vacinação=%{marker.color:.2f}%<extra></extra>"
}
],
"layout": {
"height": 400,
"title": {
"text": f"{ycol.capitalize()} por ano (colorido pela taxa de vacinação)"
},
"xaxis": {
"title": {
"text": "Ano"
}
},
"yaxis": {
"title": {
"text": ycol
}
},
"coloraxis": {
"colorscale": "Viridis",
"colorbar": {
"title": {
"text": "Taxa Vacina"
}
}
}
}
}
return answer
Para executar em modo teste de contrato inclua o trecho em tests/test_004:
from loguru import logger
from consumer_dash.basic.service import Service
class Test004():
service = Service()
def test(self):
logger.info("Testando o método test do módulo test_004.py")
service = Service()
answer = service.test("graph_3", ["casos"])
assert type(answer) == dict
Abra o terminal e execute:
Para visualizar os resultados digite (executar modo DASH_DEBUG):
Acesse a URL [http://0.0.0.0:8050/]
Em dashboards.json, incremente o número das versões de DASHT e reinicie o container dc_portal no docker.
Execute o comando no terminal:
Acesse a URL abaixo para visualizar o resultado:
Resultado esperado:

Uma vez que todos gráficos em service.py são criados em formato de dicionário, o endereço abaixo pode fornecer gráficos em formato JSON prontos para serem adaptados ao código, no gráfico de interesse, basta escolher a opção Python & R.
https://chart-studio.plotly.com/feed/#/
Por fim, vamos inserir uma tabela que seleciona um ano através de um dropdown e uma taxa de vacinação por meio de um slider.
Vá até dashboards.json e insira o conteúdo na linha 183:
,
{
"type": "div",
"style": {
"width": "100%",
"display": "inline-block"
},
"components": [
{
"type": "dropdown",
"title": "Selecione um ano:",
"id": "data_5",
"properties": {
"options": [
{
"label": "2025",
"value": 2025
},
{
"label": "2024",
"value": 2024
},
{
"label": "2023",
"value": 2023
},
{
"label": "2022",
"value": 2022
},
{
"label": "2021",
"value": 2021
},
{
"label": "2020",
"value": 2020
}
],
"default": 2020
}
},
{
"type": "slider",
"title": "Filtro - Selecione uma Taxa de Vacinação",
"id": "data_6",
"properties": {
"begin": 0,
"end": 100,
"step": 2,
"value": 0
}
},
{
"type": "datatable",
"id": "datatable_1"
}
]
}
Em callbacks, na linha 273 insira o trecho de código:
Vá até service.py e insira o contéudo após process4:
@dashProcess(componentId="datatable_1")
def process5(self, input):
logger.info("Processando datatable_1")
if input[0] is None:
ano = 2020
else:
ano = input[0]
if input[1] is None:
taxavacina = 0.0
else:
taxavacina = input[1]
path = "../data/dados.csv"
if not os.path.exists(path):
path = "data/dados.csv"
df = pd.read_csv(path)
df = df[df["ano"] == ano]
df = df[df["taxa vacina"] >= taxavacina]
answer = df.to_dict('records')
return answer
Para executar em modo teste de contrato inclua o trecho em tests/test_005:
from loguru import logger
from consumer_dash.basic.service import Service
class Test005():
service = Service()
def test(self):
logger.info("Testando o método test do módulo test_005.py")
service = Service()
answer = service.test("datatable_1", [2020, 1])
assert type(answer) == list
Abra o terminal e execute:
Para visualizar os resultados digite (executar modo DASH_DEBUG):
Acesse a URL [http://0.0.0.0:8050/]
Em dashboards.json, incremente o número das versões de DASHT e reinicie o container dc_portal no docker.
Execute o comando no terminal:
Acesse a URL abaixo para visualizar o resultado:
Resultado esperado:

Pronto! Agora você é capaz de criar seus próprios dashboards com filtros.
Resultado Final: