/****************************************************************************
 *                                                                          *
 *     Loki - Programs for genetic analysis of complex traits using MCMC    *
 *                                                                          *
 *                      Simon Heath - MSKCC                                 *
 *                                                                          *
 *                          August 2000                                     *
 *                                                                          *
 * loki_dump.c:                                                             *
 *                                                                          *
 * Routines for reading and writing dump files                              *
 *                                                                          *
 * Copyright (C) Simon C. Heath 1997, 2000, 2002                            *
 * This is free software.  You can distribute it and/or modify it           *
 * under the terms of the Modified BSD license, see the file COPYING        *
 *                                                                          *
 ****************************************************************************/

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/times.h>
#include <errno.h>
#include <sys/wait.h>
#include <signal.h>

#include "utils.h"
#include "loki.h"
#include "libhdr.h"
#include "loki_peel.h"
#include "loki_output.h"
#include "sample_rand.h"
#include "loki_ibd.h"
#include "loki_dump.h"

#ifdef FUNC_NAME
#undef FUNC_NAME
#endif
#define FUNC_NAME "read_dump"
int read_dump(int *lp,int *lp1,int *n_ibd,long *old_pos,int *flag,int analysis,loki_time *lt)
{
	int i=0,j,k,k1,k2,nl=0,type,nrec,v2[4],pflag=0;
	char *tmp,*tmp1;
	double v1[4],z;
	FILE *fdump;

	signal(SIGCHLD,SIG_IGN);
	k=k1=k2=0;
	if(Filter) {
		errno=0;
		i=child_open(READ,Dumpfile,Filter);
		fdump=fdopen(i,"r");
		if(errno && errno!=ESPIPE) i=__LINE__;
		else i=0;
		errno=0;
	} else fdump=fopen(Dumpfile,"r");
	if(!fdump || i) (void)fprintf(stderr,"[%s:%d] %s(): File Error.  Couldn't open '%s' for input\n",__FILE__,__LINE__,FUNC_NAME,Dumpfile);
	else {
		if(!(tmp=fget_line(fdump))) i=__LINE__;
		if(!i && strncmp(tmp,"Loki.dump:",10)) i=__LINE__;
		if(!i) {
			tmp1=tmp+10;
			for(j=0;!i && j<2;j++) {
				if(j && (*tmp1++!=',')) i=__LINE__;
				else v2[j]=strtol(tmp1,&tmp,16);
				tmp1=tmp;
			}
		}
		if(!i) {
			*lp=(int)v2[0];
			*lp1=(int)v2[1];
		}
		if(!i && (analysis&IBD_ANALYSIS)) {
			if(analysis&ESTIMATE_IBD) i=read_ibd_dump(fdump,n_ibd,tmp);
			else if(*tmp!='\n') i=__LINE__;
		}
		(void)fputs("[Parameters] ",stdout);
		(void)fflush(stdout);
		if(!(analysis&IBD_ANALYSIS)) {
			for(j=0;!i && j<3;j++) {
				if(*tmp1++!=',') i=__LINE__;
				else v2[j]=strtol(tmp1,&tmp,16);
				tmp1=tmp;
			}
			if(!i) {
				nl=(int)v2[0];
				n_cov_columns=(int)v2[2];
				k=3;
				if(polygenic_flag) k++;
				for(j=0;!i && j<k;j++) {
					if(*tmp1++!=',') i=__LINE__;
					if(txt_get_double(tmp1,&tmp,v1+j)) i=__LINE__;
					tmp1=tmp;
				}
				for(j=0;!i && j<n_random;j++) {
					if(*tmp1++!=',') i=__LINE__;
					if(txt_get_double(tmp1,&tmp,c_var[j])) i=__LINE__;
					tmp1=tmp;
				}
			}
			if(!i) {
				residual_var[0]=v1[0];
				tau[0]=v1[1];
				grand_mean[0]=v1[2];
				if(polygenic_flag) additive_var[0]=v1[3];
				if(*tmp!='\n') i=__LINE__;
				else if(!(tmp=fget_line(fdump))) i=__LINE__;
			}
			for(j=0;!i && j<models[0].n_terms;j++) {
				type=models[0].term[j].vars[0].type;
				if(type&(ST_TRAITLOCUS|ST_ID)) continue;
				for(k=0;!i && k<models[0].term[j].df;k++) {
					if(txt_get_double(tmp,&tmp1,models[0].term[j].eff+k)) i=__LINE__;
					if(*tmp1=='\n') {
						if(!(tmp=fget_line(fdump))) i=__LINE__;
					} else {
						if(*tmp1++!=',') i=__LINE__;
						tmp=tmp1;
					}
				}
			}
			*old_pos=-1;
			*flag=0;
			if(!i) {
				if(strncmp(tmp,"LKST:",5)) {
					*old_pos=strtol(tmp,&tmp1,10);
					if(*tmp1==',') {
						*flag=(int)strtol(++tmp1,&tmp,16);
						tmp1=tmp;
					}
					if(*tmp1!='\n') i=__LINE__;
					if(!i && !(tmp=fget_line(fdump))) i=__LINE__;
				}
			}
			if(!i && strncmp(tmp,"LKST:",5)) i=__LINE__;
			else if(!i) {
				j=(int)strtol(tmp+5,&tmp1,16);
				if(j!=N_MOVE_STATS) i=__LINE__;
			}
			for(j=0;!i && j<N_MOVE_STATS;j++) {
				if(*tmp1++!=',') i=__LINE__;
				else move_stats[j].success=(int)strtol(tmp1,&tmp,16);
				if(!i && *tmp++!=',') i=__LINE__;
				else move_stats[j].n=(int)strtol(tmp,&tmp1,16);
			}
			if(!i) {
				if(*tmp1!='\n') i=__LINE__;
				else if(!(tmp=fget_line(fdump))) i=__LINE__;
			}
			if(!i) {
				if(strncmp(tmp,"LKQT:",5)) i=__LINE__;
				else {
					j=(int)strtol(tmp+5,&tmp1,16);
					if(*tmp1!='\n' || j!=nl) i=__LINE__;
				}
			}
			for(j=0;!i && j<nl;j++) {
				if(!(tmp=fget_line(fdump))) i=__LINE__;
				else {
					k1=(int)strtol(tmp,&tmp1,16);
					if(k1!=2) ABT_FUNC("Illegal no. alleles for QTL\n");
					k=get_new_traitlocus(k1);
					tlocus[k].model_flag=1;
					if(*tmp1++!=',') i=__LINE__;
					else {
						tlocus[k].locus.link_group=(int)strtol(tmp1,&tmp,10);
						if(*tmp++!=',') i=__LINE__;
						else tlocus[k].locus.flag=(int)strtol(tmp,&tmp1,16);
					}
					if(k<0) ABT_FUNC("Internal error - Couldn't get trait locus\n");
				}
				for(k2=0;!i && k2<2;k2++) {
					if(*tmp1++!=',') i=__LINE__;
					else {
						if(txt_get_double(tmp1,&tmp,tlocus[k].locus.pos+k2)) i=__LINE__;
						else tmp1=tmp;
					}
				}
				if(!i) {
					k1=k1*(k1+1)/2-1;
					for(k2=0;!i && k2<k1;k2++) {
						if(*tmp1++!=',') i=__LINE__;
						else {
							if(txt_get_double(tmp1,&tmp,tlocus[k].eff[0]+k2)) i=__LINE__;
							else tmp1=tmp;
						}
					}
				}
				for(k1=0;!i && k1<n_genetic_groups;k1++) {
					z=1.0;
					for(k2=0;!i && k2<tlocus[j].locus.n_alleles-1;k2++) {
						if(*tmp1++!=',') i=__LINE__;
						else {
							if(txt_get_double(tmp1,&tmp,tlocus[k].locus.freq[k1]+k2)) i=__LINE__;
							else {
								z-=tlocus[k].locus.freq[k1][k2];
								tmp1=tmp;
							}
						}
					}
					if(!i) tlocus[k].locus.freq[k1][k2]=z;
				}
				if(!i && *tmp1!='\n') i=__LINE__;
			}
		}
		if(!i) {
			if(!(tmp=fget_line(fdump))) i=__LINE__;
			else {
				if(strncmp(tmp,"LKMK:",5)) i=__LINE__;
				else {
					j=(int)strtol(tmp+5,&tmp1,16);
					if(*tmp1!='\n' || j!=n_markers) i=__LINE__;
				}
			}
		}
		for(j=0;!i && j<n_markers;j++) {
			if(!(tmp=fget_line(fdump))) i=__LINE__;
			k1=(int)strtol(tmp,&tmp1,16);
			if(*tmp1++!=',' || k1!=marker[j].locus.n_alleles) i=__LINE__;
			else {
				marker[j].locus.link_group=(int)strtol(tmp1,&tmp,10);
				if(*tmp++!=',') i=__LINE__;
				else marker[j].locus.flag=((int)strtol(tmp,&tmp1,16))&~RFMASK_OK;
			}
			for(k=0;!i && k<2;k++) {
				if(*tmp1++!=',') i=__LINE__;
				else {
					if(txt_get_double(tmp1,&tmp,marker[j].locus.pos+k)) i=__LINE__;
					else tmp1=tmp;
				}
			}
			for(k=0;!i && k<n_genetic_groups;k++) {
				z=1.0;
				for(k2=0;!i && k2<k1-1;k2++) {
					if(*tmp1++!=',') i=__LINE__;
					else {
						if(txt_get_double(tmp1,&tmp,marker[j].locus.freq[k]+k2)) i=__LINE__;
						else {
							z-=marker[j].locus.freq[k][k2];
							tmp1=tmp;
						}
					}
				}
				if(!i) marker[j].locus.freq[k][k2]=z;
			}
			if(!i && *tmp1!='\n') i=__LINE__;
		}
		if(!i && n_markers+nl) {
			(void)fputs("[Genotypes] ",stdout);
			(void)fflush(stdout);
			if(nl) {
				if(!(tmp=fget_line(fdump))) i=__LINE__;
				else if(strncmp(tmp,"LKQS:",5)) i=__LINE__;
				else k2=(int)strtol(tmp+5,&tmp1,16);
				if(!i && *tmp1++!=',') i=__LINE__;
				else {
					k=(int)strtol(tmp1,&tmp,16);
					if(*tmp!='\n' || k!=ped_size || k2>=k) i=__LINE__;
				}
				if(k2) for(j=0;!i && j<n_tloci;j++) if(tlocus[j].locus.flag) {
					if(!(tmp=fget_line(fdump))) i=__LINE__;
					for(k=0;!i && k<ped_size;k++) if(id_array[k].sire || id_array[k].dam) {
						k1=(int)*tmp++;
						if(k1>='0'&&k1<='9') k1-='0';
						else if(k1>='a'&&k1<='f') k1-='a'-10;
						else i=__LINE__;
						if(!i) {
							tlocus[j].locus.seg[1][k]=(k1&3)-2;
							tlocus[j].locus.seg[0][k]=(k1>>2)-2;
						}
					}
					if(!i && *tmp!='\n') i=__LINE__;
				}
				if(!(tmp=fget_line(fdump))) i=__LINE__;
				else if(strncmp(tmp,"LKQG\n",5)) i=__LINE__;
				for(k=0;!i && k<ped_size;k++) {
					if(!(tmp=fget_line(fdump))) i=__LINE__;
					for(k1=j=0;!i && j<n_tloci;j++) if(tlocus[j].locus.flag) {
						if(k1++ && *tmp++!=',') i=__LINE__;
						else {
							tlocus[j].locus.gt[k]=(int)strtol(tmp,&tmp1,16);
							tmp=tmp1;
						}
					}
					if(!i && *tmp1!='\n') i=__LINE__;
				}
			}
			if(!i && n_markers) {
				if(!(tmp=fget_line(fdump))) i=__LINE__;
				else if(strncmp(tmp,"LKMS:",5)) i=__LINE__;
				else k2=(int)strtol(tmp+5,&tmp1,16);
				if(!i && *tmp1++!=',') i=__LINE__;
				else {
					k=(int)strtol(tmp1,&tmp,16);
					if(*tmp!='\n' || k!=n_markers) i=__LINE__;
				}
				if(k2) for(j=0;!i && j<n_markers;j++) {
					if(!(tmp=fget_line(fdump))) i=__LINE__;
					for(k=0;!i && k<ped_size;k++) if(id_array[k].sire || id_array[k].dam) {
						k1=(int)*tmp++;
						if(k1>='0'&&k1<='9') k1-='0';
						else if(k1>='a'&&k1<='f') k1-='a'-10;
						else i=__LINE__;
						if(!i) {
							marker[j].locus.seg[1][k]=(k1&3)-2;
							marker[j].locus.seg[0][k]=(k1>>2)-2;
						}
					}
					if(!i && *tmp!='\n') i=__LINE__;
				}
				for(k=j=0;!i && j<n_markers;j++) if(marker[j].mterm && marker[j].mterm[0]) k++;
				if(k) {
					if(!(tmp=fget_line(fdump))) i=__LINE__;
					else if(strncmp(tmp,"LKMG:",5)) i=__LINE__;
					else k2=(int)strtol(tmp+5,&tmp1,16);
					if(*tmp1++!=',' || k2!=k) i=__LINE__;
					else {
						k2=(int)strtol(tmp1,&tmp,16);	
						if(k2!=ped_size) i=__LINE__;
					}
					for(k1=0;!i && k1<k;k1++) {
						if(*tmp++!=',') i=__LINE__;
						else k2=(int)strtol(tmp,&tmp1,16);
						if(k2<0 || k2>=n_markers || !marker[k2].mterm[0]) i=__LINE__;
						else tmp=tmp1;
					}
					if(!i && *tmp++!='\n') i=__LINE__;
					for(k=0;!i && k<ped_size;k++) {
						if(!(tmp=fget_line(fdump))) i=__LINE__;
						for(k1=j=0;!i && j<n_markers;j++) if(marker[j].mterm[0]) {
							if(k1++ && *tmp++!=',') i=__LINE__;
							else {
								marker[j].locus.gt[k]=(int)strtol(tmp,&tmp1,16);
								tmp=tmp1;
							}
						}
						if(!i && *tmp!='\n') i=__LINE__;
					}
				}
			}
		}
		if(!i && !(analysis&IBD_ANALYSIS)) {
			(void)fputs("[Residuals] ",stdout);
			(void)fflush(stdout);
			if(!(tmp=fget_line(fdump))) i=__LINE__;
			else if(strncmp(tmp,"LKRS:",5)) i=__LINE__;
			else k2=(int)strtol(tmp+5,&tmp1,16);
			if(*tmp1++!='\n' || k2!=censored_flag) i=__LINE__;
			for(j=0;!i && j<ped_size;j++) {
				if(!i && polygenic_flag) {
					if(!(tmp=fget_line(fdump))) i=__LINE__;
					if(txt_get_double(tmp,&tmp1,&id_array[j].bv[0])) i=__LINE__;
					if(!i) {
						if(*tmp1=='\n') {
							if(pflag==1) i=__LINE__;
							else pflag=2;
						} else {
							if(!i && *tmp1++!=',') i=__LINE__;
							if(pflag==2) i=__LINE__;
							pflag=1;
							if(txt_get_double(tmp1,&tmp,&id_array[j].bvsum[0])) i=__LINE__;
							if(!i && *tmp++!=',') i=__LINE__;
							if(txt_get_double(tmp,&tmp1,&id_array[j].bvsum2[0])) i=__LINE__;
							if(!i && *tmp1!='\n') i=__LINE__;
						}
					}
				}
				if(!id_array[j].res[0]) continue;
				if(!(tmp=fget_line(fdump))) i=__LINE__;
				nrec=id_array[j].n_rec;
				if(!nrec) nrec=1;
				for(k=0;!i && k<nrec;k++) {
					if(k && *tmp++!=',') i=__LINE__;
					else if(txt_get_double(tmp,&tmp1,id_array[j].res[0]+k)) i=__LINE__;
					if(!i && use_student_t) {
						if(*tmp1++!=',') i=__LINE__;
						else if(txt_get_double(tmp1,&tmp,id_array[j].vv[0]+k)) i=__LINE__;
						tmp1=tmp;
					}
					if(!i && censored_flag && id_array[j].cens[0]) {
						if(*tmp1++!=',') i=__LINE__;
						else if(txt_get_double(tmp1,&tmp,id_array[j].cens[0]+k)) i=__LINE__;
					} else tmp=tmp1;
				}
				if(!i && *tmp!='\n') i=__LINE__;
			}
			if(!i && pflag==1) {
				if(!(tmp=fget_line(fdump))) i=__LINE__;
				else bv_iter=(int)strtol(tmp,&tmp1,16);
				if(!i && *tmp1!='\n') i=__LINE__;
			}
		}
		if(!i) {
			(void)fputs("[Seed] ",stdout);
			(void)fflush(stdout);
			if(!(tmp=fget_line(fdump))) i=__LINE__;
			else if(strncmp(tmp,"LKSD:",5)) i=__LINE__;
			if(!i && binreadseed(fdump,tmp+5)) i=__LINE__;
		}
		if(!i) {
			(void)fputs("[Time",stdout);
			(void)fflush(stdout);
			if(!(tmp=fget_line(fdump))) i=__LINE__;
			else {
				if(strncmp(tmp,"LKTM:",5)) {
					(void)fputs(" !Not found!] ",stdout);
					(void)fflush(stdout);
				} else {
					(void)fputs("] ",stdout);
					(void)fflush(stdout);
					if(txt_get_double(tmp+5,&tmp1,&lt->extra_time)) i=__LINE__;
					if(!i && *tmp1++!=',') i=__LINE__;
					if(!i && txt_get_double(tmp1,&tmp,&lt->extra_stime)) i=__LINE__;
					if(!i && *tmp++!=',') i=__LINE__;
					if(!i && txt_get_double(tmp,&tmp1,&lt->extra_utime)) i=__LINE__;
					if(!i && *tmp1!='\n') i=__LINE__;
					if(!i && !(tmp=fget_line(fdump))) i=__LINE__;
				}
				if(!i && strncmp(tmp,"Ldmp.end\n",9)) i=__LINE__;
			}
		}
	}
	(void)fget_line(0);
	if(fdump) (void)fclose(fdump);
	if(i) (void)fprintf(stderr,"[%s:%d] Error in %s() ",__FILE__,i,FUNC_NAME);
	(void)fget_line(0);
	if(!i && pflag==2) (void)fputs("Polygenic summary information not in file\n",stdout);
	signal(SIGCHLD,SIG_DFL);
	while(waitpid(-1,&i,WNOHANG)>0);
	return -i;
}

