Pular para conteúdo

GeoProcess Consumer-Dash-Sample

Introdução

O módulo Consumer-Dash-Sample é na verdade um módulo implementando de um super consumidor para dashboards de demostração e exemplificação das principais funcionalidades disponíveis na plataforma GeoProcess. A idéia desse módulo é ser utilizado como um sistema de consulta para implementação de consumidores para construção de dashboards para propósitos específicos em qualquer projeto.

Quando desejamos desenvolver um dashboard devemos pensar em algumas questões como: Quantos gráficos são necessários? Quais as dependências desses gráficos? Quais as entradas desses gráficos? Quais as bases de dados utilizadas na construção desses gráficos? Quais tipos de gráficos melhor se ajusta ao meu objetivo? A partir dessas informações podemos começar a implementação do consumidor de dashboard. Os exemplos mostrados a seguir exemplificam diversas possibilidades para a construção de dashboards e para demonstração das capacidades da plataforma GeoProcess.

Um Dashboard é um conjunto de gráficos e de entradas, em que cada gráfico pode ter múltiplas entradas. Os Dashboards são recursos úteis para realizar análises exploratórias nos dados. Pode-se construir dashboards com quantos gráficos e entradas se desejar. Os Dashboards dentro da plataforma GeoProcess não tem nenhuma relação com os consumidores (Perguntas).

Objetivo Deste Dashboard

O objetivo dessa aplicação exemplo é mostrar a robustez da plataforma na construção de dashboards interativos. Nesse sentido, o objetivo e exibir gráficos de barras, gráficos de pizza e tabelas contendo informações sobre tamanho da população e o IDH para diferentes estados e regiões do Brasil. A resposta visual esperada nesse dashboard é mostrado a seguir.

Tela Objetivo do Dashboard

Para cada um dos gráficos, parâmetros de entradas podem ser selecionados. Através dessas seleções a saída mostrada é alterada. Alguns dos parâmetros deste exemplo são: estado alvo, ano alvo e região alvo.

A seguir será descrita uma visão geral do módulo Consumer-Dash-Sample.

Visão Geral

A estrutura com as pastas e arquivos principais do projeto Consumer-Dash-Sample está destacada a seguir.

Estrutura de Pastas Consumidor Dash Sample

Na raiz do projeto, estão os principais componentes do CONSUMER-DASH-SAMPLE, incluindo:

  • main.py: Módulo principal em Python e ponto de entrada da aplicação consumidora.

  • consumer_dash/: Pasta em que fica localizado o módulo consumidor, nesse exemplo o módulo service.py na pasta basic.

  • conf_samples/ Pasta em que temos o arquivo de configuração env.conf que deverá ser copiado para a raiz do projeto.

  • graph_output/: Armazena os arquivos de resposta com os gráficos que serão utilizados na construção do dashboard.

  • logs/: Armazena os logs gerados pelo consumidor, facilitando o acompanhamento de sua execução.

  • tests/: Pasta dedicada aos testes de software.

  • dashboards/: Pasta que contém arquivos de configuração importante em formato JSON. Esses arquivos definem uma série de configurações sobre o consumidor de dashboard.

A seguir será detalhado alguns dos principais arquivos, módulos e diretórios destacados acima do consumidor dash sample.

Módulo Service

No módulo service.py na pasta consumer_dash/basic/ temos o código do consumidor responsável pelo dashboard a ser mostrado. Neste módulo, temos a declaração de uma classe chamada Service que herda de DashWorker (definida na biblioteca PGST-LIB). Essa classe contém um consumidor de dashboards com o objetivo e exibir gráficos de barras, gráficos de pizza e tabelas contendo informações sobre tamanho da população e o IDH para diferentes estados e regiões do Brasil.

A seguirm, apresentamos uma visão geral dos métodos da classe Service.

class Service(DashWorker):
    ...

    @dashProcess(componentId="graph_s1")
    def process1(self, input)
        ...

    @dashProcess(componentId="graph_s2")
    def process2(self, input)
        ...
    ...
    @dashProcess(componentId="graph_d2_s1")
    def process21(self, input)
        ...

    @dashProcess(componentId="graph_d2_s1")
    def process21(self, input)
        ...
    ...

A seguir vemos a implementação do método process1. Este método é responsável pelo processamento do primeiro gráfico (acessado através do componentId que é igual a graph_s1) do dashboard.

