• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eweitz / ideogram / 2118

pending completion
2118

push

travis-ci-com

eweitz
Consolidate Gene Hints into Gene Leads

1766 of 2271 branches covered (77.76%)

Branch coverage included in aggregate %.

6 of 6 new or added lines in 2 files covered. (100.0%)

4626 of 5173 relevant lines covered (89.43%)

34820.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.38
/src/js/init/init.js
1
/**
2
 * @fileoveriew Methods for initialization
3
 */
4

5
import {d3, slug} from '../lib';
6
import {configure} from './configure';
7
import {finishInit} from './finish-init';
8
import {writeContainer} from './write-container';
9
import {shouldFetchBands, fetchBands} from '../bands/fetch';
10
import {organismMetadata} from './organism-metadata';
11

12
function isHeterogameticChromosome(chrModel, chrIndex, ideo) {
13
  var ploidy = ideo.config.ploidy;
1,751✔
14
  return (
1,751✔
15
    'sex' in ideo.config &&
2,032✔
16
      (
17
        ploidy === 2 && ideo.sexChromosomes.index + 1 === chrIndex ||
18
        ideo.config.sex === 'female' && chrModel.name === 'Y'
19
      )
20
  );
21
}
22

23
function prepareChromosomes(bandsArray, chrs, taxid, ideo) {
24
  var j, bands, chromosome, chrModel, chrIndex;
25

26
  for (j = 0; j < chrs.length; j++) {
89✔
27
    chromosome = chrs[j];
1,751✔
28
    if (typeof bandsArray !== 'undefined') bands = bandsArray[j];
1,751✔
29

30
    chrIndex = j + ideo.config.taxids.indexOf(taxid);
1,751✔
31
    chrModel = ideo.getChromosomeModel(bands, chromosome, taxid, chrIndex);
1,751✔
32

33
    if (typeof chromosome !== 'string') {
1,751✔
34
      chromosome = chromosome.name.split(' ').slice(-1)[0].replace('chr', '');
32✔
35
    }
36

37
    ideo.chromosomes[taxid][chromosome] = chrModel;
1,751✔
38
    ideo.chromosomesArray.push(chrModel);
1,751✔
39

40
    if (isHeterogameticChromosome(chrModel, j, ideo)) continue;
1,751✔
41

42
    ideo.drawChromosome(chrModel);
1,748✔
43
  }
44
}
45

46
function setCoordinateSystem(chrs, ideo) {
47
  if (
89✔
48
    typeof chrBands !== 'undefined' &&
177✔
49
    chrs.length >= chrBands.length / 2
50
  ) {
51
    ideo.coordinateSystem = 'bp';
25✔
52
  }
53
}
54

55
/**
56
 * Configures chromosome data and calls downstream chromosome drawing functions
57
 */
58
function initDrawChromosomes() {
59
  var taxid, i, chrs, bandsArray,
60
    ideo = this,
83✔
61
    taxids = ideo.config.taxids;
83✔
62

63
  for (i = 0; i < taxids.length; i++) {
83✔
64
    taxid = taxids[i];
89✔
65
    chrs = ideo.config.chromosomes[taxid];
89✔
66

67
    bandsArray = ideo.bandsArray[taxid];
89✔
68

69
    if (!ideo.config.showNonNuclearChromosomes) {
89✔
70
      // Remove MT
71
      // TODO: Handle other non-nuclear chromosomes, e.g. CP, AP
72
      chrs = chrs.filter(chr => chr !== 'MT');
1,730✔
73
      if (typeof bandsArray !== 'undefined') {
86✔
74
        bandsArray = bandsArray.filter(bands => {
85✔
75
          return bands[0].chr !== 'MT';
1,698✔
76
        });
77
      }
78
    }
79

80
    setCoordinateSystem(chrs, ideo);
89✔
81

82
    ideo.chromosomes[taxid] = {};
89✔
83
    ideo.setSexChromosomes(chrs);
89✔
84

85
    prepareChromosomes(bandsArray, chrs, taxid, ideo);
89✔
86

87
    if (ideo.config.showBandLabels) ideo.drawBandLabels(ideo.chromosomes);
89✔
88
    ideo.handleRotateOnClick();
89✔
89
    ideo._gotChrModels = true; // Prevent issue with errant rat centromeres
89✔
90
  }
91
}
92