#ifdef FUNC_NAME
#undef FUNC_NAME
#endif
#define FUNC_NAME "write_dump"
void write_dump(int lp,int lp1,int n_ibd,long old_pos,int flag,int analysis,loki_time *lt)
{
	int i=0,j,k,k1,k2,nx,nl=0,type,nrec;
	double ex1,ex2;
	struct tms tbuf;
	long tps;
	FILE *fdump;
	
	signal(SIGCHLD,SIG_IGN);
	(void)fputs("Dumping program state: ",stdout);
	(void)fflush(stdout);
	if(!Dumpfile) Dumpfile=make_file_name(".dump");
	if(Dumpfile) {
		j=syst_var[SYST_BACKUPS].flag?syst_var[SYST_BACKUPS].data.value:1;
		if(j) i=mkbackup(Dumpfile,j);
		if(!i) {
			if(Filter) {
				errno=0;
				i=child_open(WRITE,Dumpfile,Filter);
				fdump=fdopen(i,"w");
				if(errno && errno!=ESPIPE) i=1;
				else i=0;
				errno=0;
			} else fdump=fopen(Dumpfile,"w");
			if(!fdump || i) (void)fprintf(stderr,"[%s:%d] %s(): File Error.  Couldn't open '%s' for output\n",__FILE__,__LINE__,FUNC_NAME,Dumpfile);
			else {
				if(!i && fprintf(fdump,"Loki.dump:%x,%x",lp,lp1)<0) i=1;
				if(!i && (analysis&IBD_ANALYSIS)) {
					if(analysis&ESTIMATE_IBD) i=write_ibd_dump(fdump,n_ibd);
					else if(fputc('\n',fdump)<0) i=1;
				}
				(void)fputs("[Parameters] ",stdout);
				(void)fflush(stdout);
				if(!(analysis&IBD_ANALYSIS)) {
					nx=0;
					if(models) {
						for(j=0;j<models[0].n_terms;j++) {
							type=models[0].term[j].vars[0].type;
							if(type&(ST_TRAITLOCUS|ST_ID)) continue;
							nx+=models[0].term[j].df;
						}
					}
					for(nl=j=0;j<n_tloci;j++) if(tlocus[j].locus.flag) nl++;
					if(!i && fprintf(fdump,",%x,%x,%x,",nl,nx,n_cov_columns)<0) i=1;
					if(models) {
						if(!i) i=txt_print_double(residual_var[0],fdump);
						if(!i && fputc(',',fdump)<0) i=1;
						if(!i) i=txt_print_double(tau[0],fdump);
						if(!i && fputc(',',fdump)<0) i=1;
						if(!i) i=txt_print_double(grand_mean[0],fdump);
						if(!i && polygenic_flag) {
							if(!i && fputc(',',fdump)<0) i=1;
							i=txt_print_double(additive_var[0],fdump);
						}
						for(j=0;!i && j<n_random;j++) {
							if(!i && fputc(',',fdump)<0) i=1;
							i=txt_print_double(c_var[j][0],fdump);
						}
						if(!i && fputc('\n',fdump)<0) i=1;
						for(j=0;!i && j<models[0].n_terms;j++) {
							type=models[0].term[j].vars[0].type;
							if(type&(ST_TRAITLOCUS|ST_ID)) continue;
							for(k=0;!i && k<models[0].term[j].df;k++) {
								i=txt_print_double(models[0].term[j].eff[k],fdump);	
								if(!i && fputc('\n',fdump)<0) i=1;
							}
						}
					}
					if(!i && fprintf(fdump,"%ld,%x",old_pos,flag)<0) i=1;
					if(!i && fprintf(fdump,"\nLKST:%x",N_MOVE_STATS)<0) i=1;
					for(j=0;!i && j<N_MOVE_STATS;j++) if(fprintf(fdump,",%x,%x",move_stats[j].success,move_stats[j].n)<0) i=1;
					if(!i && fprintf(fdump,"\nLKQT:%x\n",nl)<0) i=1;
					for(j=0;!i && j<n_tloci;j++) if(tlocus[j].locus.flag) {
						if(fprintf(fdump,"%x,%d,%x",tlocus[j].locus.n_alleles,tlocus[j].locus.link_group,tlocus[j].locus.flag)<0) i=1;
						for(k=0;!i && k<2;k++) {
							if(fputc(',',fdump)<0) i=1;
							else i=txt_print_double(tlocus[j].locus.pos[k],fdump);	
						}
						k=tlocus[j].locus.n_alleles;
						k1=k*(k+1)/2-1;
						for(k=0;!i && k<k1;k++) {
							if(fputc(',',fdump)<0) i=1;
							else i=txt_print_double(tlocus[j].eff[0][k],fdump);
						}
						for(k=0;!i && k<n_genetic_groups;k++) {
							for(k1=0;!i && k1<tlocus[j].locus.n_alleles-1;k1++) {
								if(fputc(',',fdump)<0) i=1;
								else i=txt_print_double(tlocus[j].locus.freq[k][k1],fdump);
							}
						}
						if(!i && fputc('\n',fdump)<0) i=1;
					}
				}
				if(!i && fprintf(fdump,"LKMK:%x\n",n_markers)<0) i=1;
				for(j=0;!i && j<n_markers;j++) {
					if(fprintf(fdump,"%x,%d,%x",marker[j].locus.n_alleles,marker[j].locus.link_group,marker[j].locus.flag)<0) i=1;
					for(k=0;!i && k<2;k++) {
						if(fputc(',',fdump)<0) i=1;
						else i=txt_print_double(marker[j].locus.pos[k],fdump);	
					}
					for(k=0;!i && k<n_genetic_groups;k++) {
						for(k1=0;!i && k1<marker[j].locus.n_alleles-1;k1++) {
							if(fputc(',',fdump)<0) i=1;
							else i=txt_print_double(marker[j].locus.freq[k][k1],fdump);
						}
					}
					if(!i && fputc('\n',fdump)<0) i=1;
				}
				if(!i && n_markers+nl) {
					(void)fputs("[Genotypes] ",stdout);
					(void)fflush(stdout);
					for(k2=k=0;k<ped_size;k++) if(id_array[k].sire || id_array[k].dam) k2++;
					if(nl) {
						if(k2) {
							if(fprintf(fdump,"LKQS:%x,%x\n",k2,ped_size)<0) i=1;
							for(j=0;!i && j<n_tloci;j++) if(tlocus[j].locus.flag) {
								for(k=0;!i && k<ped_size;k++) if(id_array[k].sire || id_array[k].dam) {
									if(fprintf(fdump,"%x",((tlocus[j].locus.seg[0][k]+2)<<2)|(tlocus[j].locus.seg[1][k]+2))<0) i=1;
								}
								if(!i && fputc('\n',fdump)<0) i=1;
							}
						}
						if(!i && fputs("LKQG\n",fdump)<0) i=1;
						for(k=0;!i && k<ped_size;k++) {
							for(k1=j=0;!i && j<n_tloci;j++) if(tlocus[j].locus.flag) {
								if(k1++ && fputc(',',fdump)<0) i=1;
								if(!i && fprintf(fdump,"%x",tlocus[j].locus.gt[k])<0) i=1;
							}
							if(!i && fputc('\n',fdump)<0) i=1;
						}
					}
					if(n_markers) {
						if(k2) {
							if(fprintf(fdump,"LKMS:%x,%x\n",k2,n_markers)<0) i=1;
							for(j=0;!i && j<n_markers;j++) {
								for(k=0;!i && k<ped_size;k++) if(id_array[k].sire || id_array[k].dam) {
									if(fprintf(fdump,"%x",((marker[j].locus.seg[0][k]+2)<<2)|(marker[j].locus.seg[1][k]+2))<0) i=1;
								}
								if(!i && fputc('\n',fdump)<0) i=1;
							}
						}
						if(models) {
							for(k=j=0;!i && j<n_markers;j++) if(marker[j].mterm[0]) k++;
							if(!i && k) {
								if(fprintf(fdump,"LKMG:%x,%x",k,ped_size)<0) i=1;
								for(j=0;!i && j<n_markers;j++) if(marker[j].mterm[0] && fprintf(fdump,",%x",j)<0) i=1;
								if(!i && fputc('\n',fdump)<0) i=1;
								for(k=0;!i && k<ped_size;k++) {
									for(k1=j=0;!i && j<n_markers;j++) if(marker[j].mterm[0]) {
										if(k1++ && fputc(',',fdump)<0) i=1;
										if(!i && fprintf(fdump,"%x",marker[j].locus.gt[k])<0) i=1;
									}
									if(!i && fputc('\n',fdump)<0) i=1;
								}
							}
						}
					}
				}
				if(!i && !(analysis&IBD_ANALYSIS)) {
					(void)fputs("[Residuals] ",stdout);
					(void)fflush(stdout);
					if(fprintf(fdump,"LKRS:%x\n",censored_flag)<0) i=1;
					if(models) for(j=0;!i && j<ped_size;j++) {
						if(polygenic_flag) {
							i=txt_print_double(id_array[j].bv[0],fdump);
							if(!i && fputc(',',fdump)<0) i=1;
							if(!i) i=txt_print_double(id_array[j].bvsum[0],fdump);
							if(!i && fputc(',',fdump)<0) i=1;
							if(!i) i=txt_print_double(id_array[j].bvsum2[0],fdump);
							if(!i && fputc('\n',fdump)<0) i=1;
						}
						if(!id_array[j].res[0]) continue;
						nrec=id_array[j].n_rec;
						if(!nrec) nrec=1;
						for(k=0;!i && k<nrec;k++) {
							if(k && fputc(',',fdump)<0) i=1;
							else i=txt_print_double(id_array[j].res[0][k],fdump);
							if(!i && use_student_t) {
								if(fputc(',',fdump)<0) i=1;
								else i=txt_print_double(id_array[j].vv[0][k],fdump);
							}
							if(!i && censored_flag && id_array[j].cens[0]) {
								if(fputc(',',fdump)<0) i=1;
								else i=txt_print_double(id_array[j].cens[0][k],fdump);
							}
						}
						if(!i && fputc('\n',fdump)<0) i=1;
					}
					if(!i && polygenic_flag) if(fprintf(fdump,"%x\n",bv_iter)<0) i=1;
				}
				if(!i) {
					(void)fputs("[Seed] ",stdout);
					(void)fflush(stdout);
					if(fputs("LKSD:",fdump)<0) i=1;
					if(!i) i=bindumpseed(fdump);
				}
				if(!i) {
					(void)fputs("[Time] ",stdout);
					(void)fflush(stdout);
					if(fputs("LKTM:",fdump)<0) i=1;
					if(!i) i=txt_print_double(lt->extra_time+difftime(time(0),lt->start_time),fdump);
					if(!i) {
						ex1=lt->extra_stime;
						ex2=lt->extra_utime;
						tps=sysconf (_SC_CLK_TCK);
						errno=0;
						(void)times(&tbuf);
						if(errno) perror("print_end_time():");
						else {
							ex1+=(double)tbuf.tms_stime/(double)tps;
							ex2+=(double)tbuf.tms_utime/(double)tps;
						}
					}
					if(!i && fputc(',',fdump)<0) i=1;
					if(!i) i=txt_print_double(ex1,fdump);
					if(!i && fputc(',',fdump)<0) i=1;
					if(!i) i=txt_print_double(ex2,fdump);
					if(!i && fputc('\n',fdump)<0) i=1;
				}
				if(!i && fputs("Ldmp.end\n",fdump)<0) i=1;
			}
			if(fdump) {
				(void)fclose(fdump);
				if(i) (void)unlink(Dumpfile);
			}
		}
	} else i=1;
	if(i) (void)fputs("FAILED\n",stdout);
	else (void)fputs("OK\n",stdout);
	signal(SIGCHLD,SIG_DFL);
	while(waitpid(-1,&i,WNOHANG)>0);
}

