LinkageDisequilibrium.
java
1 // LinkageDisequilibrium.java
7 package net.maizegenetics.analysis.popgen;
8
9 import cern.colt.map.OpenLongObjectHashMap;
23
24 /**
25 * This class calculates D' and r^2 estimates of linkage disequilibrium. It
also
26 * calculates the significance of the LD by either Fisher Exact or the
27 * multinomial permutation test. This class can work with either normal
28 * alignments of annotated alignments. The alignments should be stripped of
29 * invariable numSites.
30 * <p> {@link testDesign} sets matrix design for LD calculation. Either all
by
31 * all, sliding window, site by all, or site list.
32 * <p>
33 * There are multiple approaches for dealing with heterozygous sites.
34 * {@link HetTreatment} sets the way these are treated. Haplotype assumes
fully
35 * phased heterozygous sites (any hets are double counted). This is the best
36 * approach for speed when things are fully phased. Homozygous converted all
37 * hets to missing. Genotype does a 3x3 genotype analysis (to be implemented)
38 * <p>
39 * 2 state estimates of D' and r^2 can be found reviewed and discussed in
Weir
40 * 1996
41 * <p>
42 * Multi-state loci (>=3) require an averaging approach. In TASSEL 3 in 2010,
43 * Buckler removed these approach as the relative magnitudes and
meaningfulness
44 * of these approaches has never been clear. Additionally with the moving
away
45 * from SSR to SNPs these methods are less relevant. Researchers should
convert
46 * to biallelic - either by ignoring rarer classes or collapsing rarer
states.
47 * <p>
48 * TODO: Add 3x3 (genotype) mode.
49 *
50 * @version $Id: LinkageDisequilibrium.java,v 2
51 *
52 * @author Ed Buckler
53 */
54 public class LinkageDisequilibrium extends Thread implements Serializable,
TableReport {
55 private static final long serialVersionUID=-123423421342l;
56
57 /**
Page 1
LinkageDisequilibrium.java
58 * Design of test matrix.
59 */
60 public static enum testDesign {
61
62 /**
63 * Test All by All site
64 */
65 All,
66 /**
67 * Sliding of LD comparisons
68 */
69 SlidingWindow,
70 /**
71 * Test on site versus all others
72 */
73 SiteByAll,
74 /**
75 * Test all sites with the site list with all others
76 */
77 SiteList
78 };
79
80 /**
81 * Approaches for dealing with heterozygous sites. Haplotype assumes
fully
82 * phased heterozygous sites (any hets are double counted). This is the
best
83 * approach for speed when things are fully phased. Homozygous converted
all
84 * hets to missing. Genotype does a 3x3 genotype analysis (to be
85 * implemented)
86 */
87 public static enum HetTreatment {
88
89 Haplotype, Homozygous, Genotype
90 };
91 private static final Logger myLogger =
Logger.getLogger(LinkageDisequilibrium.class);
92 private GenotypeTable myAlignment;
93 // private Alignment mySBitAlignment;
94 private int myMinTaxaForEstimate = 20;
95 private int myWindowSize = 50;
96 private int myTestSite = -1; // this is only set when one versus all
numSites is calculated.
97 private long myTotalTests = 0;
98 private testDesign myCurrDesign = testDesign.SlidingWindow;
99 /**
100 * HashMap of results Key = (site1*siteNum + site2), Value =
Page 2
LinkageDisequilibrium.java
* HashMap of results Key = (site1*siteNum + site2), Value =
float[rsqr,d',
101 * pvalue, sampleSize]
102 */
103 private OpenLongObjectHashMap myMapResults;
104 private ProgressListener myListener = null;
105 private FisherExact myFisherExact;
106 private boolean myIsAccumulativeReport = false;
107 private int myNumAccumulativeBins = 100;
108 private float myAccumulativeInterval;
109 private int[] myAccumulativeRValueBins;
110 private int[] mySiteList;
111 private static String NotImplemented = "NotImplemented";
112 private static String NA = "N/A";
113 private static Integer IntegerTwo = Integer.valueOf(2);
114 private HetTreatment myHetTreatment = HetTreatment.Homozygous;
115
116 /**
117 * Constructor for doing LD analysis
118 *
119 * @param alignment Input alignment with segregating sites
120 * @param windowSize Size of sliding window
121 * @param LDType
122 * @param testSite
123 * @param listener
124 * @param isAccumulativeReport
125 * @param numAccumulateIntervals
126 * @param sitesList
127 * @param hetTreatment
128 */
129 public LinkageDisequilibrium(GenotypeTable alignment, int windowSize,
testDesign LDType, int testSite,
130 ProgressListener listener, boolean
isAccumulativeReport, int numAccumulateIntervals,
131 int[] sitesList, HetTreatment hetTreatment)
{
132 myAlignment = alignment;
133 myFisherExact = FisherExact.getInstance((2 *
myAlignment.numberOfTaxa()) + 10);
134 myWindowSize = windowSize;
135 myCurrDesign = LDType;
136 myTestSite = testSite;
137 myListener = listener;
138 myIsAccumulativeReport = isAccumulativeReport;
139 if (myIsAccumulativeReport) {
140 myNumAccumulativeBins = numAccumulateIntervals;
141 }
142 mySiteList = sitesList;
143 if (mySiteList != null) {
Page 3
LinkageDisequilibrium.java
144 Arrays.sort(mySiteList);
145 }
146 myHetTreatment = hetTreatment;
147 }
148
149 /**
150 * starts the thread to calculate LD
151 */
152 public void run() {
153 initMatrices();
154 switch (myHetTreatment) {
155 case Haplotype:
156 calculateBitLDForHaplotype(false);
157 break;
158 case Homozygous:
159 calculateBitLDForHaplotype(true);
160 break;
161 case Genotype:
162 calculateBitLDWithHets();
163 break;
164 default:
165 myLogger.error("Unknown LD analysis type selected for
heterozygotes; skipping");
166 break;
167 }
168 }
169
170 private void initMatrices() {
171 long numSites = myAlignment.numberOfSites();
172 if (myCurrDesign == testDesign.All) {
173 myTotalTests = numSites * (numSites - 1l) / 2l;
174 } else if (myCurrDesign == testDesign.SlidingWindow) {
175 long n = Math.min(numSites - 1l, myWindowSize);
176 myTotalTests = ((n * (n + 1l)) / 2l) + (numSites - n - 1l) * n;
177 } else if (myCurrDesign == testDesign.SiteByAll) {
178 myTotalTests = numSites - 1l;
179 } else if (myCurrDesign == testDesign.SiteList) {
180 long n = mySiteList.length;
181 myTotalTests = ((n * (n + 1l)) / 2l) + (numSites - n - 1l) * n;
182 }
183 if (myIsAccumulativeReport) {
184 myAccumulativeInterval = 1.0f / (float) myNumAccumulativeBins;
185 myAccumulativeRValueBins = new int[myNumAccumulativeBins + 1];
186 } else {
187 myMapResults = new OpenLongObjectHashMap((int)numSites);
188 }
189
190 }
Page 4
LinkageDisequilibrium.java
191
192 private long getMapKey(int r, int c) {
193 return (c < r) ? (((long) c * myAlignment.numberOfSites()) + r) :
(((long) r * myAlignment.numberOfSites()) + c);
194 }
195
196 public static LDResult calculateBitLDForHaplotype(boolean ignoreHets, int
minTaxaForEstimate, GenotypeTable alignment, int site1, int site2) {
197 FisherExact fisherExact = FisherExact.getInstance((2 *
alignment.numberOfTaxa()) + 10);
198 BitSet rMj = alignment.allelePresenceForAllTaxa(site1,
WHICH_ALLELE.Major);
199 BitSet rMn = alignment.allelePresenceForAllTaxa(site1,
WHICH_ALLELE.Minor);
200 BitSet cMj = alignment.allelePresenceForAllTaxa(site2,
WHICH_ALLELE.Major);
201 BitSet cMn = alignment.allelePresenceForAllTaxa(site2,
WHICH_ALLELE.Minor);
202 return getLDForSitePair(rMj, rMn, cMj, cMn, 2, minTaxaForEstimate,
-1.0f, fisherExact, site1, site2);
203 }
204
205 public static LDResult calculateBitLDForHaplotype(int
minTaxaForEstimate, int minorCnt, GenotypeTable alignment, int site1, int
site2) {
206 FisherExact fisherExact = FisherExact.getInstance((2 *
alignment.numberOfTaxa()) + 10);
207 BitSet rMj = alignment.allelePresenceForAllTaxa(site1,
WHICH_ALLELE.Major);
208 BitSet rMn = alignment.allelePresenceForAllTaxa(site1,
WHICH_ALLELE.Minor);
209 BitSet cMj = alignment.allelePresenceForAllTaxa(site2,
WHICH_ALLELE.Major);
210 BitSet cMn = alignment.allelePresenceForAllTaxa(site2,
WHICH_ALLELE.Minor);
211 return getLDForSitePair(rMj, rMn, cMj, cMn, minorCnt,
minTaxaForEstimate, -1.0f, fisherExact, site1, site2);
212 }
213
214 private void calculateBitLDForHaplotype(boolean ignoreHets) {
215 //It will ignore hets, make a new Alignment and set all het calls to
missing. Otherwise set the pointer to the old alignment
216 GenotypeTable workingAlignment;
217 if (ignoreHets) {
218 workingAlignment
=GenotypeTableBuilder.getHomozygousInstance(myAlignment);
219 } else {
220 workingAlignment = myAlignment;
Page 5
LinkageDisequilibrium.java
221 }
222 for (long currTest = 0; currTest < myTotalTests; currTest++) {
223 int r = getRowFromIndex(currTest);
224 int c = getColFromIndex(currTest);
225 int currentProgress = (int) (100.0 * ((double) currTest /
(double) myTotalTests));
226 fireProgress(currentProgress);
227 BitSet rMj = workingAlignment.allelePresenceForAllTaxa(r,
WHICH_ALLELE.Major);
228 BitSet rMn = workingAlignment.allelePresenceForAllTaxa(r,
WHICH_ALLELE.Minor);
229 BitSet cMj = workingAlignment.allelePresenceForAllTaxa(c,
WHICH_ALLELE.Major);
230 BitSet cMn = workingAlignment.allelePresenceForAllTaxa(c,
WHICH_ALLELE.Minor);
231 LDResult ldr = getLDForSitePair(rMj, rMn, cMj, cMn, 2,
myMinTaxaForEstimate, -1.0f, myFisherExact,r,c);
232 if (myIsAccumulativeReport) {
233 if (Float.isNaN(ldr.r2())) {
234 myAccumulativeRValueBins[myNumAccumulativeBins]++;
235 } else if (ldr.r2() == 1.0f) {
236 myAccumulativeRValueBins[myNumAccumulativeBins - 1]++;
237 } else {
238 int index = (int) Math.floor(ldr.r2() /
myAccumulativeInterval);
239 myAccumulativeRValueBins[index]++;
240 }
241 } else {
242 long key = getMapKey(r, c);
243 myMapResults.put(key, ldr);
244 }
245
246 } //end of currTest
247 if (myMapResults != null) myMapResults.trimToSize();
248 }
249
250 private void calculateBitLDWithHets() {
251 //Do nothing; not implemented yet
252 myLogger.error("Calculating LD with hets as a third state is not
implemented yet; skipping");
253 throw new IllegalStateException("LinkageDisequilibrium:
calculateBitLDWithHets: Treating hets as a third state is not yet
implemented");
254 }
255
256 public static double calculateDPrime(int countAB, int countAb, int
countaB, int countab, int minTaxaForEstimate) {
257 //this is the normalized D' is Weir Genetic Data Analysis II 1986
Page 6
LinkageDisequilibrium.java
Genetic Data Analysis II 1986
p120
258 double freqR, freqC, freq, countR, countC, nonmissingSampleSize;
259 nonmissingSampleSize = countAB + countAb + countaB + countab;
260 if (nonmissingSampleSize < minTaxaForEstimate) {
261 return Double.NaN;
262 }
263 countR = countab + countAb;
264 countC = countab + countaB;
265 freqR = (nonmissingSampleSize - countR) / nonmissingSampleSize;
266 freqC = (nonmissingSampleSize - countC) / nonmissingSampleSize;
267 // if((freqR==0)||(freqC==0)||(freqR==1)||(freqC==1)) return
-999; //changed by ed 8-13-2004
268 if ((freqR == 0) || (freqC == 0) || (freqR == 1) || (freqC == 1)) {
269 return Double.NaN;
270 }
271 freq = ((double) countAB / nonmissingSampleSize) - (freqR * freqC);
272 if (freq < 0) {
273 return freq / Math.max(-freqR * freqC, -(1 - freqR) * (1 -
freqC));
274 } else {
275 return freq / Math.min((1 - freqR) * freqC, (1 - freqC) * freqR);
276 } //check these equations
277 }
278
279 public static double calculateRSqr(int countAB, int countAb, int
countaB, int countab, int minTaxaForEstimate) {
280 //this is the Hill & Robertson measure as used in Awadella Science
1999 286:2524
281 double freqA, freqB, rsqr, nonmissingSampleSize;
282 nonmissingSampleSize = countAB + countAb + countaB + countab;
283 if (nonmissingSampleSize < minTaxaForEstimate) {
284 return Double.NaN;
285 }
286 freqA = (double) (countAB + countAb) / nonmissingSampleSize;
287 freqB = (double) (countAB + countaB) / nonmissingSampleSize;
288
289 //Through missing data & incomplete datasets some alleles can be
fixed this returns missing value
290 if ((freqA == 0) || (freqB == 0) || (freqA == 1) || (freqB == 1)) {
291 return Double.NaN;
292 }
293
294 rsqr = ((double) countAB / nonmissingSampleSize) * ((double)
countab / nonmissingSampleSize);
295 rsqr -= ((double) countaB / nonmissingSampleSize) * ((double)
countAb / nonmissingSampleSize);
296 rsqr *= rsqr;
297 rsqr /= freqA * (1 - freqA) * freqB * (1 - freqB);
Page 7
LinkageDisequilibrium.java
298 return rsqr;
299 }
300
301
302 /**
303 * Method for estimating LD between a pair of bit sets. Since there can
be tremendous missing data, minimum minor and
304 * minimum site counts ensure that meaningful results are estimated.
Site indices are merely there for annotating the LDResult.
305 * @param rMj site 1 major alleles
306 * @param rMn site 1 minor alleles
307 * @param cMj site 2 major alleles
308 * @param cMn site 2 minor alleles
309 * @param minMinorCnt minimum minor allele count after intersection
310 * @param minCnt minimum count after intersection
311 * @param minR2 results below this r2 are ignored for p-value calculation
(save times)
312 * @param myFisherExact
313 * @param site1Index annotation of LDresult with sites indices
314 * @param site2Index annotation of LDresult with sites indices
315 * @return
316 */
317 public static LDResult getLDForSitePair(BitSet rMj, BitSet rMn, BitSet
cMj, BitSet cMn,
318 int minMinorCnt, int minCnt, float minR2, FisherExact
myFisherExact, int site1Index, int site2Index) {
319 // float[] results = {Float.NaN, Float.NaN, Float.NaN, Float.NaN};
320 if(myFisherExact==null) myFisherExact=FisherExact.getInstance((2 *
(int)rMj.size()) + 10);
321 LDResult.Builder results = new
LDResult.Builder(site1Index,site2Index);
322 int n = 0;
323 int[][] contig = new int[2][2];
324 n += contig[1][1] = (int) OpenBitSet.intersectionCount(rMn, cMn);
325 n += contig[1][0] = (int) OpenBitSet.intersectionCount(rMn, cMj);
326 if (contig[1][0] + contig[1][1] < minMinorCnt) {
327 return results.build();
328 }
329 n += contig[0][1] = (int) OpenBitSet.intersectionCount(rMj, cMn);
330 if (contig[0][1] + contig[1][1] < minMinorCnt) {
331 return results.build();
332 }
333 n += contig[0][0] = (int) OpenBitSet.intersectionCount(rMj, cMj);
334 results.n(n);
335 if (n < minCnt) {
336 return results.build();
337 }
338 double rValue = LinkageDisequilibrium.calculateRSqr(contig[0][0],
Page 8
LinkageDisequilibrium.java
= LinkageDisequilibrium.calculateRSqr(contig[0][0],
contig[1][0], contig[0][1], contig[1][1], minCnt);
339 results.r2((float)rValue);
340 if (Double.isNaN(rValue)) {
341 return results.build();
342 }
343 results.dprime((float)
LinkageDisequilibrium.calculateDPrime(contig[0][0], contig[1][0], contig[0]
[1], contig[1][1], minCnt));
344 if (rValue < minR2) {
345 return results.build();
346 }
347 double pValue = myFisherExact.getTwoTailedP(contig[0][0], contig[1]
[0], contig[0][1], contig[1][1]);
348 results.p((float) pValue);
349 return results.build();
350 }
351
352 private int getRowFromIndex(long index) {
353
354 int row = 0;
355 int n = myAlignment.numberOfSites();
356 int w = myWindowSize;
357
358 if (myCurrDesign == testDesign.SlidingWindow && n > w + 1 && index >=
w * (w + 1) / (double) 2) {
359 row = (int) Math.ceil(((double) index + 1 - w * (w + 1) / 2 + w *
w) / w);
360 } else if (myCurrDesign == testDesign.SiteByAll) {
361 if (index < myTestSite) {
362 row = myTestSite;
363 } else {
364 row = (int) index + 1;
365 }
366 } else if (myCurrDesign == testDesign.SiteList) {
367
368 int k = (int) Math.ceil((n - 1.5) - Math.sqrt((n - 1.5) * (n -
1.5) + 2 * (n - index - 2)));
369 int m = n * (k + 1) - ((k + 1) * (k + 2) / 2) - 1;
370
371 if (m - index > n - mySiteList[k] - 1) {
372 row = mySiteList[k];
373 } else {
374 row = n - 1 - m + (int) index;
375 }
376 } else {
377 row = (int) Math.ceil((Math.sqrt(8 * (index + 1) + 1) - 1) / 2);
378 }
379
Page 9
LinkageDisequilibrium.java
380 return row;
381 }
382
383 private int getColFromIndex(long index) {
384
385 int row = getRowFromIndex(index);
386 int col = 0;
387 int n = myAlignment.numberOfSites();
388 int w = myWindowSize;
389
390 if (myCurrDesign == testDesign.SlidingWindow && n > w + 1 && index >=
w * (w + 1) / (double) 2) {
391 col = (int) ((row - 1 - (double) w * (w + 1) / 2 - w * (row - w)
+ 1 + index));
392 } else if (myCurrDesign == testDesign.SiteByAll) {
393 if (index < myTestSite) {
394 col = (int) index;
395 } else {
396 col = myTestSite;
397 }
398 } else if (myCurrDesign == testDesign.SiteList) {
399
400 int k = (int) Math.ceil((n - 1.5) - Math.sqrt((n - 1.5) * (n -
1.5) + 2 * (n - index - 2)));
401 int m = n * (k + 1) - ((k + 1) * (k + 2) / 2) - 1;
402
403 if (row != mySiteList[k]) {
404 col = mySiteList[k];
405 } else {
406 col = n - m + (int) index - 2;
407 int yy = Arrays.binarySearch(mySiteList, row);
408 int y = Arrays.binarySearch(mySiteList, col);
409 while (yy + (y + 1) != 0) {
410 if (y < 0) {
411 y = -(y + 1);
412 }
413 col = col - (yy - y);
414 yy = y;
415 y = Arrays.binarySearch(mySiteList, col);
416
417 }
418 }
419 } else {
420 col = row - (row * (row + 1) / 2 - (int) index);
421 }
422
423 return col;
424 }
Page 10
LinkageDisequilibrium.java
425
426 /**
427 * Returns P-value estimate for a given pair of numSites. If there were
only
428 * 2 alleles at each locus, then the Fisher Exact P-value (one-tail) is
429 * returned. If more states then the permuted Monte Carlo test is used.
430 *
431 * @param r is site 1
432 * @param c is site 2
433 * @return P-value
434 */
435 public double getPVal(int r, int c) {
436 long key = getMapKey(r, c);
437 LDResult result = (LDResult) myMapResults.get(key);
438 if (result == null) {
439 return Float.NaN;
440 }
441 return result.p();
442 }
443
444 /**
445 * Get number of gametes included in LD calculations (after missing data
was
446 * excluded)
447 *
448 * @param r is site 1
449 * @param c is site 2
450 * @return number of gametes
451 */
452 public int getSampleSize(int r, int c) {
453 long key = getMapKey(r, c);
454 LDResult result = (LDResult) myMapResults.get(key);
455 if (result == null) {
456 return 0;
457 }
458 return result.n();
459 }
460
461 /**
462 * Returns D' estimate for a given pair of numSites
463 *
464 * @param r is site 1
465 * @param c is site 2
466 * @return D'
467 */
468 public float getDPrime(int r, int c) {
469 long key = getMapKey(r, c);
470 LDResult result = (LDResult) myMapResults.get(key);
Page 11
LinkageDisequilibrium.java
471 if (result == null) {
472 return Float.NaN;
473 }
474 return result.dPrime();
475 }
476
477 /**
478 * Returns r^2 estimate for a given pair of numSites
479 *
480 * @param r is site 1
481 * @param c is site 2
482 * @return r^2
483 */
484 public float getRSqr(int r, int c) {
485 long key = getMapKey(r, c);
486 LDResult result = (LDResult) myMapResults.get(key);
487 if (result == null) {
488 return Float.NaN;
489 }
490 return result.r2();
491 }
492
493 public int getX(int row) {
494 return getColFromIndex(row);
495 }
496
497 public int getY(int row) {
498 return getRowFromIndex(row);
499 }
500
501 /**
502 * Returns the counts of the numSites in the alignment
503 */
504 public int getSiteCount() {
505 return myAlignment.numberOfSites();
506 }
507
508 /**
509 * Returns an annotated aligment if one was used for this LD this could
be
510 * used to access information of locus position
511 */
512 public GenotypeTable getAlignment() {
513 return myAlignment;
514 }
515
516 /**
517 * Returns representation of the LD results as a string
Page 12
LinkageDisequilibrium.java
518 */
519 public String toString() {
520 String delimit = "\t";
521 StringWriter sw = new StringWriter();
522 Object[] colNames = getTableColumnNames();
523 for (int j = 0; j < colNames.length; j++) {
524 sw.write(colNames[j].toString());
525 sw.write(delimit);
526 }
527 sw.write("\n");
528
529 for (long r = 0; r < myTotalTests; r++) {
530 Object[] theRow = getRow(r);
531 for (int i = 0; i < theRow.length; i++) {
532 sw.write(theRow[i].toString());
533 sw.write(delimit);
534 }
535 }
536 return sw.toString();
537 }
538
539 @Override
540 public Object[] getTableColumnNames() {
541 String[] annotatedLabels = null;
542 if (myIsAccumulativeReport) {
543 annotatedLabels = new String[]{"R2BinMin", "R2BinMax", "Count"};
544 } else {
545 annotatedLabels = new String[]{"Locus1", "Position1", "Site1",
546 "NumberOfStates1", "States1", "Frequency1", "Locus2",
"Position2",
547 "Site2", "NumberOfStates2", "States2", "Frequency2",
"Dist_bp", "R^2", "DPrime", "pDiseq", "N"};
548 }
549 return annotatedLabels;
550 }
551
552 @Override
553 public Object[] getRow(long row) {
554
555 if (myIsAccumulativeReport) {
556 Object[] data = new Object[3];
557 if (row == myNumAccumulativeBins) {
558 data[0] = Double.NaN;
559 data[1] = Double.NaN;
560 data[2] = Integer.valueOf(myAccumulativeRValueBins[(int)
row]);
561 } else {
562 double start = myAccumulativeInterval * (double) row;
Page 13
LinkageDisequilibrium.java
563 data[0] = Double.valueOf(start);
564 data[1] = Double.valueOf(start + myAccumulativeInterval);
565 data[2] = Integer.valueOf(myAccumulativeRValueBins[(int)
row]);
566 }
567 return data;
568 } else {
569 int labelOffset = 0;
570 Object[] data = new Object[17];
571
572 int r = getRowFromIndex(row);
573 int c = getColFromIndex(row);
574
575 String rState = myAlignment.majorAlleleAsString(r) + ":" +
myAlignment.minorAlleleAsString(r);
576 Integer rStr = Integer.valueOf(r);
577
578 String cState = myAlignment.majorAlleleAsString(c) + ":" +
myAlignment.minorAlleleAsString(c);
579 Integer cStr = Integer.valueOf(c);
580
581 data[labelOffset++] = myAlignment.chromosomeName(r);
582 data[labelOffset++] =
Integer.valueOf(myAlignment.chromosomalPosition(r));
583 data[labelOffset++] = rStr;
584
585 data[labelOffset++] = IntegerTwo;
586 data[labelOffset++] = rState;
587 data[labelOffset++] = NotImplemented;
588 data[labelOffset++] = myAlignment.chromosomeName(c);
589 data[labelOffset++] =
Integer.valueOf(myAlignment.chromosomalPosition(c));
590 data[labelOffset++] = cStr;
591
592 data[labelOffset++] = IntegerTwo;
593 data[labelOffset++] = cState;
594 data[labelOffset++] = NotImplemented;
595 if
(myAlignment.chromosomeName(r).equals(myAlignment.chromosomeName(c))) {
596 data[labelOffset++] =
Integer.valueOf(Math.abs(myAlignment.chromosomalPosition(r) -
myAlignment.chromosomalPosition(c)));
597 } else {
598 data[labelOffset++] = NA;
599 }
600 data[labelOffset++] = getRSqr(r, c);
601 data[labelOffset++] = getDPrime(r, c);
602 data[labelOffset++] = getPVal(r, c);
Page 14
LinkageDisequilibrium.java
603 data[labelOffset++] = getSampleSize(r, c);
604
605 return data;
606 }
607
608 }
609
610 @Override
611 public String getTableTitle() {
612 return "Linkage Disequilibrium";
613 }
614
615 @Override
616 public int getColumnCount() {
617 return getTableColumnNames().length;
618 }
619
620 @Override
621 public long getRowCount() {
622 if (myIsAccumulativeReport) {
623 return myNumAccumulativeBins + 1;
624 } else {
625 return myTotalTests;
626 }
627 }
628
629 @Override
630 public long getElementCount() {
631 return getRowCount() * getColumnCount();
632 }
633
634 @Override
635 public Object getValueAt(long row, int col) {
636 return getRow(row)[col];
637 }
638
639 protected void fireProgress(int percent) {
640 if (percent < 0) {
641 percent = -percent;
642 }
643 if (myListener != null) {
644 myListener.progress(percent, null);
645 }
646 }
647
648
649 }
650
Page 15
LinkageDisequilibrium.java
651
652
653
654
Page 16