93
/**
94
 * Attach any click handlers to rotate and toggle chromosomes
95
 */
96
function handleRotateOnClick() {
97
  var ideo = this;
95✔
98

99
  if (!('rotatable' in ideo.config && ideo.config.rotatable === false)) {
95✔
100
    d3.selectAll(ideo.selector + ' .chromosome-set').on('click', function() {
80✔
101
      // Handles click on chromosome graphic or label.
102
      // Label click needed to toggle e.g. human MT
103
      const element = this.children[1];
9✔
104

105
      ideo.rotateAndToggleDisplay(element);
9✔
106
    });
107
  } else {
108
    d3.selectAll(ideo.selector).style('cursor', 'default');
15✔
109
  }
110
}
111

112
/**
113
 * Called when Ideogram has finished initializing.
114
 * Accounts for certain ideogram properties not being set until
115
 * asynchronous requests succeed, etc.
116
 */
117
function onLoad() {
118
  call(this.onLoadCallback);
×
119
}
120

121
function getBandFileName(taxid, accession, ideo) {
122
  var organism = ideo.organisms[taxid];
90✔
123
  var bandFileName = [slug(organism.scientificName)];
90✔
124
  var assemblies = organism.assemblies;
90✔
125
  var resolution = ideo.config.resolution;
90✔
126

127
  if (accession !== assemblies.default) {
90✔
128
    bandFileName.push(accession);
8✔
129
  }
130
  if (
90✔
131
    taxid === '9606' &&
230!
132
    (accession in assemblies === 'false' &&
133
      Object.values(assemblies).includes(config.assembly) ||
134
      (resolution !== '' && resolution !== 850))
135
  ) {
136
    bandFileName.push(resolution);
4✔
137
  }
138

139
  bandFileName = bandFileName.join('-');
90✔
140

141
  var fullyBandedTaxids = ['9606', '10090', '10116'];
90✔
142
  if (fullyBandedTaxids.includes(taxid) && !ideo.config.showFullyBanded) {
90✔
143
    bandFileName += '-no-bands';
14✔
144
  }
145

146
  bandFileName += '.json';
90✔
147

148
  return bandFileName;
90✔
149
}
150

151
function getBandFileNames(taxid, bandFileNames, ideo) {
152
  var organism, assemblies, accession, bandFileName,
153
    config = ideo.config;
90✔
154

155
  organism = ideo.organisms[taxid];
90✔
156

157
  if (!config.assembly) ideo.config.assembly = 'default';
90✔
158

159
  assemblies = organism.assemblies;
90✔
160

161
  if (ideo.assemblyIsAccession()) {
90✔
162
    accession = config.assembly;
2✔
163
  } else {
164
    accession = assemblies[config.assembly];
88✔
165
  }
166

167
  bandFileName = getBandFileName(taxid, accession, ideo);
90✔
168
  var isCustomOrganism = taxid === '-1';
90✔
169

170
  if (taxid in ideo.organismsWithBands || isCustomOrganism) {
90✔
171
    bandFileNames[taxid] = bandFileName;
89✔
172
  }
173
  return bandFileNames;
90✔
174
}
175

176
function prepareContainer(taxid, bandFileNames, t0, ideo) {
177

178
  if (shouldFetchBands(bandFileNames, taxid, ideo)) {
90✔
179
    return fetchBands(bandFileNames, taxid, t0, ideo).then(function() {
89✔
180
      return ideo.processBandData(taxid);
89✔
181
    });
182
  } else {
183
    return new Promise(function(resolve) {
1✔
184
      ideo.processBandData(taxid);
1✔
185
      resolve([taxid, undefined]);
1✔
186
    });
187
  }
188
}
189