@dashProcess(componentId="graph_s1")
def process1(self, input):
    print("Processando graph_s1", input)
    if input[0] == None:
        estado = 'MG'
    else:
        estado = input[0]

    df = pd.read_csv(os.path.join('data', 'data-brasil-dash.csv'))
    answer = dict({
            "data": [
                {
                    "name": "População",
                    "type": "bar",
                    "x": df[df['estado'] == estado]['ano'],
                    "y": df[df['estado'] == estado]['população'],
                }
            ],
            "layout": {
                "title": "População por Estado (" + str(estado) + ")",
                "legend": {
                    "font": {
                        "color": "#4D5663"
                    },
                    "bgcolor": "#F5F6F9"
                },
                "xaxis1": {
                    "title": "Ano",
                    "tickfont": {
                        "color": "#4D5663"
                    },
                    "titlefont": {
                        "color": "#4D5663"
                    },
                    "type": "category"
                },
                "yaxis1": {
                    "title": "População",
                    "tickfont": {
                        "color": "#4D5663"
                    },
                    "titlefont": {
                        "color": "#4D5663"
                    },
                    "zerolinecolor": "#E1E5ED"
                },
                "plot_bgcolor": "#F5F6F9",
                "paper_bgcolor": "#F5F6F9"
            },
            "frames": []
        })
    return answer

Informação

Repare que, por ser uma aplicação de exemplo, os dados estão injetados diretamente no código. Em uma aplicação real, esses dados são carregados de algum banco de dados.

O arquivo CSV lido possui dados separados nas categorias: ano, estado, região, população e IDH:

ano,estado,região,população,IDH
1991,AC,Norte,406835,0.402
1991,AL,Nordeste,2655073,0.37
...
1991,TO,Norte,982132,0.369
2001,AC,Norte,557526,0.517
2001,AL,Nordeste,3025646,0.471
...
2001,TO,Norte,1181548,0.525
2011,AC,Norte,758000,0.663
2011,AL,Nordeste,3189000,0.631
...
2011,TO,Norte,1393000,0.699
2022,AC,Norte,910000,0.710
2022,AL,Nordeste,3435000,0.684
...
2022,TO,Norte,1669000,0.731

Nessa implementação temos a modelagem de um dos gráficos do dashboard. Esse método (process1) possui um decorador @dashProcess com o parâmetro componentId (linha 1). Este método recebe apenas um parâmetro com nome input que é uma lista contendo as informações de entrada do método (linha 2). A primeira ação do método é imprimir na tela uma informação indicando esse gráfico já começou a ser processado (linha 3). As linhas 4 a 7 definem o valor do padrão da variável estado, quando não setado, ou então, pegam o valor definido na interface gráfica. Na linha 9 é lido um arquivo CSV com os dados para exibição do gráfico e armazenado em uma variável do tipo dataframe (pandas). Na linha 10 até 51, é definido um dificionário com a resposta. O dicionário possui as partes principais de data e layout. Esse código é autoexplicativo assim não será explicado com detalhes, os valores permitidos para parâmetros do gráfico são os valores definidos na biblioteca Plotly. Na linha 52, a resposta é retornada.

Após executar a aplicação consumidora (python3 main.py CONTRACT_TEST 001), um arquivo HTML é gerado na pasta graph_outpout para ser posteriormente exibido no dashboard do GeoProcess. A imagem a seguir mostra a resposta no frontend do sistema.

Resposta Consumer Dash Sample 1

A seguir vemos a implementação do método process2. Este método representa o processamento do primeiro gráfico (acessado através do componentId que é igual a graph_s2) do dashboard.

@dashProcess(componentId="graph_s2")
def process2(self, input):
    print("Processando graph_s2", input)
    if input[0] == None:
        estado = 'MG'
    else:
        estado = input[0]
    df = pd.read_csv(os.path.join('data', 'data-brasil-dash.csv'))
    answer = dict({
            "data": [
                {
                    "name": "IDH",
                    "type": "bar",
                    "x": df[df['estado'] == estado]['ano'],
                    "y": df[df['estado'] == estado]['IDH'],
                }
            ],
            "layout": {
                "title": "IDH por Estado (" + str(estado) + ")",
                "legend": {
                    "font": {
                        "color": "#4D5663"
                    },
                    "bgcolor": "#F5F6F9"
                },
                "xaxis1": {
                    "title": "Ano",
                    "tickfont": {
                        "color": "#4D5663"
                    },
                    "titlefont": {
                        "color": "#4D5663"
                    },
                    "type": "category"
                },
                "yaxis1": {
                    "title": "IDH",
                    "tickfont": {
                        "color": "#4D5663"
                    },
                    "titlefont": {
                        "color": "#4D5663"
                    },
                    "zerolinecolor": "#E1E5ED"
                },
                "plot_bgcolor": "#F5F6F9",
                "paper_bgcolor": "#F5F6F9"
            },
            "frames": []
        })
    return answer

Após executar a aplicação consumidora (python3 main.py CONTRACT_TEST 002), uma resposta visual é exibida no dashboard do sistema após processado do process2. A imagem a seguir mostra a resposta no frontend do sistema.

Resposta Consumer Dash Sample 2

A seguir vemos a implementação do método process3. Este método representa o processamento do terceiro gráfico do dashboard.

