From b8af5dd65f305ff0230c43bd4648d386f72a0f12 Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Mon, 20 Apr 2009 08:31:30 +0000 Subject: [PATCH] Merge of eric-test branche to the trunk git-svn-id: https://www.grenoble.prabi.fr/svn/LECASofts/ecoPrimers/trunk@199 60f365c0-8329-0410-b2a4-ec073aeeaa1d --- src/ecoPrimer | Bin 62448 -> 0 bytes src/libecoprimer/amplifiatree.c | 131 +++++++++++++++++++ src/libecoprimer/pairtree.c | 136 +++++++++++++++++++ src/libecoprimer/taxstats.c | 224 ++++++++++++++++++++++++++++++++ 4 files changed, 491 insertions(+) delete mode 100755 src/ecoPrimer create mode 100644 src/libecoprimer/amplifiatree.c create mode 100644 src/libecoprimer/pairtree.c create mode 100644 src/libecoprimer/taxstats.c diff --git a/src/ecoPrimer b/src/ecoPrimer deleted file mode 100755 index 13716c122e12ae6e4bfea9dcfa533af903040fa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62448 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 LS + +static void cleanamplifia(pamplifia_t amplifia); +static void deleteamplifialist(pamplifialist_t list); +static int cmpamplifia(const void* p1,const void*p2); + + +static void cleanamplifiatlist(pamplifiacount_t list) +{ + if (list->amplifias) + ECOFREE(list->amplifias, + "Free amplifia list"); +} + +static void cleanamplifia(pamplifia_t amplifia) +{ + cleanamplifiatlist(&(amplifia->pcr)); +} + +static pamplifialist_t newamplifialist(pamplifialist_t parent, size_t size) +{ + pamplifialist_t tmp; + + tmp=ECOMALLOC(sizeof(amplifialist_t)+sizeof(amplifia_t)*(size-1), + "Cannot allocate new amplifia list"); + + tmp->amplifiaslots=size; + tmp->amplifiacount=0; + tmp->next=NULL; + + if (parent) + parent->next=(void*)tmp; + + return tmp; +} + +static void deleteamplifialist(pamplifialist_t list) +{ + size_t i; + + if (list) + { + if (list->next) + { + deleteamplifialist(list->next); + list->next=NULL; + } + for (i=0; i < list->amplifiacount; i++) + cleanamplifia((list->amplifias)+i); + + ECOFREE(list,"Delete amplifia list"); + } + +} + +static int cmpamplifia(const void* p1,const void*p2) +{ + pamplifia_t pr1,pr2; + + pr1=(pamplifia_t)p1; + pr2=(pamplifia_t)p2; + + if (pr1->p1 < pr2->p1) return -1; + if (pr1->p1 > pr2->p1) return 1; + + if (pr1->asdirect1 < pr2->asdirect1) return -1; + if (pr1->asdirect1 > pr2->asdirect1) return 1; + + if (pr1->p2 < pr2->p2) return -1; + if (pr1->p2 > pr2->p2) return 1; + + if (pr1->asdirect2 < pr2->asdirect2) return -1; + if (pr1->asdirect2 > pr2->asdirect2) return 1; + + return 0; +} + +pamplifia_t amplifiaintree (amplifia_t key, + pamplifiatree_t amplifialist) +{ + if (!amplifialist->tree) + return NULL; + + return *((pamplifia_t*)tsearch((const void *)(&key), + &(amplifialist->tree), + cmpamplifia + )); +} + +pamplifia_t insertamplifia(amplifia_t key, + pamplifiatree_t list) +{ + pamplifia_t current; + pamplifia_t found; + + if (list->last->amplifiacount==list->last->amplifiaslots) + { + list->last->next=newamplifialist(list,100); + list->last=list->last->next; + } + + current = list->last->amplifias + list->last->amplifiacount; + *current=key; + + found = *((pamplifia_t*)tsearch((const void *)current, + &(list->tree), + cmpamplifia)); + if (found==current) + list->last->amplifiacount++; + + return found; +} + +pamplifiatree_t initamplifiatree(pamplifiatree_t tree) +{ + if (!tree) + tree = ECOMALLOC(sizeof(amplifiatree_t),"Cannot allocate amplifia tree"); + + tree->first=newamplifialist(NULL,500); + tree->last=tree->first; + + tree->tree=NULL; +} diff --git a/src/libecoprimer/pairtree.c b/src/libecoprimer/pairtree.c new file mode 100644 index 0000000..7155104 --- /dev/null +++ b/src/libecoprimer/pairtree.c @@ -0,0 +1,136 @@ +/* + * pairtree.c + * + * Created on: 7 mars 2009 + * Author: coissac + */ + +#include "ecoprimer.h" +#include + +static void cleanpair(ppair_t pair); +static void deletepairlist(ppairlist_t list); +static int cmppair(const void* p1,const void*p2); + + +static void cleanamplifiatlist(pamplifiacount_t list) +{ + if (list->amplifias) + ECOFREE(list->amplifias, + "Free amplifia list"); +} + +static void cleanpair(ppair_t pair) +{ + cleanamplifiatlist(&(pair->pcr)); +} + +static ppairlist_t newpairlist(ppairlist_t parent, size_t size) +{ + ppairlist_t tmp; + + tmp=ECOMALLOC(sizeof(pairlist_t)+sizeof(pair_t)*(size-1), + "Cannot allocate new pair list"); + + tmp->pairslots=size; + tmp->paircount=0; + tmp->next=NULL; + + if (parent) + parent->next=(void*)tmp; + + + return tmp; +} + +static void deletepairlist(ppairlist_t list) +{ + size_t i; + + if (list) + { + if (list->next) + { + deletepairlist(list->next); + list->next=NULL; + } + for (i=0; i < list->paircount; i++) + cleanpair((list->pairs)+i); + + ECOFREE(list,"Delete pair list"); + } + +} + +static int cmppair(const void* p1,const void*p2) +{ + ppair_t pr1,pr2; + + pr1=(ppair_t)p1; + pr2=(ppair_t)p2; + + if (pr1->p1 < pr2->p1) return -1; + if (pr1->p1 > pr2->p1) return 1; + + if (pr1->asdirect1 < pr2->asdirect1) return -1; + if (pr1->asdirect1 > pr2->asdirect1) return 1; + + if (pr1->p2 < pr2->p2) return -1; + if (pr1->p2 > pr2->p2) return 1; + + if (pr1->asdirect2 < pr2->asdirect2) return -1; + if (pr1->asdirect2 > pr2->asdirect2) return 1; + + return 0; +} + +ppair_t pairintree (pair_t key, + ppairtree_t pairlist) +{ + if (!pairlist->tree) + return NULL; + + return *((ppair_t*)tsearch((const void *)(&key), + &(pairlist->tree), + cmppair + )); +} + +ppair_t insertpair(pair_t key, + ppairtree_t list) +{ + ppair_t current; + ppair_t found; + + if (list->last->paircount==list->last->pairslots) + { + list->last->next=newpairlist(list->last,100); + list->last=list->last->next; + } + + current = list->last->pairs + list->last->paircount; + *current=key; + + found = *((ppair_t*)tsearch((const void *)current, + &(list->tree), + cmppair)); + if (found==current) + list->last->paircount++; + + return found; +} + +ppairtree_t initpairtree(ppairtree_t tree) +{ + + if (!tree) + tree = ECOMALLOC(sizeof(pairtree_t),"Cannot allocate pair tree"); + + tree->first=newpairlist(NULL,300); + tree->last=tree->first; + + tree->tree=NULL; + tree->count=0; + + return tree; +} diff --git a/src/libecoprimer/taxstats.c b/src/libecoprimer/taxstats.c new file mode 100644 index 0000000..5cf82b8 --- /dev/null +++ b/src/libecoprimer/taxstats.c @@ -0,0 +1,224 @@ +/* + * taxstats.c + * + * Created on: 12 mars 2009 + * Author: coissac + */ + +#include +#include "ecoprimer.h" + +static int cmptaxon(const void *t1, const void* t2); + +static int cmptaxon(const void *t1, const void* t2) +{ + const size_t taxid1=(size_t)t1; + const size_t taxid2=(size_t)t2; + + // fprintf(stderr,"==> counted taxid1 : %d\n",taxid1); + // fprintf(stderr,"==> counted taxid2 : %d\n",taxid2); + + if (taxid1 < taxid2) + return -1; + if (taxid1 > taxid2) + return +1; + return 0; +} + +int32_t counttaxon(int32_t taxid) +{ + static void* taxontree=NULL; + static int32_t taxoncount=0; + + // fprintf(stderr,"counted taxid : %d taxontree %p\n",taxid,taxontree); + + if (taxid==-1) + { + if (taxontree) + ECOFREE(taxontree,"Free taxon tree"); + taxontree=NULL; + taxoncount=0; + return 0; + } + + + if ((taxid > 0) && ((!taxontree) || (!tfind((void*)((size_t)taxid),&taxontree,cmptaxon)))) + { + tsearch((void*)((size_t)taxid),&taxontree,cmptaxon); + taxoncount++; + } + + return taxoncount; +} + +int32_t getrankdbstats(pecodnadb_t seqdb, uint32_t seqdbsize, ecotaxonomy_t *taxonomy, + poptions_t options) +{ + + uint32_t i; + ecotx_t *taxon; + ecotx_t *tmptaxon; + + counttaxon(-1); + + for (i=0;itaxons->taxon[seqdb[i]->taxid]); + seqdb[i]->isexample=isGoodTaxon(taxonomy,seqdb[i]->taxid,options); + + tmptaxon = eco_findtaxonatrank(taxon, + options->taxonrankidx); + + // fprintf(stderr,"Taxid : %d %p\n",taxon->taxid,tmptaxon); + + if (tmptaxon) + { + // fprintf(stderr,"orig : %d trans : %d\n",taxon->taxid, + // tmptaxon->taxid); + + seqdb[i]->ranktaxonid=tmptaxon->taxid; + if (seqdb[i]->isexample) + options->intaxa = counttaxon(tmptaxon->taxid); + } + else + seqdb[i]->ranktaxonid=-1; + } + + counttaxon(-1); + + for (i=0;iranktaxonid>=0 && !seqdb[i]->isexample) + options->outtaxa = counttaxon(seqdb[i]->ranktaxonid); + } + + return options->outtaxa + options->intaxa; +} + + +float taxonomycoverage(ppair_t pair, poptions_t options) +{ + int32_t seqcount; + int32_t i; + int32_t incount=0; + int32_t outcount=0; + + + seqcount=pair->pcr.ampcount; + + counttaxon(-1); + for (i=0; i < seqcount; i++) + if (pair->pcr.amplifias[i].sequence->isexample) + incount = counttaxon(pair->pcr.amplifias[i].sequence->ranktaxonid); + + counttaxon(-1); + for (i=0; i < seqcount; i++) + if (!pair->pcr.amplifias[i].sequence->isexample) + outcount = counttaxon(pair->pcr.amplifias[i].sequence->ranktaxonid); + + + pair->intaxa=incount; + pair->outtaxa=outcount; + return (float)incount/options->intaxa; +} + + +static int cmpamp(const void *ampf1, const void* ampf2) +{ + int i; + int j = 0; + int incr = 1; + char cd1; + char cd2; + int chd = 0; + int len = 0; + + pamptotaxon_t pampf1 = (pamptotaxon_t) ampf1; + pamptotaxon_t pampf2 = (pamptotaxon_t) ampf2; + + + if (pampf1->strand != pampf2->strand) + { + incr = -1; + j = pampf1->length - 1; + if (pampf2->strand) + { + pampf1 = (pamptotaxon_t) ampf2; + pampf2 = (pamptotaxon_t) ampf1; + chd = 1; + } + } + + len = (pampf1->length <= pampf2->length)? pampf1->length: pampf2->length; + + for (i = 0; i < len; i++, j += incr) + { + cd1 = pampf1->amplifia[i]; + if (incr == -1) + cd2 = ecoComplementChar(pampf2->amplifia[j]); + else + cd2 = pampf2->amplifia[j]; + + if (cd1 < cd2) return chd ? 1: -1; + if (cd2 < cd1) return chd ? -1: 1; + } + + if (pampf1->length > pampf2->length) return chd ? -1: 1; + if (pampf2->length > pampf1->length) return chd ? 1: -1; + + return 0; +} + +void twalkaction (const void *node, VISIT order, int level) +{ + const size_t taxid=(size_t)node; + counttaxon(taxid); +} + +void taxonomyspecificity (ppair_t pair) +{ + uint32_t i; + uint32_t ampfindex = 0; + int32_t taxid; + void *ampftree = NULL; + pamptotaxon_t pcurrentampf; + pamptotaxon_t *ptmp; + + pamptotaxon_t ampfwithtaxtree = ECOMALLOC(sizeof(amptotaxon_t) * pair->pcr.ampcount,"Cannot allocate amplifia tree"); + + for (i = 0; i < pair->pcr.ampcount; i++) + { + /*populate taxon ids tree against each unique amplifia + i.e set of taxon ids for each amplifia*/ + ampfwithtaxtree[ampfindex].amplifia = pair->pcr.amplifias[i].amplifia; + ampfwithtaxtree[ampfindex].strand = pair->pcr.amplifias[i].strand; + ampfwithtaxtree[ampfindex].length = pair->pcr.amplifias[i].length; + pcurrentampf = &fwithtaxtree[ampfindex]; + taxid = pair->pcr.amplifias[i].sequence->ranktaxonid; + ptmp = tfind((const void*)pcurrentampf, &ftree, cmpamp); + if (ptmp == NULL) + { + pcurrentampf = &fwithtaxtree[ampfindex]; + tsearch((void*)pcurrentampf,&ftree,cmpamp); + ampfindex++; + } + else + pcurrentampf = *ptmp; + + if (tfind((void*)((size_t)taxid), &(pcurrentampf->taxontree), cmptaxon) == NULL) + { + pcurrentampf->taxoncount++; + tsearch((void*)((size_t)taxid),&(pcurrentampf->taxontree),cmptaxon); + } + } + + counttaxon(-1); + for (i = 0; i < ampfindex; i++) + { + if (ampfwithtaxtree[i].taxoncount > 1) + twalk(ampfwithtaxtree[i].taxontree, twalkaction); + } + + pair->notwellidentifiedtaxa = counttaxon(-2); + ECOFREE (ampfwithtaxtree, "Free amplifia table"); +} \ No newline at end of file