190
function initializeTaxids(ideo) {
191
  return new Promise(function(resolve) {
84✔
192
    var organism = ideo.config.organism;
84✔
193
    if (typeof organism === 'number') {
84✔
194
      // 'organism' is a taxid, e.g. 9606
195
      ideo.getOrganismFromEutils(organism, function() {
1✔
196
        ideo.getTaxids(resolve);
1✔
197
      });
198
    } else {
199
      ideo.getTaxids(resolve);
83✔
200
    }
201

202
  });
203
}
204

205
function getBandsAndPrepareContainer(taxids, t0, ideo) {
206
  var bandFileNames, i, taxid,
207
    promises = [];
84✔
208

209
  bandFileNames = {};
84✔
210
  for (taxid in organismMetadata) {
84✔
211
    bandFileNames[taxid] = '';
2,520✔
212
  }
213

214
  for (i = 0; i < taxids.length; i++) {
84✔
215
    taxid = String(taxids[i]);
90✔
216
    bandFileNames = getBandFileNames(taxid, bandFileNames, ideo);
90✔
217
    promises.push(prepareContainer(taxid, bandFileNames, t0, ideo));
90✔
218
  }
219

220
  Promise.all(promises).then(function(taxidsAndBandsArrays) {
84✔
221
    var taxidAndBandsArray, taxid, bandsArray;
222

223
    for (i = 0; i < taxidsAndBandsArrays.length; i++) {
84✔
224
      taxidAndBandsArray = taxidsAndBandsArrays[i];
90✔
225
      taxid = taxidAndBandsArray[0];
90✔
226
      bandsArray = taxidAndBandsArray[1];
90✔
227

228
      if ('bandsArray' in ideo === false) {
90✔
229
        ideo.bandsArray = {};
84✔
230
      }
231

232
      ideo.bandsArray[taxid] = bandsArray;
90✔
233
    }
234
    ideo.writeContainer(t0);
84✔
235
  });
236
}
237

238
/**
239
 * Initializes an ideogram.
240
 * Sets some high-level properties based on instance configuration,
241
 * fetches band and annotation data if needed, and
242
 * writes an SVG element to the document to contain the ideogram
243
 */
244
// Prevents race condition when init is called multiple times in
245
// quick succession.
246
// See https://github.com/eweitz/ideogram/pull/154.
247
var ideoNext = {};
1✔
248
var ideoQueued = {};
1✔
249
var ideoWait = {};
1✔
250

251
function init(ideo) {
252
  ideo = ideo || this;
84✔
253
  var containerId = ideo.config.container;
84✔
254

255
  if (ideoWait[containerId]) {
84!
256
    ideoQueued[containerId] = true;
×
257
    ideoNext[containerId] = ideo;
×
258
  } else {
259
    ideoWait[containerId] = true;
84✔
260
    initializeTaxids(ideo)
84✔
261
      .then(function(taxids) {
262

263
        var taxid = taxids[0];
84✔
264
        ideo.config.taxid = taxid;
84✔
265
        ideo.config.taxids = taxids;
84✔
266

267
        ideo.organismScientificName =
84✔
268
          ideo.getScientificName(ideo.config.taxid);
269

270
        var t0 = new Date().getTime();
84✔
271
        getBandsAndPrepareContainer(taxids, t0, ideo);
84✔
272

273
        ideoWait[containerId] = false;
84✔
274
        if (ideoQueued[containerId]) {
84!
275
          ideoQueued[containerId] = false;
×
276
          init(ideoNext[containerId]);
×
277
        }
278
      });
279
  }
280
}
281

282
export {
283
  configure, initDrawChromosomes, handleRotateOnClick,
284
  onLoad, init, finishInit, writeContainer
285
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc