Mercurial > hg > extraction-interface
comparison geotemco/lib/simile/timeplot/scripts/sources.js @ 0:b12c99b7c3f0
commit for previous development
author | Zoe Hong <zhong@mpiwg-berlin.mpg.de> |
---|---|
date | Mon, 19 Jan 2015 17:13:49 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:b12c99b7c3f0 |
---|---|
1 /** | |
2 * Sources | |
3 * | |
4 * @fileOverview Sources | |
5 * @name Sources | |
6 */ | |
7 | |
8 /** | |
9 * Timeplot.DefaultEventSource is an extension of Timeline.DefaultEventSource | |
10 * and therefore reuses the exact same event loading subsystem that | |
11 * Timeline uses. | |
12 * | |
13 * @constructor | |
14 */ | |
15 Timeplot.DefaultEventSource = function(eventIndex) { | |
16 Timeline.DefaultEventSource.apply(this, arguments); | |
17 }; | |
18 | |
19 Object.extend(Timeplot.DefaultEventSource.prototype, Timeline.DefaultEventSource.prototype); | |
20 | |
21 /** | |
22 * Function used by Timeplot to load time series data from a text file. | |
23 */ | |
24 Timeplot.DefaultEventSource.prototype.loadText = function(text, separator, url, filter, format) { | |
25 | |
26 if (text == null) { | |
27 return; | |
28 } | |
29 | |
30 this._events.maxValues = new Array(); | |
31 var base = this._getBaseURL(url); | |
32 | |
33 if (!format) format = 'iso8601'; | |
34 var parseDateTimeFunction = this._events.getUnit().getParser(format); | |
35 | |
36 var data = this._parseText(text, separator); | |
37 | |
38 var added = false; | |
39 | |
40 if (filter) { | |
41 data = filter(data); | |
42 } | |
43 | |
44 if (data) { | |
45 for (var i = 0; i < data.length; i++){ | |
46 var row = data[i]; | |
47 if (row.length > 1) { | |
48 var dateStr = SimileAjax.jQuery.trim(row[0]); | |
49 var date = parseDateTimeFunction(dateStr); | |
50 if (date) { | |
51 var evt = new Timeplot.DefaultEventSource.NumericEvent(date,row.slice(1)); | |
52 this._events.add(evt); | |
53 added = true; | |
54 } | |
55 } | |
56 } | |
57 } | |
58 | |
59 if (added) { | |
60 this._fire("onAddMany", []); | |
61 } | |
62 } | |
63 | |
64 /* | |
65 * Parse the data file. | |
66 * | |
67 * Adapted from http://www.kawa.net/works/js/jkl/js/jkl-parsexml.js by Yusuke Kawasaki | |
68 */ | |
69 Timeplot.DefaultEventSource.prototype._parseText = function (text, separator) { | |
70 text = text.replace( /\r\n?/g, "\n" ); // normalize newlines | |
71 var pos = 0; | |
72 var len = text.length; | |
73 var table = []; | |
74 while (pos < len) { | |
75 var line = []; | |
76 if (text.charAt(pos) != '#') { // if it's not a comment, process | |
77 while (pos < len) { | |
78 if (text.charAt(pos) == '"') { // "..." quoted column | |
79 var nextquote = text.indexOf('"', pos+1 ); | |
80 while (nextquote<len && nextquote > -1) { | |
81 if (text.charAt(nextquote+1) != '"') { | |
82 break; // end of column | |
83 } | |
84 nextquote = text.indexOf('"', nextquote + 2); | |
85 } | |
86 if ( nextquote < 0 ) { | |
87 // unclosed quote | |
88 } else if (text.charAt(nextquote + 1) == separator) { // end of column | |
89 var quoted = text.substr(pos + 1, nextquote-pos - 1); | |
90 quoted = quoted.replace(/""/g,'"'); | |
91 line[line.length] = quoted; | |
92 pos = nextquote + 2; | |
93 continue; | |
94 } else if (text.charAt(nextquote + 1) == "\n" || // end of line | |
95 len == nextquote + 1 ) { // end of file | |
96 var quoted = text.substr(pos + 1, nextquote-pos - 1); | |
97 quoted = quoted.replace(/""/g,'"'); | |
98 line[line.length] = quoted; | |
99 pos = nextquote + 2; | |
100 break; | |
101 } else { | |
102 // invalid column | |
103 } | |
104 } | |
105 var nextseparator = text.indexOf(separator, pos); | |
106 var nextnline = text.indexOf("\n", pos); | |
107 if (nextnline < 0) nextnline = len; | |
108 if (nextseparator > -1 && nextseparator < nextnline) { | |
109 line[line.length] = text.substr(pos, nextseparator-pos); | |
110 pos = nextseparator + 1; | |
111 } else { // end of line | |
112 line[line.length] = text.substr(pos, nextnline-pos); | |
113 pos = nextnline + 1; | |
114 break; | |
115 } | |
116 } | |
117 } else { // if it's a comment, ignore | |
118 var nextnline = text.indexOf("\n", pos); | |
119 pos = (nextnline > -1) ? nextnline + 1 : cur; | |
120 } | |
121 if (line.length > 0) { | |
122 table[table.length] = line; // push line | |
123 } | |
124 } | |
125 if (table.length < 0) return; // null data | |
126 return table; | |
127 } | |
128 | |
129 /** | |
130 * Return the range of the loaded data | |
131 */ | |
132 Timeplot.DefaultEventSource.prototype.getRange = function() { | |
133 var earliestDate = this.getEarliestDate(); | |
134 var latestDate = this.getLatestDate(); | |
135 return { | |
136 earliestDate: (earliestDate) ? earliestDate : null, | |
137 latestDate: (latestDate) ? latestDate : null, | |
138 min: 0, | |
139 max: 0 | |
140 }; | |
141 } | |
142 | |
143 // ----------------------------------------------------------------------- | |
144 | |
145 /** | |
146 * A NumericEvent is an Event that also contains an array of values, | |
147 * one for each columns in the loaded data file. | |
148 * | |
149 * @constructor | |
150 */ | |
151 Timeplot.DefaultEventSource.NumericEvent = function(time, values) { | |
152 this._id = "e" + Math.round(Math.random() * 1000000); | |
153 this._time = time; | |
154 this._values = values; | |
155 }; | |
156 | |
157 Timeplot.DefaultEventSource.NumericEvent.prototype = { | |
158 getID: function() { return this._id; }, | |
159 getTime: function() { return this._time; }, | |
160 getValues: function() { return this._values; }, | |
161 | |
162 // these are required by the EventSource | |
163 getStart: function() { return this._time; }, | |
164 getEnd: function() { return this._time; } | |
165 }; | |
166 | |
167 // ----------------------------------------------------------------------- | |
168 | |
169 /** | |
170 * A DataSource represent an abstract class that represents a monodimensional time series. | |
171 * | |
172 * @constructor | |
173 */ | |
174 Timeplot.DataSource = function(eventSource) { | |
175 this._eventSource = eventSource; | |
176 var source = this; | |
177 this._processingListener = { | |
178 onAddMany: function() { source._process(); }, | |
179 onClear: function() { source._clear(); } | |
180 } | |
181 this.addListener(this._processingListener); | |
182 this._listeners = []; | |
183 this._data = null; | |
184 this._range = null; | |
185 }; | |
186 | |
187 Timeplot.DataSource.prototype = { | |
188 | |
189 _clear: function() { | |
190 this._data = null; | |
191 this._range = null; | |
192 }, | |
193 | |
194 _process: function() { | |
195 this._data = { | |
196 times: new Array(), | |
197 values: new Array() | |
198 }; | |
199 this._range = { | |
200 earliestDate: null, | |
201 latestDate: null, | |
202 min: 0, | |
203 max: 0 | |
204 }; | |
205 }, | |
206 | |
207 /** | |
208 * Return the range of this data source | |
209 */ | |
210 getRange: function() { | |
211 return this._range; | |
212 }, | |
213 | |
214 /** | |
215 * Return the actual data that this data source represents. | |
216 * NOTE: _data = { times: [], values: [] } | |
217 */ | |
218 getData: function() { | |
219 return this._data; | |
220 }, | |
221 | |
222 /** | |
223 * Return the value associated with the given time in this time series | |
224 */ | |
225 getValue: function(t) { | |
226 if (this._data) { | |
227 for (var i = 0; i < this._data.times.length; i++) { | |
228 var l = this._data.times[i]; | |
229 if (l >= t) { | |
230 return this._data.values[i]; | |
231 } | |
232 } | |
233 } | |
234 return 0; | |
235 }, | |
236 | |
237 /** | |
238 * Return the time of the data point closest to the given time. | |
239 */ | |
240 getClosestValidTime: function(t) { | |
241 if (this._data) { | |
242 for (var i = 0; i < this._data.times.length; i++) { | |
243 var currentTime = this._data.times[i]; | |
244 if (currentTime >= t) { | |
245 if (i <= 0) { | |
246 return currentTime; | |
247 } else { | |
248 var lastTime = this._data.times[i - 1]; | |
249 // t must be between currentTime and lastTime. | |
250 // Find the closest one. | |
251 if (t - lastTime < currentTime - t) { | |
252 return lastTime; | |
253 } else { | |
254 return currentTime; | |
255 } | |
256 } | |
257 } | |
258 } | |
259 } | |
260 return 0; | |
261 }, | |
262 | |
263 /** | |
264 * Add a listener to the underlying event source | |
265 */ | |
266 addListener: function(listener) { | |
267 this._eventSource.addListener(listener); | |
268 }, | |
269 | |
270 /** | |
271 * Remove a listener from the underlying event source | |
272 */ | |
273 removeListener: function(listener) { | |
274 this._eventSource.removeListener(listener); | |
275 }, | |
276 | |
277 /** | |
278 * Replace a listener from the underlying event source | |
279 */ | |
280 replaceListener: function(oldListener, newListener) { | |
281 this.removeListener(oldListener); | |
282 this.addListener(newListener); | |
283 } | |
284 | |
285 } | |
286 | |
287 // ----------------------------------------------------------------------- | |
288 | |
289 /** | |
290 * Implementation of a DataSource that extracts the time series out of a | |
291 * single column from the events | |
292 * | |
293 * @constructor | |
294 */ | |
295 Timeplot.ColumnSource = function(eventSource, column) { | |
296 Timeplot.DataSource.apply(this, arguments); | |
297 this._column = column - 1; | |
298 }; | |
299 | |
300 Object.extend(Timeplot.ColumnSource.prototype,Timeplot.DataSource.prototype); | |
301 | |
302 Timeplot.ColumnSource.prototype.dispose = function() { | |
303 this.removeListener(this._processingListener); | |
304 this._clear(); | |
305 } | |
306 | |
307 Timeplot.ColumnSource.prototype._process = function() { | |
308 var count = this._eventSource.getCount(); | |
309 var times = new Array(count); | |
310 var values = new Array(count); | |
311 var min = Number.MAX_VALUE; | |
312 var max = Number.MIN_VALUE; | |
313 var i = 0; | |
314 | |
315 var iterator = this._eventSource.getAllEventIterator(); | |
316 while (iterator.hasNext()) { | |
317 var event = iterator.next(); | |
318 var time = event.getTime(); | |
319 times[i] = time; | |
320 var value = this._getValue(event); | |
321 if (!isNaN(value)) { | |
322 if (value < min) { | |
323 min = value; | |
324 } | |
325 if (value > max) { | |
326 max = value; | |
327 } | |
328 values[i] = value; | |
329 } | |
330 i++; | |
331 } | |
332 | |
333 this._data = { | |
334 times: times, | |
335 values: values | |
336 }; | |
337 | |
338 if (max == Number.MIN_VALUE) max = 1; | |
339 | |
340 this._range = { | |
341 earliestDate: this._eventSource.getEarliestDate(), | |
342 latestDate: this._eventSource.getLatestDate(), | |
343 min: min, | |
344 max: max | |
345 }; | |
346 } | |
347 | |
348 Timeplot.ColumnSource.prototype._getValue = function(event) { | |
349 return parseFloat(event.getValues()[this._column]); | |
350 } | |
351 | |
352 // --------------------------------------------------------------- | |
353 | |
354 /** | |
355 * Data Source that generates the time series out of the difference | |
356 * between the first and the second column | |
357 * | |
358 * @constructor | |
359 */ | |
360 Timeplot.ColumnDiffSource = function(eventSource, column1, column2) { | |
361 Timeplot.ColumnSource.apply(this, arguments); | |
362 this._column2 = column2 - 1; | |
363 }; | |
364 | |
365 Object.extend(Timeplot.ColumnDiffSource.prototype,Timeplot.ColumnSource.prototype); | |
366 | |
367 Timeplot.ColumnDiffSource.prototype._getValue = function(event) { | |
368 var a = parseFloat(event.getValues()[this._column]); | |
369 var b = parseFloat(event.getValues()[this._column2]); | |
370 return a - b; | |
371 } |