@dashProcess(componentId="graph_s3")
def process3(self, input):
    print("Processando graph_s3", input)
    if input[0] == None:
        ano = 2022
    else:
        ano = input[0]
    print(ano)
    df = pd.read_csv(os.path.join('data', 'data-brasil-dash.csv'))
    answer = dict({
            "data": [
                {
                    "name": "População-Pizza",
                    "type": "pie",
                    "hole": 0.1,
                    "marker": {
                        "colors": [
                            "#F00", "#0F0", "#00F", "#FF0", "#F0F", "#0FF", "#800", "#080", "#008",
                            "#808", "#808", "#088", "#CCC", "#888", "#F70", "#FD0", "#F40", "#F55",
                            "#26B", "#82E", "#937", "#2D2", "#7F7", "#0CD", "#48B", "#D61", "#854"
                        ]
                    },
                    "hoverinfo": "all",
                    "labels": [
                        "AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO",
                        "MA", "MT", "MS", "MG", "PA", "PB", "PR", "PE", "PI",
                        "RJ", "RN", "RS", "RO", "RR", "SC", "SP", "SE", "TO"
                    ],
                    "values": df[df['ano'] == ano]['população']
                }
            ],
            "layout": {
                "title": "População por Ano (" + str(ano) + ")",
                "autosize": True
            },
            "frames": []
        })
    return answer

Após executar a aplicação consumidora (python3 main.py CONTRACT_TEST 003), uma resposta visual é exibida no dashboard do sistema após processado do process3. A imagem a seguir mostra a resposta no frontend do sistema.

Resposta Consumer Dash Sample 3

A seguir vemos a implementação do método process4. Este método representa o processamento do quarto gráfico do dashboard.

@dashProcess(componentId="graph_s4")
def process4(self, input):
    print("Processando graph_s4", input)
    if input[0] == None:
        ano = 2022
    else:
        ano = input[0]
    df = pd.read_csv(os.path.join('data', 'data-brasil-dash.csv'))
    answer = dict({
            "data": [
                {
                    "name": "IDH-Pizza",
                    "type": "pie",
                    "hole": 0.1,
                    "marker": {
                        "colors": [
                            "#F00", "#0F0", "#00F", "#FF0", "#F0F", "#0FF", "#800", "#080", "#008",
                            "#808", "#808", "#088", "#CCC", "#888", "#F70", "#FD0", "#F40", "#F55",
                            "#26B", "#82E", "#937", "#2D2", "#7F7", "#0CD", "#48B", "#D61", "#854"
                        ]
                    },
                    "hoverinfo": "all",
                    "labels": [
                        "AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO",
                        "MA", "MT", "MS", "MG", "PA", "PB", "PR", "PE", "PI",
                        "RJ", "RN", "RS", "RO", "RR", "SC", "SP", "SE", "TO"
                    ],
                    "values": df[df['ano'] == ano]['IDH']
                }
            ],
            "layout": {
                "title": "IDH por Ano (" + str(ano) + ")",
                "autosize": True
            },
            "frames": []
        })
    return answer

Após executar a aplicação consumidora (python3 main.py CONTRACT_TEST 004), uma resposta visual é exibida no dashboard do sistema após processado do process4. A imagem a seguir mostra a resposta no frontend do sistema.

Resposta Consumer Dash Sample 4

A seguir vemos a implementação do método process5. Este método representa o processamento do quinto gráfico do dashboard.

@dashProcess(componentId="graph_s5")
def process5(self, input):
    print("Processando graph_s5", input)
    if input[0] == None:
        regiao = 'Sudeste'
    else:
        regiao = input[0]
    if input[1] == None:
        ano = 2022
    else:
        ano = input[1]
    df = pd.read_csv(os.path.join('data', 'data-brasil-dash.csv'))
    filtro_ano_regiao = (df['ano'] == ano) & (df['região'] == regiao)
    vfiltro_populacao = df.loc[filtro_ano_regiao, 'população']
    vfiltro_estado = df.loc[filtro_ano_regiao, 'estado']
    answer = dict({
            "data": [
                {
                    "name": "População",
                    "type": "pie",
                    "hole": 0.1,
                    "marker": {
                        "colors": [
                            "#F00", "#0F0", "#00F", "#FF0", "#F0F", "#0FF", "#800", "#080", "#008",
                        ]
                    },
                    "hoverinfo": "all",
                    "labels": list(vfiltro_estado),
                    "values": vfiltro_populacao
                }
            ],
            "layout": {
                "title": "População por Região (" + str(regiao) + ") por Ano (" + str(ano) + ")",
                "autosize": True
            },
            "frames": []
        })
    return answer

Após executar a aplicação consumidora (python3 main.py CONTRACT_TEST 005), uma resposta visual é exibida no dashboard do sistema após processado do process5. A imagem a seguir mostra a resposta no frontend do sistema.

Resposta Consumer Dash Sample 5

A seguir vemos a implementação do método process6. Este método representa o processamento do sexto gráfico do dashboard.

@dashProcess(componentId="graph_s6")
def process6(self, input):
    print("Processando graph_s6", input)
    if input[0] == None:
        regiao = 'Sudeste'
    else:
        regiao = input[0]
    if input[1] == None:
        ano = 2022
    else:
        ano = input[1]
    df = pd.read_csv(os.path.join('data', 'data-brasil-dash.csv'))
    filtro_ano_regiao = (df['ano'] == ano) & (df['região'] == regiao)
    vfiltro_idh = df.loc[filtro_ano_regiao, 'IDH']
    vfiltro_estado = df.loc[filtro_ano_regiao, 'estado']
    answer = dict({
            "data": [
                {
                    "name": "População",
                    "type": "pie",
                    "hole": 0.1,
                    "marker": {
                        "colors": [
                            "#F00", "#0F0", "#00F", "#FF0", "#F0F", "#0FF", "#800", "#080", "#008",
                        ]
                    },
                    "hoverinfo": "all",
                    "labels": list(vfiltro_estado),
                    "values": vfiltro_idh
                }
            ],
            "layout": {
                "title": "IDH por Região (" + str(regiao) + ") por Ano (" + str(ano) + ")",
                "autosize": True
            },
            "frames": []
        })
    return answer

Após executar a aplicação consumidora (python3 main.py CONTRACT_TEST 006), uma resposta visual é exibida no dashboard do sistema após processado do process6. A imagem a seguir mostra a resposta no frontend do sistema.

Resposta Consumer Dash Sample 6

A seguir vemos a implementação do método process7. Este método representa o processamento da primeira saída de dados do dashboard. Esse método não processa nenhum gráfico, apenas define os nomes dos campos exibidos no componente checklist que é mostrado no dashboard.

@dashProcess(componentId="data_s11")
def process7(self, input):
    print("Processando data_s11", input)
    if ( input[0] == None or input[0] == 'Sul' ):
        answer = [  {"label": "PR", "value": "PR"},
                    {"label": "RS", "value": "RS"},
                    {"label": "SC", "value": "SC"}]
    elif ( input[0] == 'Sudeste' ):
        answer = [  {"label": "ES", "value": "ES"},
                    {"label": "MG", "value": "MG"},
                    {"label": "RJ", "value": "RJ"},
                    {"label": "SP", "value": "SP"}]
    elif ( input[0] == 'Centro Oeste' ):
        answer = [  {"label": "DF", "value": "DF"},
                    {"label": "GO", "value": "GO"},
                    {"label": "MT", "value": "MT"},
                    {"label": "MS", "value": "MS"}]
    elif ( input[0] == 'Norte' ):
        answer = [  {"label": "AC", "value": "AC"},
                    {"label": "AP", "value": "AP"},
                    {"label": "AM", "value": "AM"},
                    {"label": "PA", "value": "PA"},
                    {"label": "RO", "value": "RO"},
                    {"label": "RR", "value": "RR"},
                    {"label": "TO", "value": "TO"}]
    elif ( input[0] == 'Nordeste' ):
        answer = [  {"label": "AL", "value": "AL"},
                    {"label": "BA", "value": "BA"},
                    {"label": "CE", "value": "CE"},
                    {"label": "MA", "value": "MA"},
                    {"label": "PB", "value": "PB"},
                    {"label": "PE", "value": "PE"},
                    {"label": "PI", "value": "PI"},
                    {"label": "RN", "value": "RN"},
                    {"label": "SE", "value": "SE"}]
    return answer

Após executar a aplicação consumidora (python3 main.py CONTRACT_TEST 007), nenhuma resposta visual é exibida no dashboard do sistema após processado do process7. Isso ocorre, pois esse método não faz nenhum processamento gráfico, ele faz apenas o processamento dos dados baseados na região selecionada pelo usuário e retorna uma lista de opções de estados para aquela região. Analise a imagem abaixo que será gerada apenas no dashboard final do sistema quando executado junto com o portal.

Resposta Consumer Dash Sample 7

A seguir vemos a implementação do método process8. Este método representa o processamento da primeira tabela do dashboard.

@dashProcess(componentId="datatable_1")
def process8(self, input):
    print("Processando datatable_1", input)
    lista_estado = input[0]
    df = pd.read_csv(os.path.join('data', 'data-brasil-dash.csv'))

    filtro_estado = None
    if lista_estado is not None and len(lista_estado) > 0:
        filtro_estado = (df['estado'] == lista_estado[0])
        for i in range(len(lista_estado)):
            filtro_estado = filtro_estado | (df['estado'] == lista_estado[i])
    if filtro_estado is not None:
        df_filtrado = df[filtro_estado]
        data = df_filtrado.to_dict('records')
        return data
    else:
        return []

