Wykresy graficzne

Moduł ui.Chart.image zawiera zestaw funkcji służących do grupowania obiektów Image według regionów i tworzenia wykresów na podstawie wyników. Wybór funkcji determinuje rozmieszczenie danych na wykresie, czyli to, co definiuje wartości osi X i Y oraz co definiuje serię. Korzystając z opisów i przykładów podanych niżej, wybierz najlepszą funkcję i typ wykresu do swoich potrzeb.

Funkcje wykresu

Aby zrozumieć, jak każda funkcja porządkuje wyniki funkcji zmniejszania regionu obrazu na wykresie, czyli jakie elementy definiują wartości x, wartości y i serie, skorzystaj z podanych niżej diagramów.

ui.Chart.image.byRegion

Obszary redukcji są nanoszone na osi X i oznaczone wartościami wybranej właściwości funkcji. Seria jest definiowana przez nazwy pasm, których wyniki redukcji regionu są nanoszone na osi y.

ui.Chart.image.regions

Pasy są nanoszone na osi x. Serie są oznaczane wartościami właściwości funkcji. Zmniejszenie obszaru zdefiniowanego przez geometrię odpowiednich elementów serii, które są nanoszone wzdłuż osi y.

ui.Chart.image.byClass

Paski danych są nanoszone wzdłuż osi X. Seria jest reprezentowana przez unikalne wartości w paśmie klasy. Pozycja na osi Y jest definiowana przez wyniki redukcji regionu w przypadku pikseli tworzących poszczególne serie.

ui.Chart.image.histogram

Częstotliwość występowania wartości w wybranych pasmach.

  • Oś X: zbiory danych histogramu odpowiadające wartościom wybranych pasm
  • Oś Y: częstotliwość występowania pikseli kwalifikujących się do poszczególnych zbiorów histogramu

Przykładowe dane

Poniższe przykłady opierają się na pliku FeatureCollection, który składa się z 3 cech ekoregionu definiujących regiony, w których mają być zmniejszane dane obrazu. Dane Image to normalne wartości klimatu PRISM, gdzie pasma opisują zmienne klimatyczne w poszczególnych miesiącach, np. opady w lipcu lub średnia temperatura w styczniu. Dowiedz się, jak utworzono ten komponent

ui.Chart.image.byRegion

Wykres kolumnowy

W tym przykładzie pasy obrazu przedstawiające średnią temperaturę miesięczną są zmniejszane do średniej z pikseli przecinających się z każdym z 3 ekoregionów. Wyniki są przedstawiane jako kolumny na miesiąc według ekoregionu, a wysokość kolumny wskazuje średnią temperaturę miesięczną.

Edytor kodu (JavaScript)

// Import the example feature collection.
var ecoregions = ee.FeatureCollection('projects/google/charts_feature_example');

// Load PRISM climate normals image collection; convert images to bands.
var normClim = ee.ImageCollection('OREGONSTATE/PRISM/Norm81m').toBands();

// Define the chart and print it to the console.
var chart =
    ui.Chart.image
        .byRegion({
          image: normClim.select('[0-9][0-9]_tmean'),
          regions: ecoregions,
          reducer: ee.Reducer.mean(),
          scale: 500,
          xProperty: 'label'
        })
        .setSeriesNames([
          'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
          'Nov', 'Dec'
        ])
        .setChartType('ColumnChart')
        .setOptions({
          title: 'Average Monthly Temperature by Ecoregion',
          hAxis:
              {title: 'Ecoregion', titleTextStyle: {italic: false, bold: true}},
          vAxis: {
            title: 'Temperature (°C)',
            titleTextStyle: {italic: false, bold: true}
          },
          colors: [
            '604791', '1d6b99', '39a8a7', '0f8755', '76b349', 'f0af07',
            'e37d05', 'cf513e', '96356f', '724173', '9c4f97', '696969'
          ]
        });
print(chart);

Wykres słupkowy

Poprzedni wykres kolumnowy można wyświetlić jako wykres słupkowy, zmieniając w wejściu .setChartType() wartość 'ColumnChart' na 'BarChart'.

