Crie gráficos dinamicamente no Google Earth Engine

Iago Mendes
OLAB Learning
Published in
5 min readFeb 9, 2024

Neste post, veremos como aproveitar os componentes do pacote ui para criar gráficos dinamicamente no Google Earth Engine (GEE).

Inspirado no curso “Creating Publication Quality Charts with GEE” da Spatial Thoughts, este artigo tem como objetivo apresentar um método alternativo para definir as opções de configuração de gráficos no Code Editor, uma abordagem que não apenas simplifica o processo de criação de gráficos de alta qualidade, mas que também oferece maior flexibilidade e controle sobre a visualização dos dados. Você pode acessar o material do curso clicando aqui.

Podemos dividir a abordagem proposta neste artigo nas seguintes etapas:

  1. Preparando o ambiente.
  2. Criação de uma pseudo-DataTable.
  3. Identificação da opção de configuração a ser alterada.
  4. Verificação do intervalo de valores possíveis para a opção escolhida.
  5. Criação de um componente que será utilizado para interagir diretamente com o objeto de configuração do gráfico.
  6. Definição de uma função de callback, que será acionada sempre que o valor do componente for alterado.

Preparando o ambiente

Primeiramente, criaremos dois painéis, que a princípio estarão vazios:

  • chartPanel: usado para acomodar o gráfico.
  • controlPanel: usado para organizar os componentes.
var chartPanel = ui.Panel({ style: { position: 'top-center' } });
var controlPanel = ui.Panel({ style: { position: 'middle-left' } });

Map.add(chartPanel);
Map.add(controlPanel);

Criação de uma pseudo-DataTable

No contexto do GEE, uma DataTable (ou pseudo-DataTable) é uma estrutura de dados que pode ser representada tanto por um array de duas dimensões quanto por um objeto literal JS. Em ambos os casos, a DataTable deve ser um objeto client-side.

Saiba mais: DataTable Class

Para fins de simplificação, usaremos a mesma DataTable utilizada na seção 4.1 DataTable Charts do curso.

var dataTable = {
cols: [
{ id: 'language', label: 'Programming Language', type: 'string' },
{ id: 'responses', label: 'Number of Responses', type: 'number' },
{ id: 'percentage', label: 'Percentage', type: 'number', role: 'annotation' },
{ id: 'style', label: 'Style', type: 'string', role: 'style' },
],
rows: [
{ c: [{ v: 'Python' }, { v: 178 }, { v: 77.1 }, { v: 'color: #8dd3c7' }] },
{ c: [{ v: 'R' }, { v: 102 }, { v: 44.2 }, { v: 'color: #ffffb3' }] },
{ c: [{ v: 'Javascript' }, { v: 59 }, { v: 25.5 }, { v: 'color: #bebada' }] },
{ c: [{ v: 'Fortran' }, { v: 37 }, { v: 16 }, { v: 'color: #fb8072' }] },
{ c: [{ v: 'Java' }, { v: 32 }, { v: 13.9 }, { v: 'color: #80b1d3' }] },
{ c: [{ v: 'C++' }, { v: 27 }, { v: 11.7 }, { v: 'color: #fdb462' }] },
{ c: [{ v: 'C' }, { v: 18 }, { v: 7.8 }, { v: 'color: #b3de69' }] },
{ c: [{ v: 'PHP' }, { v: 14 }, { v: 6.1 }, { v: 'color: #fccde5' }] },
{ c: [{ v: 'Julia' }, { v: 6 }, { v: 2.6 }, { v: 'color: #d9d9d9' }] },
{ c: [{ v: 'Scala' }, { v: 3 }, { v: 1.3 }, { v: 'color: #bc80bd' }] },
],
};

Identificação da opção de configuração a ser alterada

Para cada tipo de gráfico, existem dezenas de opções de configuração que podem ser ajustadas. Trabalharemos neste artigo com um gráfico do tipo BarChart, e iremos ajustar as configurações chartArea.left, chartArea.top, chartArea.width e chartArea.height.

Verificação do intervalo de valores possíveis para a opção escolhida

Na tabela de opções de configurações, podemos obter algumas informações importantes, como o tipo de dado que a opção requer e em quais unidades podemos fornecê-las.

Utilizaremos a porcentagem em vez de pixels, pois assim podemos trabalhar com o intervalo padronizado de 0 a 100.

Criação de um componente que será utilizado para interagir diretamente com o objeto de configuração do gráfico

Primeiramente criaremos um objeto literal JS que armazenará as opções de configuração do nosso gráfico.

var options = {
title: 'Use of Programming Languages by Users of Big Earth Data'
};

Depois, criaremos um ui.Slider para cada opção que iremos ajustar.

var chartAreaLeft = ui.Slider(0, 100, 0, 1);
var chartAreaTop = ui.Slider(0, 100, 0, 1);
var chartAreaWidth = ui.Slider(0, 100, 0, 1);
var chartAreaHeight = ui.Slider(0, 100, 0, 1);

Nota: se estivéssemos trabalhando com opções de configuração booleanas, poderíamos utilizar um ui.Checkbox; se fosse uma opção que recebe uma string com o nome ou código hexadecimal de uma cor, poderíamos utilizar um ui.Textbox.

Definição de uma função de callback, que será acionada sempre que o valor do componente for alterado

Para cada opção, criaremos uma função que:

  • Adiciona a opção no objeto optionscaso ela não exista.
  • Atualiza o valor da propriedade a partir do valor do componente.
  • Chama a função drawChart, responsável por recriar e atualizar o gráfico no painel chartPanel.
var drawChart = function() {
var chart = ui.Chart(dataTable, 'BarChart', options);
chartPanel.widgets().reset([chart]);
};

var updateChartAreaLeft = function(value) {
if (!options.chartArea) options.chartArea = {};
options.chartArea.left = value + '%';
drawChart();
};

var updateChartAreaTop = function(value) {
if (!options.chartArea) options.chartArea = {};
options.chartArea.top = value + '%';
drawChart();
};

var updateChartAreaWidth = function(value) {
if (!options.chartArea) options.chartArea = {};
options.chartArea.width = value + '%';
drawChart();
};

var updateChartAreaHeight = function(value) {
if (!options.chartArea) options.chartArea = {};
options.chartArea.height = value + '%';
drawChart();
};

Podemos organizar todas as informações — componentes e funções de callback — em um array de objetos, e usar o forEach para realizar a composição do controlPanel.

var components = [
{
widget: chartAreaLeft,
callback: updateChartAreaLeft,
name: 'chartArea.left',
},
{
widget: chartAreaTop,
callback: updateChartAreaTop,
name: 'chartArea.top',
},
{
widget: chartAreaWidth,
callback: updateChartAreaWidth,
name: 'chartArea.width',
},
{
widget: chartAreaHeight,
callback: updateChartAreaHeight,
name: 'chartArea.height',
},
];


var populateControlPanel = function (components) {
var widget = components.widget;
var callback = components.callback;
var name = components.name;

var nameLabel = ui.Label(name, {
textAlign: 'right',
stretch: 'horizontal',
});

widget.onSlide(callback);
widget.style().set('width', '150px');

var innerPanel = ui.Panel([nameLabel, widget]);
innerPanel.setLayout(ui.Panel.Layout.flow('horizontal'));

controlPanel.widgets().add(innerPanel);
};

components.forEach(populateControlPanel);

O resultado será este:

Neste script você consegue acessar uma versão mais completa desse exercício, com mais opções já definidas.

Dúvidas? Encontrou algum erro? Sinta-se à vontade para deixar suas perguntas e considerações nos comentários.

Siga @olablearning

--

--