1#! /usr/bin/env python3
2
3import subprocess
4import sys
5
6def main():
7    bfile_names = ['dummy_cc1', 'dummy_cc2', 'dummy1', 'dummy2', 'trio']
8    bfile_names_cc = ['dummy_cc1', 'dummy_cc2'] # there must be at least 2
9    bfile_names_qt = ['dummy1', 'dummy2']
10    bfile_names_fam = ['trio']
11
12    for bfn in bfile_names:
13        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --nonfounders --max-maf 0.4999 --recode --out test1', shell=True)
14        if not retval == 0:
15            print('Unexpected error in --file/--maf/--max-maf/--nonfounders/--recode/--write-snplist test.')
16            sys.exit(1)
17        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --nonfounders --max-maf 0.4999 --recode --out test2', shell=True)
18        if not retval == 0:
19            print('Unexpected error in --file/--maf/--max-maf/--nonfounders/--recode/--write-snplist test.')
20            sys.exit(1)
21        retval = subprocess.call('diff -q test1.ped test2.ped', shell=True)
22        if not retval == 0:
23            print('--file/--maf/--max-maf/--nonfounders/--recode/--write-snplist test failed.')
24            sys.exit(1)
25        retval = subprocess.call('diff -q test1.map test2.map', shell=True)
26        if not retval == 0:
27            print('--file/--maf/--max-maf/--nonfounders/--recode/--write-snplist test failed.')
28            sys.exit(1)
29
30        retval = subprocess.call('plink107 --noweb --file test1 --silent --nonfounders --maf 0.04999 --write-snplist --out test1', shell=True)
31        if not retval == 0:
32            print('Unexpected error in --file/--maf/--max-maf/--nonfounders/--recode/--write-snplist test.')
33            sys.exit(1)
34        retval = subprocess.call('plink19 --file test2 --silent --nonfounders --maf 0.04999 --write-snplist --out test2', shell=True)
35        if not retval == 0:
36            print('Unexpected error in --file/--maf/--max-maf/--nonfounders/--recode/--write-snplist test.')
37            sys.exit(1)
38        subprocess.call('diff -q test1.snplist test2.snplist', shell=True)
39        if not retval == 0:
40            print('--file/--maf/--max-maf/--nonfounders/--recode/--write-snplist test failed.')
41            sys.exit(1)
42    print('--file/--maf/--max-maf/--nonfounders/--recode/--write-snplist test passed.')
43
44    # --hwe takes case/control status into account, and VCF doesn't store that,
45    # so this test is quantitative-trait only
46    for bfn in bfile_names_qt:
47        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --recode vcf --out test2', shell=True)
48        if not retval == 0:
49            print('Unexpected error in --hwe/--recode vcf/--vcf test.')
50            sys.exit(1)
51        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --hwe 0.009999 --write-snplist --out test1', shell=True)
52        if not retval == 0:
53            print('Unexpected error in --hwe/--recode vcf/--vcf test.')
54            sys.exit(1)
55        retval = subprocess.call('plink19 --vcf test2.vcf --silent --hwe 0.009999 --write-snplist --out test2', shell=True)
56        if not retval == 0:
57            print('Unexpected error in --hwe/--recode vcf/--vcf test.')
58            sys.exit(1)
59        retval = subprocess.call('diff -q test1.snplist test2.snplist', shell=True)
60        if not retval == 0:
61            print('--hwe/--recode vcf/--vcf test failed.')
62            sys.exit(1)
63    print('--hwe/--recode vcf/--vcf test passed.')
64
65    for bfn in bfile_names:
66        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --nonfounders --max-maf 0.4999 --recode --transpose --out test1', shell=True)
67        if not retval == 0:
68            print('Unexpected error in --missing/--recode transpose/--tfile test.')
69            sys.exit(1)
70        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --nonfounders --max-maf 0.4999 --recode transpose --out test2', shell=True)
71        if not retval == 0:
72            print('Unexpected error in --missing/--recode transpose/--tfile test.')
73            sys.exit(1)
74        retval = subprocess.call('diff -q test1.tped test2.tped', shell=True)
75        if not retval == 0:
76            print('--missing/--recode transpose/--tfile test failed.')
77            sys.exit(1)
78        retval = subprocess.call('diff -q test1.tfam test2.tfam', shell=True)
79        if not retval == 0:
80            print('--missing/--recode transpose/--tfile test failed.')
81            sys.exit(1)
82
83        retval = subprocess.call('plink107 --noweb --tfile test1 --silent --missing --out test1', shell=True)
84        if not retval == 0:
85            print('Unexpected error in --missing/--recode transpose/--tfile test.')
86            sys.exit(1)
87        retval = subprocess.call('plink19 --tfile test2 --silent --missing --out test2', shell=True)
88        if not retval == 0:
89            print('Unexpected error in --missing/--recode transpose/--tfile test.')
90            sys.exit(1)
91        subprocess.call('diff -q test1.imiss test2.imiss', shell=True)
92        if not retval == 0:
93            print('--missing/--recode transpose/--tfile test failed.')
94            sys.exit(1)
95        subprocess.call('diff -q test1.lmiss test2.lmiss', shell=True)
96        if not retval == 0:
97            print('--missing/--recode transpose/--tfile test failed.')
98            sys.exit(1)
99    print('--missing/--recode transpose/--tfile test passed.')
100
101    retval = subprocess.call('plink107 --noweb --bfile ' + bfile_names_cc[0] + ' --silent --bmerge ' + bfile_names_cc[1] + '.bed ' + bfile_names_cc[1] + '.bim ' + bfile_names_cc[1] + '.fam --max-maf 0.4999 --make-bed --out test1', shell=True)
102    if not retval == 0:
103        print('Unexpected error in --bmerge/--make-bed test.')
104        sys.exit(1)
105    retval = subprocess.call('plink19 --bfile ' + bfile_names_cc[0] + ' --silent --bmerge ' + bfile_names_cc[1] + ' --max-maf 0.4999 --make-bed --out test2', shell=True)
106    if not retval == 0:
107        print('Unexpected error in --bmerge/--make-bed test.')
108        sys.exit(1)
109    retval = subprocess.call('diff -q test1.bed test2.bed', shell=True)
110    if not retval == 0:
111        print('--bmerge/--make-bed test failed.')
112        sys.exit(1)
113    retval = subprocess.call('diff -q test1.bim test2.bim', shell=True)
114    if not retval == 0:
115        print('--bmerge/--make-bed test failed.')
116        sys.exit(1)
117    retval = subprocess.call('diff -q test1.bim test2.bim', shell=True)
118    if not retval == 0:
119        print('--bmerge/--make-bed test failed.')
120        sys.exit(1)
121    print('--bmerge/--make-bed test passed.')
122
123    subprocess.call('rm -f test2.bim', shell=True)
124    retval = subprocess.call('plink19 --bfile ' + bfile_names_cc[0] + ' --silent --bmerge ' + bfile_names_cc[1] + ' --max-maf 0.4999 --make-just-bim --out test2', shell=True)
125    if not retval == 0:
126        print('Unexpected error in --make-just-bim test.')
127        sys.exit(1)
128    retval = subprocess.call('diff -q test1.bim test2.bim', shell=True)
129    if not retval == 0:
130        print('--make-just-bim test failed.')
131        sys.exit(1)
132    print('--make-just-bim test passed.')
133
134    subprocess.call('rm -f test2.fam', shell=True)
135    retval = subprocess.call('plink19 --bfile ' + bfile_names_cc[0] + ' --silent --bmerge ' + bfile_names_cc[1] + ' --make-just-fam --out test2', shell=True)
136    if not retval == 0:
137        print('Unexpected error in --make-just-bim test.')
138        sys.exit(1)
139    retval = subprocess.call('diff -q test1.fam test2.fam', shell=True)
140    if not retval == 0:
141        print('--make-just-fam test failed.')
142        sys.exit(1)
143    print('--make-just-fam test passed.')
144
145    for bfn in bfile_names_cc:
146        # force at least 14 to be missing out of 513...
147        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --geno 0.06049 --max-maf 0.4999 --write-snplist --out test2', shell=True)
148        if not retval == 0:
149            print('Unexpected error in --extract/--freq/--geno test.')
150            sys.exit(1)
151        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --freq --extract test2.snplist --out test1', shell=True)
152        if not retval == 0:
153            print('Unexpected error in --extract/--freq/--geno test.')
154            sys.exit(1)
155        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --freq --extract test2.snplist --out test2', shell=True)
156        if not retval == 0:
157            print('Unexpected error in --extract/--freq/--geno test.')
158            sys.exit(1)
159        retval = subprocess.call('diff -q test1.frq test2.frq', shell=True)
160        if not retval == 0:
161            print('--extract/--freq/--geno test failed.')
162            sys.exit(1)
163    print('--extract/--freq/--geno test passed.')
164
165    for bfn in bfile_names_fam:
166        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --covar ' + bfn + '.fam --covar-number 3 --filter-founders --write-covar --out test1', shell=True)
167        if not retval == 0:
168            print('Unexpected error in --covar/--covar-number/--filter-founders/--write-covar test.')
169            sys.exit(1)
170        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --covar ' + bfn + '.fam --covar-number 3 --filter-founders --write-covar --out test2', shell=True)
171        if not retval == 0:
172            print('Unexpected error in --covar/--covar-number/--filter-founders/--write-covar test.')
173            sys.exit(1)
174        retval = subprocess.call('diff -q test1.cov test2.cov', shell=True)
175        if not retval == 0:
176            print('--covar/--covar-number/--filter-founders/--write-covar test failed.')
177            sys.exit(1)
178    print('--covar/--covar-number/--filter-founders/--write-covar test passed.')
179
180    for bfn in bfile_names:
181        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --cluster --K 2 --out test1', shell=True)
182        if not retval == 0:
183            print('Unexpected error in --cluster/--filter-females/--within/--write-cluster test.')
184            sys.exit(1)
185        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --cluster only2 old-tiebreaks --K 2 --out ' + bfn, shell=True)
186        if not retval == 0:
187            print('Unexpected error in --cluster/--filter-females/--within/--write-cluster test.')
188            sys.exit(1)
189        retval = subprocess.call('diff -q test1.cluster2 ' + bfn + '.cluster2', shell=True)
190        if not retval == 0:
191            print('--cluster/--filter-females/--within/--write-cluster test failed.')
192            sys.exit(1)
193        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --within ' + bfn + '.cluster2 --filter-females --write-cluster --out test1', shell=True)
194        if not retval == 0:
195            print('Unexpected error in --cluster/--filter-females/--within/--write-cluster test.')
196            sys.exit(1)
197        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --within ' + bfn + '.cluster2 --filter-females --write-cluster --out test2', shell=True)
198        if not retval == 0:
199            print('Unexpected error in --cluster/--filter-females/--within/--write-cluster test.')
200            sys.exit(1)
201        retval = subprocess.call('diff -q test1.clst test2.clst', shell=True)
202        if not retval == 0:
203            print('--cluster/--filter-females/--within/--write-cluster test failed.')
204            sys.exit(1)
205    print('--cluster/--filter-females/--within/--write-cluster test passed.')
206
207    for bfn in bfile_names:
208        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --make-set set.txt --write-set --out test1', shell=True)
209        if not retval == 0:
210            print('Unexpected error in --make-set/--set/--set-table/--write-set test.')
211            sys.exit(1)
212        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --make-set set.txt --write-set --out test2', shell=True)
213        if not retval == 0:
214            print('Unexpected error in --make-set/--set/--set-table/--write-set test.')
215            sys.exit(1)
216        retval = subprocess.call('diff -q test1.set test2.set', shell=True)
217        if not retval == 0:
218            print('--make-set/--set/--set-table/--write-set test failed.')
219            sys.exit(1)
220        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --make-set set.txt --set-table --out test1', shell=True)
221        if not retval == 0:
222            print('Unexpected error in --make-set/--set/--set-table/--write-set test.')
223            sys.exit(1)
224        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --set test2.set --set-table --out test2', shell=True)
225        if not retval == 0:
226            print('Unexpected error in --make-set/--set/--set-table/--write-set test.')
227            sys.exit(1)
228        # PLINK 1.07 generates a .set.table file with a double-tab after the
229        # third column, which we deliberately don't replicate.  Remove it and
230        # the header row (which doesn't have the double-tab) before diffing.
231        retval = subprocess.call('cat test1.set.table | tail -n +2 | cut -f 1-3,5- > test1.set.table2', shell=True)
232        if not retval == 0:
233            print('Unexpected error in --make-set/--set/--set-table/--write-set test.')
234            sys.exit(1)
235        retval = subprocess.call('cat test2.set.table | tail -n +2 > test2.set.table2', shell=True)
236        if not retval == 0:
237            print('Unexpected error in --make-set/--set/--set-table/--write-set test.')
238            sys.exit(1)
239        retval = subprocess.call('diff -q test1.set.table2 test2.set.table2', shell=True)
240        if not retval == 0:
241            print('--make-set/--set/--set-table/--write-set test failed.')
242            sys.exit(1)
243    print('--make-set/--set/--set-table/--write-set test passed.')
244
245    retval = subprocess.call('plink19 --bfile ' + bfile_names_cc[1] + ' --silent --recode --out test2', shell=True)
246    if not retval == 0:
247        print('Unexpected error in --merge test.')
248        sys.exit(1)
249    retval = subprocess.call('plink19 --bfile ' + bfile_names_cc[0] + ' --silent --merge test2 --max-maf 0.4999 --make-bed --out test2', shell=True)
250    if not retval == 0:
251        print('Unexpected error in --merge test.')
252        sys.exit(1)
253    retval = subprocess.call('diff -q test1.bed test2.bed', shell=True)
254    if not retval == 0:
255        print('--merge test failed.')
256        sys.exit(1)
257    retval = subprocess.call('diff -q test1.bim test2.bim', shell=True)
258    if not retval == 0:
259        print('--merge test failed.')
260        sys.exit(1)
261    retval = subprocess.call('diff -q test1.bim test2.bim', shell=True)
262    if not retval == 0:
263        print('--merge test failed.')
264        sys.exit(1)
265    print('--merge test passed.')
266
267    subprocess.call('rm -f merge_list.txt', shell=True)
268    retval = subprocess.call('echo ' + bfile_names_cc[0] + '.bed ' + bfile_names_cc[0] + '.bim ' + bfile_names_cc[0] + '.fam > merge_list.txt', shell=True)
269    if not retval == 0:
270        print('Unexpected error in --merge-list test.')
271        sys.exit(1)
272    retval = subprocess.call('echo ' + bfile_names_cc[1] + '.bed ' + bfile_names_cc[1] + '.bim ' + bfile_names_cc[1] + '.fam >> merge_list.txt', shell=True)
273    if not retval == 0:
274        print('Unexpected error in --merge-list test.')
275        sys.exit(1)
276    retval = subprocess.call('plink19 --merge-list merge_list.txt --silent --max-maf 0.4999 --make-bed --out test2', shell=True)
277    if not retval == 0:
278        print('Unexpected error in --merge-list test.')
279        sys.exit(1)
280    retval = subprocess.call('diff -q test1.bed test2.bed', shell=True)
281    if not retval == 0:
282        print('--merge-list test failed.')
283        sys.exit(1)
284    retval = subprocess.call('diff -q test1.bim test2.bim', shell=True)
285    if not retval == 0:
286        print('--merge-list test failed.')
287        sys.exit(1)
288    retval = subprocess.call('diff -q test1.bim test2.bim', shell=True)
289    if not retval == 0:
290        print('--merge-list test failed.')
291        sys.exit(1)
292    subprocess.call('rm -f merge_list.txt', shell=True)
293    print('--merge-list test passed.')
294
295    for bfn in bfile_names_cc:
296        # diff error likely at MAF = 0.4875 due to rounding
297        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --flip-scan --mind 0.05399 --maf 0.4876 --max-maf 0.4999 --out test1', shell=True)
298        if not retval == 0:
299            print('Unexpected error in --flip-scan/--mind test.')
300            sys.exit(1)
301        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --flip-scan --mind 0.05399 --maf 0.4876 --max-maf 0.4999 --out test2', shell=True)
302        if not retval == 0:
303            print('Unexpected error in --flip-scan/--mind test.')
304            sys.exit(1)
305        retval = subprocess.call('diff -q test1.flipscan test2.flipscan', shell=True)
306        if not retval == 0:
307            print('--flip-scan/--mind test failed.')
308            sys.exit(1)
309    print('--flip-scan/--mind test passed.')
310
311
312    # don't bother with --test-mishap for now due to EM phasing algorithm
313    # change
314
315    for bfn in bfile_names_cc:
316        # force at least 14 to be missing out of 513...
317        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --geno 0.0254 --write-snplist --out test1', shell=True)
318        if not retval == 0:
319            print('Unexpected error in --exclude/--hardy test.')
320            sys.exit(1)
321        # ...but no more than 31 out of 512.
322
323        # --hardy + --geno order of operations has changed, for good reason.
324        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --exclude test1.snplist --geno 0.06049 --write-snplist --out test2', shell=True)
325        if not retval == 0:
326            print('Unexpected error in --exclude/--hardy test.')
327            sys.exit(1)
328
329        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --extract test2.snplist --hardy --out test1', shell=True)
330        if not retval == 0:
331            print('Unexpected error in --exclude/--hardy test.')
332            sys.exit(1)
333        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --extract test2.snplist --hardy --out test2', shell=True)
334        if not retval == 0:
335            print('Unexpected error in --exclude/--hardy test.')
336            sys.exit(1)
337        # skip column 8 due to likelihood of floating point error
338        # note that leading space(s) cause it to be column 9 after tr
339        retval = subprocess.call("cat test1.hwe | tr -s ' ' '\t' | cut -f 1-8,10 > test1.hwe2", shell=True)
340        retval = subprocess.call("cat test2.hwe | tr -s ' ' '\t' | cut -f 1-8,10 > test2.hwe2", shell=True)
341        retval = subprocess.call('diff -q test1.hwe2 test2.hwe2', shell=True)
342        if not retval == 0:
343            print('--exclude/--hardy test failed.')
344            sys.exit(1)
345    print('--exclude/--hardy test passed.')
346
347    for bfn in bfile_names_fam:
348        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --mendel --out test1', shell=True)
349        if not retval == 0:
350            print('Unexpected error in --mendel test.')
351            sys.exit(1)
352        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --mendel --out test2', shell=True)
353        if not retval == 0:
354            print('Unexpected error in --mendel test.')
355            sys.exit(1)
356        retval = subprocess.call('diff -q test1.mendel test2.mendel', shell=True)
357        if not retval == 0:
358            print('--mendel test failed.')
359            sys.exit(1)
360        retval = subprocess.call('diff -q test1.imendel test2.imendel', shell=True)
361        if not retval == 0:
362            print('--mendel test failed.')
363            sys.exit(1)
364        retval = subprocess.call('diff -q test1.fmendel test2.fmendel', shell=True)
365        if not retval == 0:
366            print('--mendel test failed.')
367            sys.exit(1)
368        retval = subprocess.call('diff -q test1.lmendel test2.lmendel', shell=True)
369        if not retval == 0:
370            print('--mendel test failed.')
371            sys.exit(1)
372    print('--mendel test passed.')
373
374    for bfn in bfile_names:
375        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --recode oxford --out test2', shell=True)
376        if not retval == 0:
377            print('Unexpected error in --data/--het/--recode oxford test.')
378            sys.exit(1)
379        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --het --nonfounders --out test1', shell=True)
380        if not retval == 0:
381            print('Unexpected error in --data/--het/--recode oxford test.')
382            sys.exit(1)
383        retval = subprocess.call('plink19 --data test2 --silent --het --out test2', shell=True)
384        if not retval == 0:
385            print('Unexpected error in --data/--het/--recode oxford test.')
386            sys.exit(1)
387        retval = subprocess.call('diff -q test1.het test2.het', shell=True)
388        if not retval == 0:
389            print('--data/--het/--recode oxford test failed.')
390            sys.exit(1)
391    print('--data/--het/--recode oxford test passed.')
392
393    for bfn in bfile_names_cc:
394        retval = subprocess.call('rm -f test1.bim.tmp', shell=True)
395        retval = subprocess.call('cat ' + bfn + ".bim | sed 's/^1/23/' > test1.bim.tmp", shell=True)
396        if not retval == 0:
397            print('Unexpected error in --check-sex/--impute-sex/--read-freq test.')
398            sys.exit(1)
399        retval = subprocess.call('plink19 --bed ' + bfn + '.bed --bim test1.bim.tmp --fam ' + bfn + '.fam --silent --freq --out test1', shell=True)
400        if not retval == 0:
401            print('Unexpected error in --check-sex/--impute-sex/--read-freq test.')
402            sys.exit(1)
403        retval = subprocess.call('plink107 --noweb --bed ' + bfn + '.bed --bim test1.bim.tmp --fam ' + bfn + '.fam --silent --read-freq test1.frq --check-sex --out test1', shell=True)
404        if not retval == 0:
405            print('Unexpected error in --check-sex/--impute-sex/--read-freq test.')
406            sys.exit(1)
407        retval = subprocess.call('plink19 --bed ' + bfn + '.bed --bim test1.bim.tmp --fam ' + bfn + '.fam --silent --read-freq test1.frq --check-sex --out test2', shell=True)
408        if not retval == 0:
409            print('Unexpected error in --check-sex/--impute-sex/--read-freq test.')
410            sys.exit(1)
411        retval = subprocess.call('diff -q test1.sexcheck test2.sexcheck', shell=True)
412        if not retval == 0:
413            print('--check-sex/--impute-sex/--read-freq test failed.')
414            sys.exit(1)
415        retval = subprocess.call('plink107 --noweb --bed ' + bfn + '.bed --bim test1.bim.tmp --fam ' + bfn + '.fam --silent --read-freq test1.frq --maf 0.4876 --max-maf 0.4999 --impute-sex --make-bed --out test1', shell=True)
416        if not retval == 0:
417            print('Unexpected error in --check-sex/--impute-sex/--read-freq test.')
418            sys.exit(1)
419        retval = subprocess.call('plink19 --bed ' + bfn + '.bed --bim test1.bim.tmp --fam ' + bfn + '.fam --silent --read-freq test1.frq --maf 0.4876 --max-maf 0.4999 --impute-sex --make-bed --out test2', shell=True)
420        if not retval == 0:
421            print('Unexpected error in --check-sex/--impute-sex/--read-freq test.')
422            sys.exit(1)
423        retval = subprocess.call('diff -q test1.sexcheck test2.sexcheck', shell=True)
424        if not retval == 0:
425            print('--check-sex/--impute-sex/--read-freq test failed.')
426            sys.exit(1)
427        retval = subprocess.call('diff -q test1.bed test2.bed', shell=True)
428        if not retval == 0:
429            print('--check-sex/--impute-sex/--read-freq test failed.')
430            sys.exit(1)
431        retval = subprocess.call('diff -q test1.bim test2.bim', shell=True)
432        if not retval == 0:
433            print('--check-sex/--impute-sex/--read-freq test failed.')
434            sys.exit(1)
435        retval = subprocess.call('diff -q test1.fam test2.fam', shell=True)
436        if not retval == 0:
437            print('--check-sex/--impute-sex/--read-freq test failed.')
438            sys.exit(1)
439    print('--check-sex/--impute-sex/--read-freq test passed.')
440
441    # Skip --indep-pairwise for now since harmless minor differences are
442    # expected.
443
444    # floating-point error is more likely to affect --r, so we just test --r2
445    for bfn in bfile_names:
446        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --r2 --out test1', shell=True)
447        if not retval == 0:
448            print('Unexpected error in --r2 test.')
449            sys.exit(1)
450        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --r2 --out test2', shell=True)
451        if not retval == 0:
452            print('Unexpected error in --r2 test.')
453            sys.exit(1)
454        retval = subprocess.call('diff -q test1.ld test2.ld', shell=True)
455        if not retval == 0:
456            print('--r2 test failed.')
457            sys.exit(1)
458    print('--r2 test passed.')
459
460    for bfn in bfile_names:
461        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --make-set set.txt --write-set --out test1', shell=True)
462        if not retval == 0:
463            print('Unexpected error in --gene/--show-tags test.')
464            sys.exit(1)
465        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --set test1.set --gene set2 --show-tags all --tag-r2 0.031 --out test1', shell=True)
466        if not retval == 0:
467            print('Unexpected error in --gene/--show-tags test.')
468            sys.exit(1)
469        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --make-set set.txt --gene set2 --show-tags all --tag-r2 0.031 --out test2', shell=True)
470        if not retval == 0:
471            print('Unexpected error in --gene/--show-tags test.')
472            sys.exit(1)
473        # ignore column 7 since we changed the interval length definition
474        retval = subprocess.call("cat test1.tags.list | sed 's/^[[:space:]]*//g' | tr -s ' ' '\t' | cut -f 1-6,8 > test1.tags.list2", shell=True)
475        if not retval == 0:
476            print('Unexpected error in --gene/--show-tags test.')
477            sys.exit(1)
478        retval = subprocess.call("cat test2.tags.list | sed 's/^[[:space:]]*//g' | tr -s ' ' '\t' | cut -f 1-6,8 > test2.tags.list2", shell=True)
479        if not retval == 0:
480            print('Unexpected error in --gene/--show-tags test.')
481            sys.exit(1)
482        retval = subprocess.call('diff -q test1.tags.list2 test2.tags.list2', shell=True)
483        if not retval == 0:
484            print('--gene/--show-tags test failed.')
485            sys.exit(1)
486    print('--gene/--show-tags test passed.')
487
488    # skip --blocks for now since test files lack the necessary LD
489
490    for bfn in bfile_names:
491        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --cluster --distance-matrix --out test1', shell=True)
492        if not retval == 0:
493            print('Unexpected error in --distance-matrix test.')
494            sys.exit(1)
495        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --distance-matrix --out test2', shell=True)
496        if not retval == 0:
497            print('Unexpected error in --distance-matrix test.')
498            sys.exit(1)
499        retval = subprocess.call('diff -q test1.mdist test2.mdist', shell=True)
500        if not retval == 0:
501            print('--distance-matrix test failed.')
502            sys.exit(1)
503    print('--distance-matrix test passed.')
504
505    for bfn in bfile_names:
506        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --genome --out test1', shell=True)
507        if not retval == 0:
508            print('Unexpected error in --genome test.')
509            sys.exit(1)
510        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --genome --out test2', shell=True)
511        if not retval == 0:
512            print('Unexpected error in --genome test.')
513            sys.exit(1)
514        retval = subprocess.call('diff -q test1.genome test2.genome', shell=True)
515        if not retval == 0:
516            print('--genome test failed.')
517            sys.exit(1)
518    print('--genome test passed.')
519
520    for bfn in bfile_names:
521        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --homozyg --out test1', shell=True)
522        if not retval == 0:
523            print('Unexpected error in --homozyg test.')
524            sys.exit(1)
525        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --homozyg subtract-1-from-lengths --out test2', shell=True)
526        if not retval == 0:
527            print('Unexpected error in --homozyg test.')
528            sys.exit(1)
529        retval = subprocess.call('diff -q test1.hom test2.hom', shell=True)
530        if not retval == 0:
531            print('--homozyg test failed.')
532            sys.exit(1)
533    print('--homozyg test passed.')
534
535    # skip --neighbour test for now due to likelihood of ties.  (Caught a
536    # command-line parsing bug when trying to write that test, though.)
537
538    for bfn in bfile_names_cc:
539        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --assoc --max-maf 0.4999 --out test1', shell=True)
540        if not retval == 0:
541            print('Unexpected error in case/control --assoc test.')
542            sys.exit(1)
543        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --assoc --max-maf 0.4999 --out test2', shell=True)
544        if not retval == 0:
545            print('Unexpected error in case/control --assoc test.')
546            sys.exit(1)
547        # remove columns 5/6/8 due to likely rounding differences (6/7/9 after
548        # leading space)
549        retval = subprocess.call("cat test1.assoc | tr -s ' ' '\t' | cut -f 1-5,8 > test1.assoc2", shell=True)
550        retval = subprocess.call("cat test2.assoc | tr -s ' ' '\t' | cut -f 1-5,8 > test2.assoc2", shell=True)
551        retval = subprocess.call('diff -q test1.assoc2 test2.assoc2', shell=True)
552        if not retval == 0:
553            print('Case/control --assoc test failed.')
554            sys.exit(1)
555    print('Case/control --assoc test passed.')
556
557    for bfn in bfile_names_qt:
558        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --assoc --max-maf 0.4999 --out test1', shell=True)
559        if not retval == 0:
560            print('Unexpected error in QT --assoc test.')
561            sys.exit(1)
562        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --assoc --max-maf 0.4999 --out test2', shell=True)
563        if not retval == 0:
564            print('Unexpected error in QT --assoc test.')
565            sys.exit(1)
566        retval = subprocess.call('diff -q test1.qassoc test2.qassoc', shell=True)
567        if not retval == 0:
568            print('QT --assoc test failed.')
569            sys.exit(1)
570    print('QT --assoc test passed.')
571
572    for bfn in bfile_names_cc:
573        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --max-maf 0.4999 --model --out test1', shell=True)
574        if not retval == 0:
575            print('Unexpected error in --model test.')
576            sys.exit(1)
577        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --max-maf 0.4999 --model --out test2', shell=True)
578        if not retval == 0:
579            print('Unexpected error in --model test.')
580            sys.exit(1)
581        retval = subprocess.call('diff -q test1.model test2.model', shell=True)
582        if not retval == 0:
583            print('--model test failed.')
584            sys.exit(1)
585    print('--model test passed.')
586
587    for bfn in bfile_names_cc:
588        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --within ' + bfn + '.cluster2 --max-maf 0.4999 --bd --out test1', shell=True)
589        if not retval == 0:
590            print('Unexpected error in --bd test.')
591            sys.exit(1)
592        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --within ' + bfn + '.cluster2 --max-maf 0.4999 --bd --out test2', shell=True)
593        if not retval == 0:
594            print('Unexpected error in --bd test.')
595            sys.exit(1)
596        retval = subprocess.call('diff -q test1.cmh test2.cmh', shell=True)
597        if not retval == 0:
598            print('--bd test failed.')
599            sys.exit(1)
600    print('--bd test passed.')
601
602    # --mh2 output format has been changed, so we skip that.
603
604    for bfn in bfile_names_cc:
605        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --within ' + bfn + '.cluster2 --max-maf 0.4999 --homog --out test1', shell=True)
606        if not retval == 0:
607            print('Unexpected error in --homog test.')
608            sys.exit(1)
609        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --within ' + bfn + '.cluster2 --max-maf 0.4999 --homog --out test2', shell=True)
610        if not retval == 0:
611            print('Unexpected error in --homog test.')
612            sys.exit(1)
613        retval = subprocess.call('diff -q test1.homog test2.homog', shell=True)
614        if not retval == 0:
615            print('--homog test failed.')
616            sys.exit(1)
617    print('--homog test passed.')
618
619    for bfn in bfile_names_qt:
620        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --cluster --K 3 --out test1', shell=True)
621        if not retval == 0:
622            print('Unexpected error in --gxe test.')
623            sys.exit(1)
624        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --gxe --covar test1.cluster2 --max-maf 0.4999 --out test1', shell=True)
625        if not retval == 0:
626            print('Unexpected error in --gxe test.')
627            sys.exit(1)
628        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --gxe --covar test1.cluster2 --max-maf 0.4999 --out test2', shell=True)
629        if not retval == 0:
630            print('Unexpected error in --gxe test.')
631            sys.exit(1)
632        retval = subprocess.call('diff -q test1.qassoc.gxe test2.qassoc.gxe', shell=True)
633        if not retval == 0:
634            print('--gxe test failed.')
635            sys.exit(1)
636    print('--gxe test passed.')
637
638    # can't use qt[1] as covar file since it probably used the same random seed
639    # and hence has the same phenotypes as qt[0]
640    retval = subprocess.call('plink107 --noweb --bfile ' + bfile_names_qt[0] + ' --silent --adjust --linear --covar ' + bfile_names_cc[0] + '.fam --covar-number 4 --out test1', shell=True)
641    if not retval == 0:
642        print('Unexpected error in --adjust/--linear test.')
643        sys.exit(1)
644    retval = subprocess.call('plink19 --bfile ' + bfile_names_qt[0] + ' --silent --adjust --linear --covar ' + bfile_names_cc[0] + '.fam --covar-number 4 --out test2', shell=True)
645    if not retval == 0:
646        print('Unexpected error in --adjust/--linear test.')
647        sys.exit(1)
648    retval = subprocess.call('diff -q test1.assoc.linear test2.assoc.linear', shell=True)
649    if not retval == 0:
650        print('--adjust/--linear test failed.')
651        sys.exit(1)
652    retval = subprocess.call('diff -q test1.assoc.linear.adjusted test2.assoc.linear.adjusted', shell=True)
653    if not retval == 0:
654        print('--adjust/--linear test failed.')
655        sys.exit(1)
656    print('--adjust/--linear test passed.')
657
658    # skip --logistic for now due to internal use of single precision floats
659
660    for bfn in bfile_names_qt:
661        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --recode oxford --out test1', shell=True)
662        if not retval == 0:
663            print('Unexpected error in --dosage test.')
664            sys.exit(1)
665        retval = subprocess.call('plink107 --noweb --silent --dosage test1.gen noheader skip0=1 skip1=1 format=3 --fam ' + bfn + '.fam --covar ' + bfile_names_cc[0] + '.fam --covar-number 4 --out test1', shell=True)
666        if not retval == 0:
667            print('Unexpected error in --dosage test.')
668            sys.exit(1)
669        retval = subprocess.call('plink19 --silent --dosage test1.gen noheader skip0=1 skip1=1 format=3 --fam ' + bfn + '.fam --covar ' + bfile_names_cc[0] + '.fam --covar-number 4 --out test2', shell=True)
670        if not retval == 0:
671            print('Unexpected error in --dosage test.')
672            sys.exit(1)
673        retval = subprocess.call('diff -q test1.assoc.dosage test2.assoc.dosage', shell=True)
674        if not retval == 0:
675            print('--dosage test failed.')
676            sys.exit(1)
677    print('--dosage test passed.')
678
679    # [0] may or may not have variants with zero missing calls, which
680    # complicates things
681    retval = subprocess.call('plink107 --noweb --bfile ' + bfile_names_cc[1] + ' --silent --test-missing --out test1', shell=True)
682    if not retval == 0:
683        print('Unexpected error in --test-missing test.')
684        sys.exit(1)
685    retval = subprocess.call('plink19 --bfile ' + bfile_names_cc[1] + ' --silent --test-missing --out test2', shell=True)
686    if not retval == 0:
687        print('Unexpected error in --test-missing test.')
688        sys.exit(1)
689    retval = subprocess.call('diff -q test1.missing test2.missing', shell=True)
690    if not retval == 0:
691        print('--test-missing test failed.')
692        sys.exit(1)
693    print('--test-missing test passed.')
694
695    for bfn in bfile_names_fam:
696        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --tdt --out test1', shell=True)
697        if not retval == 0:
698            print('Unexpected error in --tdt test.')
699            sys.exit(1)
700        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --tdt --out test2', shell=True)
701        if not retval == 0:
702            print('Unexpected error in --tdt test.')
703            sys.exit(1)
704        retval = subprocess.call('diff -q test1.tdt test2.tdt', shell=True)
705        if not retval == 0:
706            print('--tdt test failed.')
707            sys.exit(1)
708    print('--tdt test passed.')
709
710    # skip --qfam for now since there's no QT test file with family info
711
712    for bfn in bfile_names_qt:
713        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --linear --out test1', shell=True)
714        if not retval == 0:
715            print('Unexpected error in --annotate test.')
716            sys.exit(1)
717        retval = subprocess.call('plink107 --noweb --silent --annotate test1.assoc.linear ranges=set.txt --out test1', shell=True)
718        if not retval == 0:
719            print('Unexpected error in --annotate test.')
720            sys.exit(1)
721        retval = subprocess.call('plink19 --silent --annotate test1.assoc.linear ranges=set.txt --out test2', shell=True)
722        if not retval == 0:
723            print('Unexpected error in --annotate test.')
724            sys.exit(1)
725        retval = subprocess.call('diff -q test1.annot test2.annot', shell=True)
726        if not retval == 0:
727            print('--annotate test failed.')
728            sys.exit(1)
729    print('--annotate test passed.')
730
731    # skip --clump for now due to lack of LD
732
733    # skip --gene-report for now due to format changes
734
735    for bfn in bfile_names_cc:
736        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --fast-epistasis --out test1', shell=True)
737        if not retval == 0:
738            print('Unexpected error in --epistasis-summary-merge/--fast-epistasis/--parallel test.')
739            sys.exit(1)
740        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --fast-epistasis no-ueki --parallel 1 2 --out test2', shell=True)
741        if not retval == 0:
742            print('Unexpected error in --epistasis-summary-merge/--fast-epistasis/--parallel test.')
743            sys.exit(1)
744        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --fast-epistasis no-ueki --parallel 2 2 --out test2', shell=True)
745        if not retval == 0:
746            print('Unexpected error in --epistasis-summary-merge/--fast-epistasis/--parallel test.')
747            sys.exit(1)
748        retval = subprocess.call('rm -f test2.epi.cc', shell=True)
749        retval = subprocess.call('rm -f test2.epi.cc.summary', shell=True)
750        retval = subprocess.call('cat test2.epi.cc.1 test2.epi.cc.2 > test2.epi.cc', shell=True)
751        if not retval == 0:
752            print('Unexpected error in --epistasis-summary-merge/--fast-epistasis/--parallel test.')
753            sys.exit(1)
754        retval = subprocess.call('plink19 --epistasis-summary-merge test2.epi.cc 2 --silent --out test2', shell=True)
755        if not retval == 0:
756            print('Unexpected error in --epistasis-summary-merge/--fast-epistasis/--parallel test.')
757            sys.exit(1)
758        retval = subprocess.call('diff -q test1.epi.cc test2.epi.cc', shell=True)
759        if not retval == 0:
760            print('--epistasis-summary-merge/--fast-epistasis/--parallel test failed.')
761            sys.exit(1)
762        # remove column 6 (7 after leading spaces) due to floating point error
763        retval = subprocess.call("cat test1.epi.cc.summary | tr -s ' ' '\t' | cut -f 1-6,8- > test1.epi.cc.summary2", shell=True)
764        if not retval == 0:
765            print('--epistasis-summary-merge/--fast-epistasis/--parallel test failed.')
766            sys.exit(1)
767        retval = subprocess.call("cat test2.epi.cc.summary | tr -s ' ' '\t' | cut -f 1-6,8- > test2.epi.cc.summary2", shell=True)
768        if not retval == 0:
769            print('--epistasis-summary-merge/--fast-epistasis/--parallel test failed.')
770            sys.exit(1)
771        retval = subprocess.call('diff -q test1.epi.cc.summary2 test2.epi.cc.summary2', shell=True)
772        if not retval == 0:
773            print('--epistasis-summary-merge/--fast-epistasis/--parallel test failed.')
774            sys.exit(1)
775    print('--epistasis-summary-merge/--fast-epistasis/--parallel test passed.')
776
777    # skip --twolocus due to format change
778
779    for bfn in bfile_names_qt:
780        retval = subprocess.call('plink107 --noweb --bfile ' + bfn + ' --silent --score score.txt --out test1', shell=True)
781        if not retval == 0:
782            print('Unexpected error in --score test.')
783            sys.exit(1)
784        retval = subprocess.call('plink19 --bfile ' + bfn + ' --silent --score score.txt --out test2', shell=True)
785        if not retval == 0:
786            print('Unexpected error in --score test.')
787            sys.exit(1)
788        retval = subprocess.call('diff -q test1.profile test2.profile', shell=True)
789        if not retval == 0:
790            print('--score test failed.')
791            sys.exit(1)
792    print('--score test passed.')
793
794    print('All tests passed.')
795    subprocess.call('rm -f test1.*', shell=True)
796    subprocess.call('rm -f test2.*', shell=True)
797
798
799if __name__ == '__main__':
800    main()
801