var chart =
    ui.Chart.image
        .byRegion({
          image: normClim.select('[0-9][0-9]_tmean'),
          regions: ecoregions,
          reducer: ee.Reducer.mean(),
          scale: 500,
          xProperty: 'label'
        })
        .setSeriesNames([
          'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
          'Nov', 'Dec'
        ])
        .setChartType('BarChart')
        .setOptions({
          title: 'Average Monthly Temperature by Ecoregion',
          hAxis: {
            title: 'Temperature (°C)',
            titleTextStyle: {italic: false, bold: true}
          },
          vAxis:
              {title: 'Ecoregion', titleTextStyle: {italic: false, bold: true}},
          colors: [
            '604791', '1d6b99', '39a8a7', '0f8755', '76b349', 'f0af07',
            'e37d05', 'cf513e', '96356f', '724173', '9c4f97', '696969'
          ]
        });

Skumulowany wykres kolumnowy

Opcja wykresu isStacked określa, czy kolumny wykresu mają być ułożone w stosie. Dostępnych jest kilka opcji dotyczących nakładania. Poniższe przykłady pokazują, jak używać opcji 'absolute''relative'.

Bezwzględna

Skumulowany wykres słupkowy bezwzględny porównuje sumę zmiennej liczbowej z przyrostami serii zmiennej kategorialnej. Na przykład w tym przykładzie łączne opady są przedstawiane jako suma miesięcznych opadów w danym roku według ekoregionu. Łączne opady w danym miesiącu są uzyskiwane z pasm obrazów, gdzie każdy pas reprezentuje siatkę średnich opadów w danym miesiącu, zredukowaną do średniej z pikseli przecinających się z każdym z 3 ekoregionów. Aby sformatować wyniki jako wartości bezwzględne, opcja wykresu isStacked jest ustawiona na 'absolute'.

Edytor kodu (JavaScript)

// Import the example feature collection.
var ecoregions = ee.FeatureCollection('projects/google/charts_feature_example');

// Load PRISM climate normals image collection; convert images to bands.
var normClim = ee.ImageCollection('OREGONSTATE/PRISM/Norm81m').toBands();

// Define the chart and print it to the console.
var chart =
    ui.Chart.image
        .byRegion({
          image: normClim.select('[0-9][0-9]_ppt'),
          regions: ecoregions,
          reducer: ee.Reducer.mean(),
          scale: 500,
          xProperty: 'label'
        })
        .setSeriesNames([
          'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
          'Nov', 'Dec'
        ])
        .setChartType('ColumnChart')
        .setOptions({
          title: 'Average Monthly Precipitation by Ecoregion',
          hAxis:
              {title: 'Ecoregion', titleTextStyle: {italic: false, bold: true}},
          vAxis: {
            title: 'Precipitation (mm)',
            titleTextStyle: {italic: false, bold: true}
          },
          colors: [
            '604791', '1d6b99', '39a8a7', '0f8755', '76b349', 'f0af07',
            'e37d05', 'cf513e', '96356f', '724173', '9c4f97', '696969'
          ],
          isStacked: 'absolute'
        });
print(chart);

Krewny

Przekształć poprzedni bezwzględny wykres słupkowy z wartościami skumulowanymi na wykres słupkowy z wartościami skumulowanymi względnymi, zmieniając opcję isStacked'absolute' na 'relative'. Wykres słupkowy z względnym ułożeniem słupków przedstawia stosunek serii zmiennych porządkowych do sumy zmiennej liczbowej. Na przykład w tym przykładzie opady miesięczne są przedstawiane jako ułamek łącznych rocznych opadów w poszczególnych ekoregionach.

var chart =
    ui.Chart.image
        .byRegion({
          image: normClim.select('[0-9][0-9]_ppt'),
          regions: ecoregions,
          reducer: ee.Reducer.mean(),
          scale: 500,
          xProperty: 'label'
        })
        .setSeriesNames([
          'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
          'Nov', 'Dec'
        ])
        .setChartType('ColumnChart')
        .setOptions({
          title: 'Average Monthly Precipitation by Ecoregion',
          hAxis:
              {title: 'Ecoregion', titleTextStyle: {italic: false, bold: true}},
          vAxis: {
            title: 'Precipitation (mm)',
            titleTextStyle: {italic: false, bold: true}
          },
          colors: [
            '604791', '1d6b99', '39a8a7', '0f8755', '76b349', 'f0af07',
            'e37d05', 'cf513e', '96356f', '724173', '9c4f97', '696969'
          ],
          isStacked: 'relative'
        });

