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
Person()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
~Person()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
Copy(Person & rhs)64 void Person::Copy(Person & rhs)
65 {
66 CopyIDs(rhs);
67 CopyPhenotypes(rhs);
68 }
69
CopyPhenotypes(Person & rhs)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
WipePhenotypes(bool remove_genotypes)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
CopyIDs(Person & rhs)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
CheckParents()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
AssessStatus()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
Order(Person * & p1,Person * & p2)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
GenotypedMarkers()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
haveData()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
isAncestor(Person * descendant)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 }
231