1 /**
  2  * @class Legacy-compatible NCList for 1.2.1 backward compatibility.
  3  */
  4 function NCList_v0() {}
  5 
  6 NCList_v0.prototype.importExisting = function(nclist, sublistIndex,
  7                                            lazyIndex, baseURL,
  8                                            lazyUrlTemplate) {
  9     this.topList = nclist;
 10     this.sublistIndex = sublistIndex;
 11     this.lazyIndex = lazyIndex;
 12     this.baseURL = baseURL;
 13     this.lazyUrlTemplate = lazyUrlTemplate;
 14 };
 15 
 16 NCList_v0.prototype.fill = function(intervals, sublistIndex) {
 17     //intervals: array of arrays of [start, end, ...]
 18     //sublistIndex: index into a [start, end] array for storing a sublist
 19     //              array. this is so you can use those arrays for something
 20     //              else, and keep the NCList_v0 bookkeeping from interfering.
 21     //              That's hacky, but keeping a separate copy of the intervals
 22     //              in the NCList_v0 seems like a waste (TODO: measure that waste).
 23     //half-open?
 24     this.sublistIndex = sublistIndex;
 25     var myIntervals = intervals;//.concat();
 26     //sort by OL
 27     myIntervals.sort(function(a, b) {
 28         if (a[0] != b[0])
 29             return a[0] - b[0];
 30         else
 31             return b[1] - a[1];
 32     });
 33     var sublistStack = new Array();
 34     var curList = new Array();
 35     this.topList = curList;
 36     curList.push(myIntervals[0]);
 37     var curInterval, topSublist;
 38     for (var i = 1, len = myIntervals.length; i < len; i++) {
 39         curInterval = myIntervals[i];
 40         //if this interval is contained in the previous interval,
 41         if (curInterval[1] < myIntervals[i - 1][1]) {
 42             //create a new sublist starting with this interval
 43             sublistStack.push(curList);
 44             curList = new Array(curInterval);
 45             myIntervals[i - 1][sublistIndex] = curList;
 46         } else {
 47             //find the right sublist for this interval
 48             while (true) {
 49                 if (0 == sublistStack.length) {
 50                     curList.push(curInterval);
 51                     break;
 52                 } else {
 53                     topSublist = sublistStack[sublistStack.length - 1];
 54                     if (topSublist[topSublist.length - 1][1] > curInterval[1]) {
 55                         //curList is the first (deepest) sublist that
 56                         //curInterval fits into
 57                         curList.push(curInterval);
 58                         break;
 59                     } else {
 60                         curList = sublistStack.pop();
 61                     }
 62                 }
 63             }
 64         }
 65     }
 66 };
 67 
 68 NCList_v0.prototype.binarySearch = function(arr, item, itemIndex) {
 69     var low = -1;
 70     var high = arr.length;
 71     var mid;
 72 
 73     while (high - low > 1) {
 74         mid = (low + high) >>> 1;
 75         if (arr[mid][itemIndex] > item)
 76             high = mid;
 77         else
 78             low = mid;
 79     }
 80 
 81     //if we're iterating rightward, return the high index;
 82     //if leftward, the low index
 83     if (1 == itemIndex) return high; else return low;
 84 };
 85 
 86 NCList_v0.prototype.iterHelper = function(arr, from, to, fun, finish,
 87                                        inc, searchIndex, testIndex, path) {
 88     var len = arr.length;
 89     var i = this.binarySearch(arr, from, searchIndex);
 90     while ((i < len)
 91            && (i >= 0)
 92            && ((inc * arr[i][testIndex]) < (inc * to)) ) {
 93 
 94         if ("object" == typeof arr[i][this.lazyIndex]) {
 95             var ncl = this;
 96             // lazy node
 97             if (arr[i][this.lazyIndex].state) {
 98                 if ("loading" == arr[i][this.lazyIndex].state) {
 99                     // node is currenly loading; finish this query once it
100                     // has been loaded
101                     finish.inc();
102                     arr[i][this.lazyIndex].callbacks.push(
103                         function(parentIndex) {
104                             return function(o) {
105                                 ncl.iterHelper(o, from, to, fun, finish, inc,
106                                                searchIndex, testIndex,
107                                                path.concat(parentIndex));
108                                 finish.dec();
109                             };
110                         }(i)
111                     );
112                 } else if ("loaded" == arr[i][this.lazyIndex].state) {
113                     // just continue below
114                 } else {
115                     console.log("unknown lazy type: " + arr[i]);
116                 }
117             } else {
118                 // no "state" property means this node hasn't been loaded,
119                 // start loading
120                 arr[i][this.lazyIndex].state = "loading";
121                 arr[i][this.lazyIndex].callbacks = [];
122                 finish.inc();
123                 dojo.xhrGet(
124                     {
125                         url: Util.resolveUrl(
126                                 this.baseURL,
127                                 this.lazyUrlTemplate.replace(
128                                     /\{chunk\}/g,
129                                    arr[i][this.lazyIndex].chunk
130                                 )
131                              ),
132                         handleAs: "json",
133                         load: function(lazyFeat, lazyObj,
134                                        sublistIndex, parentIndex) {
135                             return function(o) {
136                                 lazyObj.state = "loaded";
137                                 lazyFeat[sublistIndex] = o;
138                                 ncl.iterHelper(o, from, to,
139                                                fun, finish, inc,
140                                                searchIndex, testIndex,
141                                                path.concat(parentIndex));
142                                 for (var c = 0;
143                                      c < lazyObj.callbacks.length;
144                                      c++)
145                                      lazyObj.callbacks[c](o);
146                                 finish.dec();
147                             };
148                         }(arr[i], arr[i][this.lazyIndex], this.sublistIndex, i),
149                         error: function() {
150                             finish.dec();
151                         }
152                     });
153             }
154         } else {
155             fun(arr[i], path.concat(i));
156         }
157 
158         if (arr[i][this.sublistIndex])
159             this.iterHelper(arr[i][this.sublistIndex], from, to,
160                             fun, finish, inc, searchIndex, testIndex,
161                             path.concat(i));
162         i += inc;
163     }
164 };
165 
166 NCList_v0.prototype.iterate = function(from, to, fun, postFun) {
167     // calls the given function once for each of the
168     // intervals that overlap the given interval
169     //if from <= to, iterates left-to-right, otherwise iterates right-to-left
170 
171     //inc: iterate leftward or rightward
172     var inc = (from > to) ? -1 : 1;
173     //searchIndex: search on start or end
174     var searchIndex = (from > to) ? 0 : 1;
175     //testIndex: test on start or end
176     var testIndex = (from > to) ? 1 : 0;
177     var finish = new Finisher(postFun);
178     this.iterHelper(this.topList, from, to, fun, finish,
179                     inc, searchIndex, testIndex, []);
180     finish.finish();
181 };
182 
183 NCList_v0.prototype.histogram = function(from, to, numBins, callback) {
184     //calls callback with a histogram of the feature density
185     //in the given interval
186 
187     var result = new Array(numBins);
188     var binWidth = (to - from) / numBins;
189     for (var i = 0; i < numBins; i++) result[i] = 0;
190     //this.histHelper(this.topList, from, to, result, numBins, (to - from) / numBins);
191     this.iterate(from, to,
192                  function(feat) {
193 	             var firstBin =
194                          Math.max(0, ((feat[0] - from) / binWidth) | 0);
195                      var lastBin =
196                          Math.min(numBins, ((feat[1] - from) / binWidth) | 0);
197 	             for (var bin = firstBin; bin <= lastBin; bin++)
198                          result[bin]++;
199                  },
200                  function() {
201                      callback(result);
202                  }
203                  );
204 };
205 
206 /*
207 
208 Copyright (c) 2007-2009 The Evolutionary Software Foundation
209 
210 Created by Mitchell Skinner <mitch_skinner@berkeley.edu>
211 
212 This package and its accompanying libraries are free software; you can
213 redistribute it and/or modify it under the terms of the LGPL (either
214 version 2.1, or at your option, any later version) or the Artistic
215 License 2.0.  Refer to LICENSE for the full license text.
216 
217 */
218