Wykres rozproszony

Średnie temperatury w styczniu i lipcu dla losowej próby lokalizacji w stanie Kolorado są przedstawione jako funkcja wysokości. DEM jest próbkowany za pomocą funkcji sample, która zwraca FeatureCollection z właściwością geometryczną i wysokości. Uzyskana wartość FeatureCollection jest następnie używana jako argument parametru regions funkcji ui.Chart.image.byRegion. Serie są definiowane przez wybrane pasma obrazu danych wejściowych normalnych wartości klimatycznych.

Edytor kodu (JavaScript)

// Load SRTM elevation data.
var elev = ee.Image('CGIAR/SRTM90_V4').select('elevation');

// Subset Colorado from the TIGER States feature collection.
var colorado = ee.FeatureCollection('TIGER/2018/States')
                   .filter(ee.Filter.eq('NAME', 'Colorado'));

// Draw a random sample of elevation points from within Colorado.
var samp = elev.sample(
    {region: colorado, scale: 30, numPixels: 500, geometries: true});

// Load PRISM climate normals image collection; convert images to bands.
var normClim = ee.ImageCollection('OREGONSTATE/PRISM/Norm81m').toBands();

// Define the chart and print it to the console.
var chart = ui.Chart.image
                .byRegion({
                  image: normClim.select(['01_tmean', '07_tmean']),
                  regions: samp,
                  reducer: ee.Reducer.mean(),
                  scale: 500,
                  xProperty: 'elevation'
                })
                .setSeriesNames(['Jan', 'Jul'])
                .setChartType('ScatterChart')
                .setOptions({
                  title: 'Average Monthly Colorado Temperature by Elevation',
                  hAxis: {
                    title: 'Elevation (m)',
                    titleTextStyle: {italic: false, bold: true}
                  },
                  vAxis: {
                    title: 'Temperature (°C)',
                    titleTextStyle: {italic: false, bold: true}
                  },
                  pointSize: 4,
                  dataOpacity: 0.6,
                  colors: ['1d6b99', 'cf513e'],
                });
print(chart);

Wykres kombi

W przypadku 3 ekoregionów w ee.FeatureCollection przedstawiono średnią temperaturę i opady w czerwcu. Wyniki pochodzą z redukcji regionu obrazu, w którym każdy pasek to siatka normalnych wartości klimatycznych opisujących opady i temperaturę miesięczną; paski reprezentujące temperaturę i opady w czerwcu stanowią podzbiór. Ponieważ opady i temperatura są podawane w różnych jednostkach, 2 osi Y są używane przez ustawienia opcji seriesvAxes. Zwróć uwagę na użycie opcji series.targetAxisIndex, aby określić, która zmienna ma być nanoszona na prawą i lewą oś Y. Symbole związane z poszczególnymi seriami (punkty i kolumny) ułatwiają odróżnienie tych 2 zmiennych, które mają różne jednostki.

Edytor kodu (JavaScript)

// Import the example feature collection.
var ecoregions = ee.FeatureCollection('projects/google/charts_feature_example');

// Load PRISM climate normals image collection; convert images to bands.
var normClim = ee.ImageCollection('OREGONSTATE/PRISM/Norm81m').toBands();

// Define the chart and print it to the console.
var chart =
    ui.Chart.image
        .byRegion({
          image: normClim.select(['06_tmean', '06_ppt']),
          regions: ecoregions,
          reducer: ee.Reducer.mean(),
          scale: 500,
          xProperty: 'label'
        })
        .setSeriesNames(['Precipitation', 'Temperature'])
        .setChartType('ColumnChart')
        .setOptions({
          title: 'Average June Temperature and Precipitation by Ecoregion',
          series: {
            0: {targetAxisIndex: 1, type: 'bar', color: '1d6b99'},
            1: {
              targetAxisIndex: 0,
              type: 'line',
              lineWidth: 0,
              pointSize: 10,
              color: 'e37d05'
            }
          },
          hAxis:
              {title: 'Ecoregion', titleTextStyle: {italic: false, bold: true}},
          vAxes: {
            0: {
              title: 'Temperature (°C)',
              baseline: 0,
              titleTextStyle: {italic: false, bold: true, color: 'e37d05'}
            },
            1: {
              title: 'Precipitation (mm)',
              titleTextStyle: {italic: false, bold: true, color: '1d6b99'}
            },
          },
          bar: {groupWidth: '40%'},
        });