Analise a imagem abaixo que será gerada apenas no dashboard final do sistema quando executado junto com o portal.

Resposta Consumer Dash Sample 8

Essa tabela irá mostrar as informações na tela baseados nos estados selecionados. A seguir vemos a implementação do método process9. Este método representa o processamento do primeiro código markdown para ser exibido do dashboard.

@dashProcess(componentId="markdown_1")
def process9(self, input):
    print("Processando markdown_1", input)
    # Abaixo são suportados diversos comandos da linguagem markdown para estilizar a página.
    answer = f'''
            #### Breve Explicação

            Os *gráficos* e *tabelas* mostrados a seguir apresentam informações sobre a **População** e o **IDH**
            ([Índice de Desenvolvimento Humano](https://pt.wikipedia.org/wiki/%C3%8Dndice_de_Desenvolvimento_Humano))
            dos estados brasileiros para os anos de 1991, 2001, 2011 e 2022.

            > **Dica:** Utilize os campos de filtragem de dados para especificar um `estado`, `ano` ou `região` para assim alterar as informações visuais exibidas.

            > ![Ícone gráficos](https://cdn-icons-png.flaticon.com/64/2257/2257295.png)

            ___

            Exemplo de exibição de entrada de dados: {input[0]}
        '''
    return answer

Esse markdown irá mostrar informações no dashboard baseada na descrição feita em linguagem markdown. Analise a imagem abaixo que será gerada apenas no dashboard final do sistema quando executado junto com o portal.

Resposta Consumer Dash Sample 9

A seguir vemos a implementação do método process10. Este método representa o processamento da segunda tabela do dashboard.

    @dashProcess(componentId="datatable_2")
    def process10(self, input):
        print("Processando datatable_2", input)
        if input[0] == None:
            ano = 2022
        else:
            ano = input[0]
        if input[1] == None:
            idh = 0.05
        else:
            idh = input[1]
        if input[2] == None:
            lista_regiao = None
        else:
            lista_regiao = input[2]
        df = pd.read_csv(os.path.join('data', 'data-brasil-dash.csv'))

        filtro_regiao = None
        if lista_regiao is not None and len(lista_regiao) > 0:
            filtro_regiao = (df['região'] == lista_regiao[0])
            for i in range(len(lista_regiao)):
                filtro_regiao = filtro_regiao | (df['região'] == lista_regiao[i])
        if filtro_regiao is not None:
            df_filtrado = df[(df['ano'] == ano) & (df['IDH'] >= idh) & filtro_regiao]
            data = df_filtrado.to_dict('records')
            return data
        else:
            return []

Essa tabela irá mostrar as informações na tela baseadas em uma série de filtros disponíveis. Analise a imagem abaixo que será gerada apenas no dashboard final do sistema quando executado junto com o portal.

Resposta Consumer Dash Sample 10

Arquivo de Configuração env.conf

Existe um arquivo de configuração chamado env.conf na pasta conf_samples. Esse arquivo será copiado para um outro arquivo chamado env.conf na raiz do projeto no passo configurando a aplicação desse tutorial. O arquivo conf_samples/env.conf é um arquivo de exemplo que vem junto com o projeto e não deve ser alterado. O arquivo env.conf, que é uma cópia do anterior, pode ser alterado/customizado conforme a necessidade do desenvolvedor. A seguir é mostrado um exemplo desse arquivo seguido de uma breve explicação.

CONSUMER_CODE=sample
LOG_LEVEL=INFO
#LOCAL
TIME_WAIT_RESTART=10
MESSAGE_BROKER_HOST_DOCKER=host.docker.internal
MESSAGE_BROKER_PORT_DOCKER=5672
CACHE_HOST_DOCKER=host.docker.internal
CACHE_PORT_DOCKER=6379
#DOCKER
MESSAGE_BROKER_HOST=192.168.1.4
MESSAGE_BROKER_PORT=5672
MESSAGE_BROKER_USER=admin
MESSAGE_BROKER_PASSWORD=password
CACHE_HOST=192.168.1.4
CACHE_PORT=6379
#OPTIONAL
#METRICS_PORT=9091
#PORTAL_DIR=pgst-portal
#DB_NAME=postgres
#DB_USER=postgres
#DB_PASSWORD=root
#DB_HOST=localhost
#DB_PORT=5433

Os primeiros atributos são obrigatórios. O atributo CONSUMER_CODE informa o nome do código consumidor. O atributo LOG_LEVEL informa o nível de detalhes impressos no sistema de log. Os valores possíveis são: DEBUG, INFO, WARNING, ERROR e CRITICAL.

