Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

Commit

Permalink
Merge pull request #107 from azavea/feature/SupportMonthlyIndicators
Browse files Browse the repository at this point in the history
Support monthly indicators in line graphs
  • Loading branch information
fungjj92 authored Oct 25, 2016
2 parents 6db09e3 + 64e145d commit 4d2f824
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 26 deletions.
28 changes: 10 additions & 18 deletions src/app/charts/line-graph.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,12 @@ export class LineGraphComponent implements OnInit, OnDestroy {
private yScale; // D3 scale in Y
private htmlElement; // Host HTMLElement
private valueline; // Base for a chart line
private xRange: Array<string>; // Min, max date range
private xRange: Array<Date>; // Min, max date range
private xData: Array<number>; // Stores x axis data as integers rather than dates, necessary for trendline math
private yData: Array<number>; // Stores primary y axis data, multi-use
private trendData: Array<DataPoint>; // Formatted data for the trendline
private timeFormat: string; // Date formatting for x axis labels (e.g, '%Y-%m')
private scrubber; // Lump of scrubber elements
private scrubberLine; // Scrubber element, independent
private timeOptions: any;
private timeFormat: string;
private id: string; // Randomly generated int # used to distinguish the chart for drawing and isolated chart scrubber
// Not a perfect solution should the random int and indicator be the same
// However, this is quite unlikely (1/10000, and even less likely by way of app use)
Expand All @@ -61,10 +59,6 @@ export class LineGraphComponent implements OnInit, OnDestroy {
constructor(private element: ElementRef, private chartService: ChartService) {
this.htmlElement = this.element.nativeElement;
this.host = D3.select(this.element.nativeElement);
this.timeOptions = {
'yearly': '%Y',
'daily': '%Y-%m-%d'
}
}

@HostListener('window:resize', ['$event'])
Expand Down Expand Up @@ -129,16 +123,12 @@ export class LineGraphComponent implements OnInit, OnDestroy {
private filterData(): void {
// Preserves parent data by fresh copying indicator data that will undergo processing
let clippedData = _.cloneDeep(_.find(this.data, obj => obj.indicator.name === this.indicator.name));
if (clippedData) {
this.timeFormat = this.timeOptions[clippedData.time_agg];
}
_.has(clippedData, 'data') ? this.extractedData = clippedData['data'] : this.extractedData = [];
// Remove empty day in non-leap years (affects only daily data)
if (this.extractedData[365] && this.extractedData[365]['date'] == null) {
this.extractedData.pop();
}
// Parse out avg data for ease of use later
this.yData = _.map(this.extractedData, d => d.values.avg);
this.timeFormat = clippedData.time_format;
}

/* Will setup the chart basics */
Expand All @@ -163,9 +153,11 @@ export class LineGraphComponent implements OnInit, OnDestroy {

// Set axis and line scales
private setLineScales(): void {
// Time scales only recognize annual and daily data
var parseTime = D3.timeParse(this.timeFormat);
this.extractedData.forEach(d => d.date = parseTime(d.date));
// Sort data by date ascending
this.extractedData.sort(function(a, b) {return +a.date - +b.date;});
// Parse out avg data for ease of use later
this.yData = _.map(this.extractedData, d => d.values.avg);

this.xRange = D3.extent(this.extractedData, d => d.date);
this.xScale.domain(this.xRange);

Expand Down Expand Up @@ -249,9 +241,9 @@ export class LineGraphComponent implements OnInit, OnDestroy {
var y1 = leastSquaresCoeff[0] + leastSquaresCoeff[1];
var x2 = this.xRange[0];
var y2 = leastSquaresCoeff[0] * this.xData.length + leastSquaresCoeff[1];
this.trendData = [{'date': x1, 'value': y2}, {'date': x2, 'value': y1}];
let trendData = [{'date': x1, 'value': y2}, {'date': x2, 'value': y1}];
// Add trendline
this.drawLine(this.trendData, 'trendline');
this.drawLine(trendData, 'trendline');
}
}

Expand Down
13 changes: 7 additions & 6 deletions src/app/models/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,19 @@ export class ChartData {
indicator: string;
data: MultiDataPoint[];
time_agg: string[];
time_format: string;
}

export class DataPoint {
date: string;
value: number;
date: Date;
value: number;
}

export class MultiDataPoint {
date: string;
date: Date;
values: {
'avg': Number,
'min': Number,
'max': Number
'avg': number,
'min': number,
'max': number
};
}
16 changes: 14 additions & 2 deletions src/app/services/chart.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ChartData, MultiDataPoint } from '../models/chart';

import * as moment from 'moment';
import * as _ from 'lodash';
import * as D3 from 'd3';

/*
* Chart Service
Expand All @@ -19,6 +20,13 @@ export class ChartService {
public multiChartScrubberInfoObservable = this._multiChartScrubberInfo.asObservable();
public multiChartScrubberHoverObservable = this._multiChartScrubberHover.asObservable();


private timeOptions = {
'yearly': '%Y',
'daily': '%Y-%m-%d',
'monthly': '%Y-%m'
};

constructor() {}

// receive and ship mousemove event
Expand Down Expand Up @@ -51,9 +59,12 @@ export class ChartService {
_.each(data, obj => {
let indicatorData: MultiDataPoint[] = [];
let indicator = obj.indicator;
let timeFormat = this.timeOptions[indicator.time_aggregation];
let parseTime = D3.timeParse(timeFormat);

_.each(obj.data, (values, key) => {
indicatorData.push({
'date': key,
'date': parseTime(key),
'values': values
} as MultiDataPoint);
});
Expand All @@ -63,7 +74,8 @@ export class ChartService {
chartData.push({
'indicator': indicator,
'data': indicatorData,
'time_agg': indicator.time_aggregation
'time_agg': indicator.time_aggregation,
'time_format': timeFormat
} as ChartData);
}
});
Expand Down

0 comments on commit 4d2f824

Please sign in to comment.