print(chart);

ui.Chart.image.regions

Przykładowa konfiguracja

Funkcja ui.Chart.image.regions przyjmuje listę, która umożliwia kontrolowanie etykiety i kolejności nazw zespołów wzdłuż osi X poprzez przypisywanie im wartości liczbowych. Na wykresach poniżej nazwy pasm są używane jako etykiety miesięcy i uporządkowane chronologicznie według średnich miesięcznych opadów.

Wykres kolumnowy

Ten wykres pokazuje łączną średnią ilość opadów w danym miesiącu w 3 ekoregionach. Wyniki pochodzą z regionalnego zmniejszenia obrazu, w którym każdy pas jest siatką średnich łącznych opadów w danym miesiącu. Pasy są nanoszone wzdłuż osi x, a regiony definiują serię. Zwróć uwagę na operacje po stronie klienta, które służą do definiowania danych wejściowych opcji wykresu xLabelsticks w celu niestandardowego układu osi X. Operacje po stronie klienta są wymagane, ponieważ opcje podawane funkcji setOptions muszą być obiektami po stronie klienta (aby zrozumieć tę różnicę, zapoznaj się z artykułem Po stronie klienta a po stronie serwera). Aby przekształcić wykres w wykres słupkowy, użyj wartości 'BarChart' jako wartości wejściowej .setChartType().

Edytor kodu (JavaScript)

// Import the example feature collection.
var ecoregions = ee.FeatureCollection('projects/google/charts_feature_example');

// Load PRISM climate normals image collection, convert images to bands, and
// subset precipitation bands.
var precip = ee.ImageCollection('OREGONSTATE/PRISM/Norm81m')
                 .toBands()
                 .select('[0-9][0-9]_ppt');

// Define a dictionary that associates band names with values and labels.
var precipInfo = {
  '01_ppt': {v: 1, f: 'Jan'},
  '02_ppt': {v: 2, f: 'Feb'},
  '03_ppt': {v: 3, f: 'Mar'},
  '04_ppt': {v: 4, f: 'Apr'},
  '05_ppt': {v: 5, f: 'May'},
  '06_ppt': {v: 6, f: 'Jun'},
  '07_ppt': {v: 7, f: 'Jul'},
  '08_ppt': {v: 8, f: 'Aug'},
  '09_ppt': {v: 9, f: 'Sep'},
  '10_ppt': {v: 10, f: 'Oct'},
  '11_ppt': {v: 11, f: 'Nov'},
  '12_ppt': {v: 12, f: 'Dec'}
};

// Organize precipitation information into objects for defining x values and
// their tick labels. Note that chart options provided to the .setOptions()
// function must be client-side objects, which is why a client-side for
// loop is used to iteratively populate lists from the above dictionary.
var xPropVals = [];    // List to codify x-axis band names as values.
var xPropLabels = [];  // Holds dictionaries that label codified x-axis values.
for (var key in precipInfo) {
  xPropVals.push(precipInfo[key].v);
  xPropLabels.push(precipInfo[key]);
}

// Define the chart and print it to the console.
var chart = ui.Chart.image
                .regions({
                  image: precip,
                  regions: ecoregions,
                  reducer: ee.Reducer.mean(),
                  scale: 5e3,
                  seriesProperty: 'label',
                  xLabels: xPropVals
                })
                .setChartType('ColumnChart')
                .setOptions({
                  title: 'Average Ecoregion Precipitation by Month',
                  hAxis: {
                    title: 'Month',
                    titleTextStyle: {italic: false, bold: true},
                    ticks: xPropLabels
                  },
                  vAxis: {
                    title: 'Precipitation (mm)',
                    titleTextStyle: {italic: false, bold: true}
                  },
                  colors: ['f0af07', '0f8755', '76b349'],
                });