Os sete próximos atributos são opcionais. Os atributos DB_NAME, DB_USER, DB_PASSWORD, DB_HOST, DB_PORT são utilizados para estabelecer a conexão com o banco de dados do postgres, caso a aplicação integre com esse banco de dados.

Módulos para Testes

Na raiz do projeto existe uma pasta chamada tests que contém os testes de software implementados. Dentro dessa pasta terá um arquivo chamado test_001.py que define os testes para o primeiro dashboard. A seguir é mostrada uma parte do código do módulo test_001.py.

import logging
from consumer_dash.basic.service import Service

class Test001():
    logger = logging.getLogger(__name__)
    service = Service()
    def test(self):
        self.logger.info("Testando o método test do módulo test_001.py")
        service = Service()
        answer = service.test("graph_s1", ['SP'])
        assert type(answer) == dict

Repare que o código desse teste é bastante genérico. Ele basicamente cria um consumidor do tipo Service. Quando esse teste for executado, o método com componentId igual a graph_s1 será chamado. Em nosso caso, é o método com nome process1 da classe Service que possui esse componentId. Então, ele irá pegar a saída gerada e verificar se a mesma é do tipo dicionário.

Atenção: É necessário criar um teste de software por gráfico a ser plotado nas telas do dashboard.

Diretório graph_output

Na raiz do projeto tem uma pasta chamada graph_output em que ficam armazenados os arquivos com os gráficos que serão utilizados no dashboard.

Ao mandar exibir, por exemplo, o arquivo graph_graph_s1.html uma tela semelhante a mostrada a seguir deverá ser exibida.

Tela com gráfico do Dashboard

Esses gráficos em HTML são criados quando executamos os comandos de testes de contrato da seção Executando a Aplicação em Modo Teste.

Arquivo dashboards.json

Na raiz do projeto tem um arquivo chamado dashboards.json que contém arquivos de configurações importantes em formato JSON. Esses arquivos definem uma série de parâmetros sobre o consumidor de dashboards.

A seguir temos um exemplo de arquivo dashboards.json (apenas uma parte) com as configurações de como montar os dashboards.

