libStatGen Software  1
PedigreePerson.cpp
1 /*
2  * Copyright (C) 2010 Regents of the University of Michigan
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "PedigreePerson.h"
19 #include "Constant.h"
20 #include "StringArray.h"
21 #include "Error.h"
22 
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include <string.h>
26 #include <limits.h>
27 
28 Person::Person()
29 {
30  zygosity = sex = 0;
31  serial = traverse = -1;
32 
33  markers = new Alleles [markerCount];
34  traits = new double [traitCount];
35  covariates = new double [covariateCount];
36  affections = new char [affectionCount];
37  strings = new String [stringCount];
38 
39  for (int i = 0; i < traitCount; i++) traits[i] = _NAN_;
40  for (int i = 0; i < covariateCount; i++) covariates[i] = _NAN_;
41  for (int i = 0; i < affectionCount; i++) affections[i] = 0;
42 
43  filter = false;
44 
45  father = mother = NULL;
46  sibs = NULL;
47  sibCount = 0;
48 
49  ngeno = 0;
50  hasBothParents = hasAllTraits = hasAllAffections = hasAllCovariates = false;
51 }
52 
53 Person::~Person()
54 {
55  delete [] markers;
56  delete [] traits;
57  delete [] affections;
58  delete [] covariates;
59  delete [] strings;
60 
61  if (sibCount) delete [] sibs;
62 }
63 
64 void Person::Copy(Person & rhs)
65 {
66  CopyIDs(rhs);
67  CopyPhenotypes(rhs);
68 }
69 
70 void Person::CopyPhenotypes(Person & rhs)
71 {
72  for (int i = 0; i < Person::traitCount; i++)
73  traits[i] = rhs.traits[i];
74  for (int i = 0; i < Person::affectionCount; i++)
75  affections[i] = rhs.affections[i];
76  for (int i = 0; i < Person::covariateCount; i++)
77  covariates[i] = rhs.covariates[i];
78  for (int i = 0; i < Person::markerCount; i++)
79  markers[i] = rhs.markers[i];
80  ngeno = rhs.ngeno;
81 }
82 
83 void Person::WipePhenotypes(bool remove_genotypes)
84 {
85  for (int i = 0; i < traitCount; i++) traits[i] = _NAN_;
86  for (int i = 0; i < covariateCount; i++) covariates[i] = _NAN_;
87  for (int i = 0; i < affectionCount; i++) affections[i] = 0;
88 
89  if (remove_genotypes)
90  {
91  for (int i = 0; i < markerCount; i++)
92  markers[i][0] = markers[i][1] = 0;
93  ngeno = 0;
94  }
95 }
96 
97 void Person::CopyIDs(Person & rhs)
98 {
99  famid = rhs.famid;
100  pid = rhs.pid;
101  fatid = rhs.fatid;
102  motid = rhs.motid;
103  sex = rhs.sex;
104  zygosity = rhs.zygosity;
105 }
106 
107 bool Person::CheckParents()
108 {
109  hasBothParents = father != NULL && mother != NULL;
110 
111  if (!hasBothParents)
112  {
113  if (father != NULL || mother != NULL)
114  {
115  printf("Parent named %s for Person %s in Family %s is missing\n",
116  (father == NULL) ? (const char *) fatid : (const char *) motid,
117  (const char *) pid, (const char *) famid);
118  return false;
119  }
120  else
121  return true;
122  }
123 
124  if (father->sex == SEX_FEMALE || mother->sex == SEX_MALE)
125  // If parents are switched around, we can fix it...
126  {
127  Person * swap = father;
128  father = mother;
129  mother = swap;
130 
131  String temp = fatid;
132  fatid = motid;
133  motid = temp;
134  }
135 
136  if (father->sex == SEX_FEMALE || mother->sex == SEX_MALE)
137  // If things still don't make sense then the problem is more serious ...
138  {
139  printf("Parental sex codes don't make sense for Person %s in Family %s\n",
140  (const char *) pid, (const char *) famid);
141  return false;
142  }
143 
144  return true;
145 }
146 
147 void Person::AssessStatus()
148 {
149  hasBothParents = father != NULL && mother != NULL;
150 
151  hasAllTraits = hasAllAffections = hasAllCovariates = true;
152 
153  ngeno = 0;
154  for (int m = 0; m < markerCount; m++)
155  if (isGenotyped(m))
156  ngeno++;
157 
158  for (int t = 0; t < traitCount; t++)
159  if (!isPhenotyped(t))
160  {
161  hasAllTraits = false;
162  break;
163  }
164 
165  for (int c = 0; c < covariateCount; c++)
166  if (!isControlled(c))
167  {
168  hasAllCovariates = false;
169  break;
170  }
171 
172  for (int a = 0; a < affectionCount; a++)
173  if (!isDiagnosed(a))
174  {
175  hasAllAffections = false;
176  break;
177  }
178 }
179 
180 void Person::Order(Person * & p1, Person * & p2)
181 {
182  if (p1->traverse > p2->traverse)
183  {
184  Person * temp = p1;
185  p1 = p2;
186  p2 = temp;
187  }
188 }
189 
190 int Person::GenotypedMarkers()
191 {
192  int count = 0;
193 
194  for (int m = 0; m < Person::markerCount; m++)
195  if (markers[m].isKnown())
196  count++;
197 
198  return count;
199 }
200 
201 bool Person::haveData()
202 {
203  if (ngeno)
204  return true;
205 
206  for (int i = 0; i < affectionCount; i++)
207  if (affections[i] != 0)
208  return true;
209 
210  for (int i = 0; i < traitCount; i++)
211  if (traits[i] != _NAN_)
212  return true;
213 
214  return false;
215 }
216 
217 bool Person::isAncestor(Person * descendant)
218 {
219  if (traverse > descendant->traverse)
220  return false;
221 
222  if (serial == descendant->serial)
223  return true;
224 
225  if (descendant->isFounder())
226  return false;
227 
228  return (isAncestor(descendant->mother) ||
229  isAncestor(descendant->father));
230 }