print(chart);

Wykres liniowy

Poprzedni wykres kolumnowy można wyświetlić jako wykres liniowy, zmieniając wartość parametru .setChartType()'ColumnChart' na 'LineChart'.

var chart = ui.Chart.image
                .regions({
                  image: precip,
                  regions: ecoregions,
                  reducer: ee.Reducer.mean(),
                  scale: 500,
                  seriesProperty: 'label',
                  xLabels: xPropVals
                })
                .setChartType('LineChart')
                .setOptions({
                  title: 'Average Ecoregion Precipitation by Month',
                  hAxis: {
                    title: 'Month',
                    titleTextStyle: {italic: false, bold: true},
                    ticks: xPropLabels
                  },
                  vAxis: {
                    title: 'Precipitation (mm)',
                    titleTextStyle: {italic: false, bold: true}
                  },
                  colors: ['f0af07', '0f8755', '76b349'],
                  lineSize: 5
                });

Wykres warstwowy

Poprzedni wykres kolumnowy można wyświetlić jako wykres warstwowy, zmieniając wartość parametru .setChartType()'ColumnChart' na 'AreaChart'.

var chart = ui.Chart.image
                .regions({
                  image: precip,
                  regions: ecoregions,
                  reducer: ee.Reducer.mean(),
                  scale: 500,
                  seriesProperty: 'label',
                  xLabels: xPropVals
                })
                .setChartType('AreaChart')
                .setOptions({
                  title: 'Average Ecoregion Precipitation by Month',
                  hAxis: {
                    title: 'Month',
                    titleTextStyle: {italic: false, bold: true},
                    ticks: xPropLabels
                  },
                  vAxis: {
                    title: 'Precipitation (mm)',
                    titleTextStyle: {italic: false, bold: true}
                  },
                  colors: ['f0af07', '0f8755', '76b349'],
                  lineSize: 5
                });

Wykres kołowy

Średnie miesięczne opady są wyświetlane jako ułamek średniej łącznej rocznej sumy opadów w danym ekoregionie leśnym. Pasma obrazów przedstawiające opady miesięczne są podzbiorem zbioru danych o normalnych wartościach klimatycznych i są ograniczone do średniej wartości pikseli przecinających się z ekoregionem.

Edytor kodu (JavaScript)

// Import the example feature collection, subset the forest ecoregion.
var forest = ee.FeatureCollection('projects/google/charts_feature_example')
                 .filter(ee.Filter.eq('label', 'Forest'));

// Load PRISM climate normals image collection, convert images to bands.
var normClim = ee.ImageCollection('OREGONSTATE/PRISM/Norm81m').toBands();

// Define x-axis labels to replace default band names.
var monthNames = [
  'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov',
  'Dec'
];

// Define the chart and print it to the console.
var chart = ui.Chart.image
                .regions({
                  image: normClim.select('[0-9][0-9]_ppt'),
                  regions: forest,
                  reducer: ee.Reducer.mean(),
                  scale: 5e3,
                  seriesProperty: 'label',
                  xLabels: monthNames
                })
                .setChartType('PieChart')
                .setOptions({
                  title: 'Average Monthly Precipitation for Forest Ecoregion',
                  colors: [
                    '604791', '1d6b99', '39a8a7', '0f8755', '76b349', 'f0af07',
                    'e37d05', 'cf513e', '96356f', '724173', '9c4f97', '696969'
                  ]
                });
print(chart);

Wykres pierścieniowy

Przekształć przykład wykresu kołowego w wykres donut, ustawiając opcję wykresu pieHole. Jako wartości początkowe spróbuj użyć 0,4 i 0,6.

var chart = ui.Chart.image
                .regions({
                  image: normClim.select('[0-9][0-9]_ppt'),
                  regions: forest,
                  reducer: ee.Reducer.mean(),
                  scale: 5e3,
                  seriesProperty: 'label',
                  xLabels: monthNames
                })
                .setChartType('PieChart')
                .setOptions({
                  title: 'Average Monthly Precipitation for Forest Ecoregion',
                  colors: [
                    '604791', '1d6b99', '39a8a7', '0f8755', '76b349', 'f0af07',
                    'e37d05', 'cf513e', '96356f', '724173', '9c4f97', '696969'
                  ],
                  pieHole: 0.4
                });