Arquivo: dashboards.json
{
    "id": "dash_3",
    "version": 1.0,
    "project_title": "Projeto 2",
    "role_tag": "DASH03",
    "title": "DashBoard - Exemplos - Informações do Brasil",
    "description": "Este painel mostra diferentes informações sobre o Brasil.",
    "consumer_id":"sample",
    "components": [
        {
            "type": "div",
            "components": [
                {
                    "type": "markdown",
                    "id": "markdown_1"
                }
            ]
        },
        {
            "type": "div",
            "style": {
                "width": "49%",
                "display": "inline-block",
                "marginRight": "10px"
            },
            "components": [
                {
                    "type": "dropdown",
                    "title": "Filtro - Selecione um Estado",
                    "id": "data_s1",
                    "properties": {
                        "options": [
                            {
                                "label": "AC",
                                "value": "AC"
                            },
                            ...
                            {
                                "label": "TO",
                                "value": "TO"
                            }
                        ],
                        "default": "MG"
                    }
                },
                {
                    "type": "graph",
                    "id": "graph_s1",
                    "help": "This parameter is not necessary, is just for documentation purposes. consumer_id is the queue name and graph_s1 is the function name. The Hardcoded mode only return from consumer_id queue."
                }
            ]
        },
        {
            "type": "div",
            "style": {
                "width": "49%",
                "display": "inline-block"
            },
            "components": [
                {
                    "type": "dropdown",
                    "title": "Filtro - Selecione um Estado",
                    "id": "data_s2",
                    "properties": {
                        "options": [
                            {
                                "label": "AC",
                                "value": "AC"
                            },
                            ...
                            {
                                "label": "TO",
                                "value": "TO"
                            }
                        ],
                        "default": "MG"
                    }
                },
                {
                    "type": "graph",
                    "id": "graph_s2"
                }
            ]
        },
        {
            "type": "div",
            "style": {
                "width": "49%",
                "display": "inline-block",
                "marginRight": "10px"
            },
            "components": [
                {
                    "type": "dropdown",
                    "title": "Filtro - Selecione um Ano",
                    "id": "data_s3",
                    "properties": {
                        "options": [
                            {
                                "label": "1991",
                                "value": 1991
                            },
                            ...
                            {
                                "label": "2022",
                                "value": 2022
                            }
                        ],
                        "default": 2022
                    }
                },
                {
                    "type": "graph",
                    "id": "graph_s3"
                }
            ]
        },
        {
            "type": "div",
            "style": {
                "width": "49%",
                "display": "inline-block"
            },
            "components": [
                {
                    "type": "dropdown",
                    "title": "Filtro - Selecione um Ano",
                    "id": "data_s4",
                    "properties": {
                        "options": [
                            {
                                "label": "1991",
                                "value": 1991
                            },
                            ...
                            {
                                "label": "2022",
                                "value": 2022
                            }
                        ],
                        "default": 2022
                    }
                },
                {
                    "type": "graph",
                    "id": "graph_s4"
                }
            ]
        },
        {
            "type": "div",
            "style": {
                "width": "100%",
                "display": "inline-block"
            },
            "components": [
                {
                    "type": "dropdown",
                    "title": "Filtro - Selecione uma Região",
                    "id": "data_s5",
                    "properties": {
                        "options": [
                            {
                                "label": "Centro Oeste",
                                "value": "Centro Oeste"
                            },
                            ...
                            {
                                "label": "Sul",
                                "value": "Sul"
                            }
                        ],
                        "default": "Sudeste"
                    }
                },
                {
                    "type": "dropdown",
                    "title": "Filtro - Selecione um Ano",
                    "id": "data_s6",
                    "properties": {
                        "options": [
                            {
                                "label": "1991",
                                "value": 1991
                            },
                            ...
                            {
                                "label": "2022",
                                "value": 2022
                            }
                        ],
                        "default": 2022
                    }
                }
            ]
        },
        {
            "type": "div",
            "style": {
                "width": "49%",
                "display": "inline-block",
                "marginRight": "10px"
            },
            "components": [
                {
                    "type": "graph",
                    "id": "graph_s5"
                }
            ]
        },
        {
            "type": "div",
            "style": {
                "width": "49%",
                "display": "inline-block"
            },
            "components": [
                {
                    "type": "graph",
                    "id": "graph_s6"
                }
            ]
        },
        {
            "type": "div",
            "style": {
                "width": "100%",
                "display": "inline-block"
            },
            "components": [
                {
                    "type": "dropdown",
                    "title": "Filtro - Selecione uma Região",
                    "id": "data_s7",
                    "properties": {
                        "options": [
                            {
                                "label": "Centro Oeste",
                                "value": "Centro Oeste"
                            },
                            ...
                            {
                                "label": "Sul",
                                "value": "Sul"
                            }
                        ],
                        "default": "Sul"
                    }
                },
                {
                    "type": "checklist",
                    "title": "Filtro - Selecione um Estado",
                    "id": "data_s11",
                    "properties": {
                        "options": [],
                        "default" :[],
                        "help": "This (options) should be empty in dynamic inputs, and the name of component should starts with ",
                        "style": {
                            "display": "inline-block",
                            "marginTop": "5px"
                        }
                    }
                },
                {
                    "type": "datatable",
                    "id": "datatable_1"
                }
            ]
        },
        {
            "type": "div",
            "style": {
                "width": "100%",
                "display": "inline-block"
            },
            "components": [
                {
                    "type": "dropdown",
                    "title": "Filtro - Selecione um Ano",
                    "id": "data_s8",
                    "properties": {
                        "options": [
                            {
                                "label": "1991",
                                "value": 1991
                            },
                            ...
                            {
                                "label": "2022",
                                "value": 2022
                            }
                        ],
                        "default": 2022
                    }
                },
                {
                    "type": "slider",
                    "title": "Filtro - Selecione um IDH",
                    "id": "data_s9",
                    "properties": {
                        "begin": 0.0,
                        "end": 1.0,
                        "step": 0.05,
                        "value": 0.5
                    }
                },
                {
                    "type": "checklist",
                    "title": "Filtro - Selecione uma Região",
                    "id": "data_s10",
                    "properties": {
                        "options": ["Centro Oeste", "Nordeste", "Norte", "Sudeste", "Sul"],
                        "default" : ["Sudeste", "Norte"],
                        "style": {
                            "marginTop": "5px"
                        }
                    }
                },
                {
                    "type": "datatable",
                    "id": "datatable_2"
                }
            ]
        }
    ],
    "callbacks": [
        {
            "outputs": [
                "markdown_1"
            ],
            "inputs": [
                "data_s1"
            ]
        },
        {
            "outputs": [
                "graph_s1"
            ],
            "inputs": [
                "data_s1"
            ],
            "help": "This parameter is not necessary, is just for documentation purposes. It is not possible to have two callbacks with the same outputs."
        },
        {
            "outputs": [
                "graph_s2"
            ],
            "inputs": [
                "data_s2"
            ]
        },
        {
            "outputs": [
                "graph_s3"
            ],
            "inputs": [
                "data_s3"
            ]
        },
        {
            "outputs": [
                "graph_s4"
            ],
            "inputs": [
                "data_s4"
            ]
        },
        {
            "outputs": [
                "graph_s5",
                "graph_s6"
            ],
            "inputs": [
                "data_s5",
                "data_s6"
            ]
        },
        {
            "outputs": [
                "data_s11"
            ],
            "inputs": [
                "data_s7"
            ]
        },
        {
            "outputs": [
                "datatable_1"
            ],
            "inputs": [
                "data_s11"
            ]
        },
        {
            "outputs": [
                "datatable_2"
            ],
            "inputs": [
                "data_s8",
                "data_s9",
                "data_s10"
            ]
        }
    ]
}

