|
|
@@ -3,45 +3,105 @@ import {Injectable} from '@angular/core';
|
|
|
import {Subject} from 'rxjs';
|
|
|
import {csv} from 'd3';
|
|
|
|
|
|
+import vars2facts from '../../assets/data/variables2factors.json';
|
|
|
+
|
|
|
@Injectable({providedIn: 'root'})
|
|
|
export class SdmDihService {
|
|
|
readonly DATA_PATH = '../../assets/data/normalized_data.csv';
|
|
|
sdmData = {};
|
|
|
- aggregatedData = {};
|
|
|
+ //aggregatedData = {};
|
|
|
dataLoads: Subject<void> = new Subject();
|
|
|
|
|
|
constructor(private httpClient: HttpClient) {
|
|
|
- this.loadData().then(() => this.calculateAggregation());
|
|
|
+ this.loadData().then(() => {
|
|
|
+ this.dataLoads.next();
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- calculateAttractiveness(data) {
|
|
|
- return data;
|
|
|
+ calcAggregatedIndex(regionData) {
|
|
|
+ let weightedSum = 0;
|
|
|
+ let sumWeight = 0;
|
|
|
+ for (const key of Object.keys(regionData) as any) {
|
|
|
+ if (key === 'MODEL' || key === 'TIME_STEP') {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ const factorValues = regionData[key];
|
|
|
+ let sumValue = 0;
|
|
|
+ let n = 0;
|
|
|
+ for (const ds of factorValues.datasets) {
|
|
|
+ sumValue += ds.value;
|
|
|
+ n += 1;
|
|
|
+ }
|
|
|
+ weightedSum += sumValue * factorValues['weight'];
|
|
|
+ sumWeight += n * factorValues['weight'];
|
|
|
+ }
|
|
|
+ return weightedSum / sumWeight;
|
|
|
}
|
|
|
|
|
|
- calculateAggregation() {
|
|
|
- console.log('aggregating...', this.sdmData);
|
|
|
- for (const year of Object.keys(this.sdmData)) {
|
|
|
- const yearData = this.sdmData[year];
|
|
|
- const yearAggregated = this.calculateAttractiveness(yearData);
|
|
|
- if (!this.aggregatedData[year]) {
|
|
|
- this.aggregatedData[year] = yearAggregated;
|
|
|
- } else {
|
|
|
- this.aggregatedData[year].push(yearAggregated);
|
|
|
- }
|
|
|
+ calcFactorIndex(factorData) {
|
|
|
+ let sumValue = 0;
|
|
|
+ let n = 0;
|
|
|
+ for (const ds of factorData.datasets) {
|
|
|
+ sumValue += ds.value;
|
|
|
+ n += 1;
|
|
|
}
|
|
|
- this.dataLoads.next();
|
|
|
+ return sumValue / n;
|
|
|
}
|
|
|
|
|
|
async loadData() {
|
|
|
- const data = await csv(this.DATA_PATH);
|
|
|
+ const data = await csv(this.DATA_PATH); // Array of objects, each object represents a row, where key is a heading and value is the cell
|
|
|
console.log(data);
|
|
|
for (const row of data) {
|
|
|
- if (!this.sdmData[row['TIME_STEP']]) {
|
|
|
- this.sdmData[row['TIME_STEP']] = [row];
|
|
|
- } else {
|
|
|
- this.sdmData[row['TIME_STEP']].push(row);
|
|
|
+ const timeStep = row['TIME_STEP'];
|
|
|
+ const regionData = this.splitDataByFactor(row);
|
|
|
+ if (!this.sdmData[timeStep]) {
|
|
|
+ this.sdmData[timeStep] = [];
|
|
|
}
|
|
|
+ this.sdmData[timeStep].push(regionData);
|
|
|
}
|
|
|
console.log(this.sdmData);
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Change format of each input row into a two-level structure where datasets are classified by factors
|
|
|
+ * @param inputRegionData - row as read by the CSV reader
|
|
|
+ * @returns data for one region in one point in time
|
|
|
+ */
|
|
|
+ splitDataByFactor(inputRegionData) {
|
|
|
+ const regionData = {};
|
|
|
+ for (const dataset of Object.keys(inputRegionData)) {
|
|
|
+ const datasetValue = inputRegionData[dataset];
|
|
|
+ if (['MODEL', 'TIME_STEP'].includes(dataset)) {
|
|
|
+ // just copy the MODEL and TIME_STEP
|
|
|
+ regionData[dataset] = datasetValue;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ const factor = vars2facts[dataset];
|
|
|
+ // when no factor is defined for the dataset, then skip this dataset
|
|
|
+ if (!factor) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (!regionData[factor]) {
|
|
|
+ regionData[factor] = {
|
|
|
+ weight: 1,
|
|
|
+ datasets: [],
|
|
|
+ };
|
|
|
+ }
|
|
|
+ regionData[factor].datasets.push({
|
|
|
+ name: dataset,
|
|
|
+ value: parseFloat(datasetValue),
|
|
|
+ });
|
|
|
+ }
|
|
|
+ for (const key of Object.keys(regionData)) {
|
|
|
+ if (key === 'MODEL' || key === 'TIME_STEP') {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ const values = regionData[key];
|
|
|
+ const index = this.calcFactorIndex(values);
|
|
|
+ values['index'] = index;
|
|
|
+ }
|
|
|
+ const aggregated = this.calcAggregatedIndex(regionData);
|
|
|
+ regionData['aggregated'] = aggregated;
|
|
|
+ return regionData;
|
|
|
+ }
|
|
|
}
|