forked from ANGSD/angsd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
abcGetFasta.cpp
209 lines (169 loc) · 5.61 KB
/
abcGetFasta.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*
thorfinn [email protected] 18dec 2012
assumes zero index positions
should remove mutexs, and make function thread safe. dragon daemon
part of angsd using faidx
Actually no need to mutex, except for the first chunk. Lets fix it at some point.
*/
#include <cassert>
#include "analysisFunction.h"
#include "shared.h"
#include "pthread.h"
#include "abc.h"
#include "abcGetFasta.h"
//this will initialize our data
perFasta *init(const char *fname){
fprintf(stderr,"\t-> Reading fasta: %s\n",fname);
if(aio::fexists(fname)==0){
fprintf(stderr,"\t-> fastafile: \'%s\' doesn't exists, will exit\n",fname);
exit(0);
}
//check that fa hasn't been updated
char *strtsk=NULL;
strtsk = (char*)calloc(strlen(fname) + 5, 1);
sprintf(strtsk, "%s.fai", fname);
if(aio::isNewer(fname,strtsk)){
fprintf(stderr,"\t-> fai index file: \'%s\' looks older than corresponding fastafile: \'%s\'.\n\t-> Please reindex fasta file\n",strtsk,fname);
exit(0);
}
free(strtsk);
perFasta *r= new perFasta;
r->fastaname=NULL;
r->fai = NULL;
r->seqs = NULL;
r->curChr = -1;
if(pthread_mutex_init(&r->aMut,NULL)){
fprintf(stderr,"[%s:%s] error initializing mutex \n",__FILE__,__FUNCTION__);
exit(0);
}
if(NULL==(r->fai = fai_load(fname))){
fprintf(stderr,"[%s:%s] error reading fai file:%s\n",__FILE__,__FUNCTION__,fname);
exit(0);
}
r->fastaname=strdup(fname);
return r;
}
void abcGetFasta::printArg(FILE *argFile){
fprintf(argFile,"---------------\n%s:\n\n",__FILE__);
fprintf(argFile,"\t-ref\t%s\t(afile.fasta)\n",refName);
fprintf(argFile,"\t-anc\t%s\t(afile.fasta)\n",ancName);
fprintf(argFile,"\tNB these fasta files should be indexed 'samtools faidx'\n");
fprintf(argFile,"\n");
}
//this will destroy a perfasta structure
void destroy(perFasta *f){
fai_destroy(f->fai);
free(f->seqs);
free(f->fastaname);
delete f;
f=NULL;
}
abcGetFasta::~abcGetFasta(){
if(ref)
destroy(ref);
if(anc)
destroy(anc);
free(refName);
free(ancName);
}
htsFormat *dingding2 =(htsFormat*) calloc(1,sizeof(htsFormat));//<-superstupid hack to be able to parse crams. This should be fixed
void abcGetFasta::getOptions(argStruct *arguments){
refName = NULL;
ancName = NULL;
//from command line
ancName = angsd::getArg("-anc",ancName,arguments);
refName = angsd::getArg("-ref",refName,arguments);
if(refName==NULL)
refName = angsd::getArg("-T",refName,arguments);
// fprintf(stderr,"refName=%s\tancName=%s\n",refName,ancName);
if(arguments->argc==2){
if(!strcasecmp(arguments->argv[1],"-ref")|| !strcasecmp(arguments->argv[1],"-anc") ){
printArg(stdout);
exit(0);
}else
return;
}
if(refName){
char *ref =(char*) malloc(10 + strlen(refName) + 1);
sprintf(ref, "reference=%s", refName);
hts_opt_add((hts_opt **)&dingding2->specific,ref);
free(ref);
}
}
char *abcGetFasta::loadChr(perFasta *f, char*chrName,int chrId){
// fprintf(stderr,"[%s] \t->loading chr:%s from faidx=%p curchr=%d\n",__FUNCTION__,chrName,f,f->curChr);
free(f->seqs);
f->seqs=NULL;
//fprintf(stderr,"f->curChr=%d chrId=%d\n",f->curChr,chrId);
f->curChr = chrId;
f->seqs = faidx_fetch_seq(f->fai, chrName, 0, 0x7fffffff, &f->chrLen);
if(f->seqs==NULL){
fprintf(stderr,"\n[%s] Error loading fasta info from chr:\'%s\' \n",__FUNCTION__,chrName);
f->chrLen=0;
}
// fprintf(stderr,"[%s] done\n",__FUNCTION__);
if(f->chrLen!=header->target_len[chrId]){
fprintf(stderr,"\t-> Problem with length of fastafile vs length of chr in BAM header\n");
fprintf(stderr,"\t-> Chromosome name: \'%s\' length from BAM header:%d length from fai file:%d\n",chrName,header->target_len[chrId],f->chrLen);
extern int SIG_COND;
SIG_COND = 0;
}
return f->seqs;
}
char *abcGetFasta::magic(int refId,int *posi,int numSites,perFasta *f){
pthread_mutex_lock(&f->aMut);
assert(refId!=-1);
//load new chr if different from last or if nothing has been loaded before
if(f->curChr==-1||refId!=f->curChr){
// fprintf(stderr,"[%s] chaning to chr: %d\n",__FUNCTION__,refId);
//fflush(stderr);
loadChr(f,header->target_name[refId],refId);
}
//first check that last position is not to long after.
if(posi[numSites-1] > f->chrLen+200){
fprintf(stderr,"Trying to access fasta efter end of chromsome+200:%s/%s pos=%d ref_len=%d\n",header->target_name[f->curChr],header->target_name[refId],posi[numSites-1],f->chrLen);
}
//now loop over all positions. We allow +200 since a read might match to the end of a chr
char *ret=new char[numSites];
for(int i=0;i<numSites;i++){
if(f->seqs&&posi[i]<f->chrLen)
ret[i] = refToInt[f->seqs[posi[i]]];//offseting by one, to make in work like samtools
else{
ret[i] = 4;
}
}
pthread_mutex_unlock(&f->aMut);
return ret;
}
abcGetFasta::abcGetFasta(argStruct *arguments){
refName = NULL;
ancName = NULL;
ref=NULL;
anc=NULL;
if(arguments->argc==2){
if(!strcasecmp(arguments->argv[1],"-ref")||!strcasecmp(arguments->argv[1],"-anc")){
printArg(stdout);
exit(0);
}else
return;
}
getOptions(arguments);
if(ref!=NULL || anc!=NULL)
printArg(arguments->argumentFile);
if(ancName!=NULL)
anc = init(ancName);
if(refName!=NULL)
ref = init(refName);
if(ref==NULL&&anc==NULL)
shouldRun[index]=0;
}
void abcGetFasta::run(funkyPars *pars){
if(pars->numSites==0)
return;
if(ref)
pars->ref = magic(pars->refId,pars->posi,pars->numSites,ref);
if(anc)
pars->anc = magic(pars->refId,pars->posi,pars->numSites,anc);
}
void abcGetFasta::print(funkyPars *f){}
void abcGetFasta::clean(funkyPars *f){}