ui.Chart.image.byClass

Wykres liniowy

Funkcja ui.Chart.image.byClass nanosi statystyki wartości pasma na piksele w regionach sklasyfikowanych jako „pasmo klasy”. W tym przykładzie jest on używany do wyświetlania profilu widmowego 3 ekoregionów. Cechy ekoregionu są rastrowane i dodawane jako pasmo do obrazu odbicia powierzchni (SR) MODIS. W przypadku każdej klasy ekoregionu i pasma odbicia promieniowania oblicza się średnią wartości pikseli i nanosi ją na oś y. Centralne długości fal pasm MODIS SR określają znaczniki i etykiety osi X. Pamiętaj, że opcja wykresu liniowego curveType jest ustawiona na 'function', aby wygładzić linie.

Edytor kodu (JavaScript)

// Import the example feature collection.
var ecoregions = ee.FeatureCollection('projects/google/charts_feature_example');

// Convert ecoregion feature collection to a classified image.
var regionsBand =
    ecoregions
        .reduceToImage({properties: ['value'], reducer: ee.Reducer.first()})
        .rename('class');

// Define a MODIS surface reflectance composite.
var modisSr = ee.ImageCollection('MODIS/006/MOD09A1')
                  .filter(ee.Filter.date('2018-06-01', '2018-09-01'))
                  .select('sur_refl_b0[0-7]')
                  .mean();

// Reorder reflectance bands by ascending wavelength and
// add the classified ecoregions image as a band to the SR collection and
var modisSrClass = modisSr.select([2, 3, 0, 1, 4, 5, 6]).addBands(regionsBand);

// Define a list of MODIS SR wavelengths for x-axis labels.
var wavelengths = [469, 555, 655, 858, 1240, 1640, 2130];

// Define the chart and print it to the console.
var chart = ui.Chart.image
                .byClass({
                  image: modisSrClass,
                  classBand: 'class',
                  region: ecoregions,
                  reducer: ee.Reducer.mean(),
                  scale: 500,
                  classLabels: ['Desert', 'Forest', 'Grassland'],
                  xLabels: wavelengths
                })
                .setChartType('ScatterChart')
                .setOptions({
                  title: 'Ecoregion Spectral Signatures',
                  hAxis: {
                    title: 'Wavelength (nm)',
                    titleTextStyle: {italic: false, bold: true},
                    viewWindow: {min: wavelengths[0], max: wavelengths[6]}
                  },
                  vAxis: {
                    title: 'Reflectance (x1e4)',
                    titleTextStyle: {italic: false, bold: true}
                  },
                  colors: ['f0af07', '0f8755', '76b349'],
                  pointSize: 0,
                  lineSize: 5,
                  curveType: 'function'
                });
print(chart);

ui.Chart.image.histogram

Histograma wartości pikseli w regionie wokół Salt Lake City w stanie Utah w USA dla 3 pasm odbicia promieniowania MODIS.

Edytor kodu (JavaScript)

// Define a MODIS surface reflectance composite.
var modisSr = ee.ImageCollection('MODIS/006/MOD09A1')
                  .filter(ee.Filter.date('2018-06-01', '2018-09-01'))
                  .select(['sur_refl_b01', 'sur_refl_b02', 'sur_refl_b06'])
                  .mean();

// Define a region to calculate histogram for.
var histRegion = ee.Geometry.Rectangle([-112.60, 40.60, -111.18, 41.22]);

// Define the chart and print it to the console.
var chart =
    ui.Chart.image.histogram({image: modisSr, region: histRegion, scale: 500})
        .setSeriesNames(['Red', 'NIR', 'SWIR'])
        .setOptions({
          title: 'MODIS SR Reflectance Histogram',
          hAxis: {
            title: 'Reflectance (x1e4)',
            titleTextStyle: {italic: false, bold: true},
          },
          vAxis:
              {title: 'Count', titleTextStyle: {italic: false, bold: true}},
          colors: ['cf513e', '1d6b99', 'f0af07']
        });
print(chart);