libStatGen Software
1
|
00001 /* 00002 * Copyright (C) 2010 Regents of the University of Michigan 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include "Pedigree.h" 00019 #include "Error.h" 00020 00021 #include <stdio.h> 00022 00023 bool Pedigree::TwinCheck() 00024 { 00025 bool fail = false; 00026 IntArray mzTwins; 00027 00028 for (int f = 0; f < familyCount; f++) 00029 { 00030 mzTwins.Clear(); 00031 00032 for (int i = families[f]->first, j; i <= families[f]->last; i++) 00033 // Is this person an identical twin? 00034 if (persons[i]->isMzTwin(*persons[i])) 00035 { 00036 // Have we got another identical sib yet? 00037 for (j = 0; j < mzTwins.Length(); j++) 00038 if (persons[i]->isMzTwin(*persons[mzTwins[j]])) 00039 break; 00040 00041 // If not, add to list of twins 00042 if (j == mzTwins.Length()) 00043 { 00044 mzTwins.Push(i); 00045 continue; 00046 } 00047 00048 // Check that their genotypes are compatible and 00049 // merge new twin's genotypes into original twin... 00050 Person * original = persons[mzTwins[j]]; 00051 Person * twin = persons[i]; 00052 00053 for (int m = 0; m < Person::markerCount; m++) 00054 { 00055 if (!original->markers[m].isKnown()) 00056 original->markers[m] = twin->markers[m]; 00057 else if (twin->markers[m].isKnown() && 00058 twin->markers[m] != original->markers[m]) 00059 printf("MZ Twins %s and %s in family %s have " 00060 "different %s genotypes\n", 00061 (const char *) original->pid, 00062 (const char *) twin->pid, 00063 (const char *) original->famid, 00064 (const char *) Person::markerNames[m]), 00065 fail = true; 00066 00067 if (twin->sex != original->sex) 00068 printf("MZ Twins %s and %s in family %s have " 00069 "different sexes\n", 00070 (const char *) original->pid, 00071 (const char *) twin->pid, 00072 (const char *) original->famid), 00073 fail = true; 00074 } 00075 } 00076 00077 if (mzTwins.Length() == 0) continue; 00078 00079 // In the second pass we copy merged twin genotypes 00080 // from original twin to other twins 00081 for (int i = families[f]->first, j; i <= families[f]->last; i++) 00082 if (persons[i]->isMzTwin(*persons[i])) 00083 { 00084 for (j = 0; j < mzTwins.Length(); j++) 00085 if (persons[i]->isMzTwin(*persons[mzTwins[j]])) 00086 break; 00087 00088 if (mzTwins[j] == i) continue; 00089 00090 Person * original = persons[mzTwins[j]]; 00091 Person * twin = persons[i]; 00092 00093 for (int m = 0; m < Person::markerCount; m++) 00094 twin->markers[m] = original->markers[m]; 00095 } 00096 } 00097 return fail; 00098 } 00099 00100 void Pedigree::MergeTwins() 00101 { 00102 if (!haveTwins) return; 00103 00104 IntArray mzTwins, surplus; 00105 00106 printf("Merging MZ twins into a single individual...\n"); 00107 00108 for (int f = 0; f < familyCount; f++) 00109 { 00110 mzTwins.Clear(); 00111 00112 for (int i = families[f]->first, j; i <= families[f]->last; i++) 00113 if (persons[i]->isMzTwin(*persons[i])) 00114 { 00115 // Have we got another identical sib yet? 00116 for (j = 0; j < mzTwins.Length(); j++) 00117 if (persons[i]->isMzTwin(*persons[mzTwins[j]])) 00118 break; 00119 00120 // If not, add to list of twins 00121 if (j == mzTwins.Length()) 00122 { 00123 mzTwins.Push(i); 00124 continue; 00125 } 00126 00127 // Append name to first twins name 00128 persons[mzTwins[j]]->pid += ((char) '$') + persons[i]->pid; 00129 00130 // Set the first twin to affected if at least one of the cotwins is affected 00131 for (int j = 0; j < affectionCount; j++) 00132 if (persons[i]->affections[j] == 2) 00133 persons[mzTwins[j]]->affections[j] = 2; 00134 00135 surplus.Push(i); 00136 } 00137 00138 // More than one representative of each twin-pair... 00139 if (surplus.Length()) 00140 { 00141 // Reassign parent names for each offspring 00142 for (int i = families[f]->first, j; i < families[f]->last; i++) 00143 if (!persons[i]->isFounder()) 00144 { 00145 if (persons[i]->father->isMzTwin(*persons[i]->father)) 00146 { 00147 for (j = 0; j < mzTwins.Length(); j++) 00148 if (persons[i]->father->isMzTwin(*persons[mzTwins[j]])) 00149 break; 00150 persons[i]->fatid = persons[mzTwins[j]]->pid; 00151 } 00152 if (persons[i]->mother->isMzTwin(*persons[i]->mother)) 00153 { 00154 for (j = 0; j < mzTwins.Length(); j++) 00155 if (persons[i]->mother->isMzTwin(*persons[mzTwins[j]])) 00156 break; 00157 persons[i]->motid = persons[mzTwins[j]]->pid; 00158 } 00159 } 00160 00161 // Delete surplus individuals 00162 while (surplus.Length()) 00163 { 00164 int serial = surplus.Pop(); 00165 00166 delete persons[serial]; 00167 00168 for (count--; serial < count; serial++) 00169 persons[serial] = persons[serial + 1]; 00170 } 00171 00172 // Resort pedigree 00173 Sort(); 00174 } 00175 } 00176 } 00177 00178 00179 00180