1+ <template >
2+ <v-container >
3+ <h2 class =" pb-10" >Yearly NDVI vs. Temperature</h2 >
4+ <v-row justify =" center" >
5+ <div ref =" plotContainer" style =" width : 100% ; height : 400px " class =" d-flex justify-center" ></div >
6+ </v-row >
7+ </v-container >
8+ </template >
9+
10+ <script >
11+ import axios from ' axios' ;
12+ import Plotly from ' plotly.js-dist-min' ;
13+ import { onMounted , ref , watch } from ' vue' ;
14+
15+ export default {
16+ name: ' YearlyNdviTemperaturePlot' ,
17+ setup () {
18+ const temperatureData = ref (null );
19+ const ndviData = ref (null );
20+ const plotContainer = ref (null );
21+ const startDate = ref (1514764800 ); // 2018-01-01
22+ const endDate = ref (1733007599 ); // 2024-11-30
23+
24+ const fetchTemperatureData = async () => {
25+ const apiUrl = ' https://thf-climate-run-1020174331409.europe-west3.run.app/weather/index' ;
26+ const params = {
27+ weatherVariable: ' temperature_2m' ,
28+ startDate: startDate .value ,
29+ endDate: endDate .value ,
30+ location: ' TEMPELHOFER_FELD' ,
31+ temporalResolution: ' MONTHLY' ,
32+ aggregation: ' MEAN' ,
33+ };
34+ try {
35+ const response = await axios .get (apiUrl, { params });
36+ temperatureData .value = response .data ;
37+ } catch (error) {
38+ console .error (' Error fetching temperature data:' , error);
39+ }
40+ };
41+
42+ const fetchNdviData = async () => {
43+ const apiUrl = ' https://thf-climate-run-1020174331409.europe-west3.run.app/index/ndvi' ;
44+ const params = {
45+ startDate: startDate .value ,
46+ endDate: endDate .value ,
47+ location: ' TEMPELHOFER_FELD' ,
48+ temporalResolution: ' MONTHLY' ,
49+ aggregation: ' MEAN' ,
50+ };
51+ try {
52+ const response = await axios .get (apiUrl, { params });
53+ ndviData .value = response .data ;
54+ } catch (error) {
55+ console .error (' Error fetching NDVI data:' , error);
56+ }
57+ };
58+
59+ const calculateYearlyAverages = (data ) => {
60+ const yearlyData = {};
61+ data .forEach ((entry ) => {
62+ const year = new Date (entry .timestamp * 1000 ).getFullYear ();
63+ if (! yearlyData[year]) yearlyData[year] = { sum: 0 , count: 0 };
64+ yearlyData[year].sum += entry .value ;
65+ yearlyData[year].count += 1 ;
66+ });
67+ return Object .entries (yearlyData).map (([year , { sum, count }]) => ({
68+ year: parseInt (year, 10 ),
69+ average: sum / count,
70+ }));
71+ };
72+
73+ const renderPlot = () => {
74+ if (temperatureData .value && ndviData .value ) {
75+ const yearlyTemperature = calculateYearlyAverages (temperatureData .value .data );
76+ const yearlyNdvi = calculateYearlyAverages (ndviData .value .data );
77+
78+ const tempTrace = {
79+ x: yearlyTemperature .map ((e ) => e .year ),
80+ y: yearlyTemperature .map ((e ) => e .average ),
81+ mode: ' lines+markers' ,
82+ name: ' Temperature (°C)' ,
83+ marker: { color: ' red' , size: 7 , symbol: ' square' },
84+ hoverinfo: ' text' ,
85+ text: yearlyTemperature .map ((e ) => ` ${ e .average .toFixed (2 )} °C` )
86+ };
87+
88+ const ndviTrace = {
89+ x: yearlyNdvi .map ((e ) => e .year ),
90+ y: yearlyNdvi .map ((e ) => e .average ),
91+ mode: ' lines+markers' ,
92+ name: ' NDVI' ,
93+ line: { color: ' blue' },
94+ yaxis: ' y2' ,
95+ hoverinfo: ' text' ,
96+ text: yearlyNdvi .map ((e ) => ` ${ e .average .toFixed (2 )} ` )
97+ };
98+
99+ const layout = {
100+ title: ' Yearly NDVI vs. Temperature (2018-2024)' ,
101+ xaxis: { title: ' Year' , type: ' category' },
102+ yaxis: { title: ' Temperature (°C)' },
103+ yaxis2: { title: ' NDVI' , overlaying: ' y' , side: ' right' },
104+ template: ' plotly_white' ,
105+ };
106+
107+ Plotly .newPlot (plotContainer .value , [tempTrace, ndviTrace], layout);
108+ }
109+ };
110+
111+ onMounted (() => {
112+ fetchTemperatureData ();
113+ fetchNdviData ();
114+ });
115+
116+ watch ([temperatureData, ndviData], ([temp , ndvi ]) => {
117+ if (temp && ndvi) renderPlot ();
118+ });
119+
120+ return { plotContainer };
121+ },
122+ };
123+
124+
125+ </script >
126+
127+ <style scoped></style >
128+
0 commit comments