Nesse arquivo é importante destacar os seguintes atributos:

  • id: denota um identificador do dashboard.
  • version: denota a versão do dashboard.
  • project_title: denota o título do projeto ao qual o dashboard está vinculado.
  • role_tag: é utilizado para dar permissões de acesso ao dashboard.
  • title: é utilizado para exibir um título na interface do portal.
  • description: é utilizado para especificar uma descrição para o dashboard exibida na interface do portal.
  • components: é utilizado para especificar todos os elementos gráficos que apareceram no dashboard. Informando como será o layout de exibição os tipos de entrada e os tipos de saída.
  • callbacks: é utilizado para relacionar as entradas e saídas dos gráficos.

Instalação

Para a execução do consumidor de dashboard sample, é necessário preparar o ambiente com as ferramentas adequadas. Abaixo, apresentamos um passo a passo sucinto para instalação e configuração.

Pré-Requisitos

Para que o Consumer-Dash-Sample funcione corretamente, é necessário atender aos seguintes pré-requisitos:

  • Python
  • Pip
  • Git
  • Postgres
  • Postgis
  • Docker Desktop

Além disso, alguns subprojetos do GeoProcess também são necessários. Para isso, clone os seguintes repositórios:

  • pgst-portal
git clone https://github.com/ZETTA-ORG/pgst-portal.git
  • pgst-lib
git clone https://github.com/ZETTA-ORG/pgst-lib.git

Após a instalação dos pré-requisitos, você poderá preparar o Consumer-Dash-Sample.

Preparando a Aplicação

Primeiramente, clone o projeto pgst-consumer-dash-sample com o seguinte comando:

git clone https://github.com/ZETTA-ORG/pgst-consumer-dash-sample.git

Observação

Esse projeto deve ser clonado dentro de uma pasta geoprocess, conforme a organização do projeto.

Configurando a Aplicação

Em seguida, copie o arquivo de configuração do ambiente com o comando apropriado para o seu sistema operacional:

cp conf_samples/env.conf env.conf
copy conf_samples/env.conf env.conf

Depois, abra o arquivo env.conf e atualize-o conforme as configurações do seu ambiente de trabalho.

Para isolar as dependências do Python, crie um ambiente virtual venv com o comando a seguir:

python3 -m venv venv
py -m venv venv

Ative o ambiente virtual no seu computador utilizando o comando abaixo:

source venv/bin/activate
venv\Scripts\activate

Agora, instale as dependências do projeto utilizando o comando abaixo:

pip3 install -r requirements.txt

Em seguida, instale as dependências do projeto pgst-lib dentro do projeto principal:

pip3 install -e ../pgst-lib/

Executando a Aplicação em Modo Teste

Para executar a aplicação em modo teste unitário, utilize a linha de comando abaixo:

cd pgst-consumer-dash-sample/
source venv/bin/activate
python3 main.py UNIT_TEST

Para executar a aplicação em modo teste de contrato, utilize a linha de comando abaixo:

cd pgst-consumer-dash-sample/
source venv/bin/activate
python3 main.py CONTRACT_TEST 001

Após isso, a saída será gerada no diretório graph_output. Abra os exemplos html dessa pasta utilizando algum servidor web, como o Live Server http://127.0.0.1:5500/graph_output/graph_graph_s1.html.

Uma tela semelhante a mostrada a seguir deverá ser exibida.

Tela com gráfico do Dashboard

Informação

Para encerrar a execução do consumidor, basta apertar o botão x ou pressionar Ctrl + C.

Executando a Aplicação junto com Portal

Para executar a aplicação, primeiro é necessário abrir o Docker Desktop e subir o Postgis, pgAdmin e o Redis.

Em um terminal, execute o Consumer-Dash-Sample.

cd pgst-consumer-dash-sample/
source venv/bin/activate
cd consumer_dash/
python3 manage.py dash_service

Em seguida, acesse a URL http://0.0.0.0:8000/. Vá em Projeto 2 e em Painéis vá em DashBoard - Exemplos - Informações do Brasil. Repare agora que os gráficos estão sendo exibidos.

Tela do Portal com Dashboard 2 Tela do Portal com Dashboard 3 Tela do Portal com Dashboard 3 Tela do Portal com Dashboard 3

Visualizando os Resultados

Para visualizar os resultados digite:

cd pgst-consumer-dash-sample/
source venv/bin/activate
python3 main.py DASH_DEBUG

Acesse a URL http://0.0.0.0:8050/.

Github do Projeto

A seguir temos o link para o github do projeto.

CONSUMER-DASH-SAMPLE