1 // $Id: ui_vars_datapackplus.cpp,v 1.34 2012/03/09 22:55:20 jmcgill Exp $
2 
3 /*
4   Copyright 2002  Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein
5 
6   This software is distributed free of charge for non-commercial use
7   and is copyrighted.  Of course, we do not guarantee that the software
8   works, and are not responsible for any damage you may cause or have.
9 */
10 
11 #include <cassert>
12 #include <set>
13 
14 #include "datapack.h"
15 #include "dlmodel.h"
16 #include "errhandling.h"
17 #include "region.h"
18 #include "stringx.h"
19 #include "ui_vars.h"
20 #include "ui_vars_datapackplus.h"
21 #include "ui_strings.h"
22 
23 //------------------------------------------------------------------------------------
24 
UIVarsDataPackPlus(UIVars * myUIVars,DataPack & dp)25 UIVarsDataPackPlus::UIVarsDataPackPlus(UIVars * myUIVars, DataPack& dp)
26     : UIVarsComponent(myUIVars),
27       datapack(dp),
28       m_effectivePopSizes(),
29       m_simulateData()
30 {
31     for (long regnum=0; regnum<GetNumRegions(); regnum++)
32     {
33         m_effectivePopSizes.push_back(datapack.GetRegion(regnum).GetEffectivePopSize());
34         deque<bool> nosims(GetNumLoci(regnum), false);
35         m_simulateData.push_back(nosims);
36     }
37 }
38 
UIVarsDataPackPlus(UIVars * myUIVars,const UIVarsDataPackPlus & dpp)39 UIVarsDataPackPlus::UIVarsDataPackPlus(UIVars * myUIVars, const UIVarsDataPackPlus& dpp)
40     : UIVarsComponent(myUIVars),
41       datapack(dpp.datapack),
42       m_effectivePopSizes(dpp.m_effectivePopSizes),
43       m_simulateData(dpp.m_simulateData)
44 {
45 }
46 
~UIVarsDataPackPlus()47 UIVarsDataPackPlus::~UIVarsDataPackPlus()
48 {
49 }
50 
51 long
GetMaxLoci() const52 UIVarsDataPackPlus::GetMaxLoci() const
53 {
54     long maxL = 0;
55     long numRegions = GetNumRegions();
56     for(long i=0; i < numRegions; i++)
57     {
58         long lociCount = GetNumLoci(i);
59         if(lociCount > maxL)
60         {
61             maxL = lociCount;
62         }
63     }
64 
65     return maxL;
66 }
67 
68 long
GetNumRegions() const69 UIVarsDataPackPlus::GetNumRegions() const
70 {
71     return datapack.GetNRegions();
72 }
73 
74 long
GetNumLoci(long regIndex) const75 UIVarsDataPackPlus::GetNumLoci(long regIndex) const
76 {
77     return datapack.GetRegion(regIndex).GetNloci();
78 }
79 
80 long
GetNCrossPartitions() const81 UIVarsDataPackPlus::GetNCrossPartitions() const
82 {
83     return datapack.GetNCrossPartitions();
84 }
85 
86 long
GetNPartitionsByForceType(force_type ft) const87 UIVarsDataPackPlus::GetNPartitionsByForceType(force_type ft) const
88 {
89     return datapack.GetNPartitionsByForceType(ft);
90 }
91 
GetEffectivePopSize(long region) const92 double UIVarsDataPackPlus::GetEffectivePopSize(long region) const
93 {
94     return m_effectivePopSizes[region];
95 }
96 
GetNumIndividualsWithMultipleHaplotypes(long region,string lname) const97 long UIVarsDataPackPlus::GetNumIndividualsWithMultipleHaplotypes(long region, string lname) const
98 {
99     long nMultiInd=0;
100     const IndVec individuals = datapack.GetRegion(region).GetIndividuals();
101     for (unsigned long ind=0; ind<individuals.size(); ind++)
102     {
103         if (individuals[ind].GetHaplotypesFor(lname, 0).MultipleHaplotypes())
104         {
105             nMultiInd++;
106         }
107     }
108     return nMultiInd;
109 }
110 
GetSimulateData(long region,long locus) const111 bool UIVarsDataPackPlus::GetSimulateData(long region, long locus) const
112 {
113     if (region < 0 || locus < 0)
114     {
115         assert(false); //Don't ask about this! (probably FLAGLONG or the like)
116         return false;
117     }
118     return m_simulateData[region][locus];
119 }
120 
121 // LS NOTE:  This should move into the converter eventually.  Probably.
SetEffectivePopSize(long region,double size)122 void UIVarsDataPackPlus::SetEffectivePopSize(long region, double size)
123 {
124     if (size <= 0)
125     {
126         throw data_error("The effective population size must be positive.");
127     }
128     assert(region < GetNumRegions());
129     if (region >= static_cast<long>(m_effectivePopSizes.size()))
130     {
131         throw implementation_error("Unable to set this region's size--vector not long enough.");
132     }
133     m_effectivePopSizes[region] = size;
134 
135     // may need to update start values at this point
136     GetUIVars().forces.FillCalculatedStartValues();
137 }
138 
SetSimulateData(long region,long locus,bool sim)139 void UIVarsDataPackPlus::SetSimulateData(long region, long locus, bool sim)
140 {
141     m_simulateData[region][locus] = sim;
142 }
143 
RevertAllMovingLoci()144 void UIVarsDataPackPlus::RevertAllMovingLoci()
145 {
146     for (long reg=0; reg<GetNumRegions(); reg++)
147     {
148         datapack.GetRegion(reg).RevertMovingLoci();
149     }
150 }
151 
152 bool
CanHapArrange() const153 UIVarsDataPackPlus::CanHapArrange() const
154 {
155     return datapack.CanHapArrange();
156 }
157 
158 bool
HasSomeNucleotideData() const159 UIVarsDataPackPlus::HasSomeNucleotideData() const
160 {
161     for (long reg=0; reg<GetNumRegions(); reg++)
162     {
163         for (long loc=0; loc<GetNumLoci(reg); loc++)
164         {
165             if ((GetDataType(reg, loc) == dtype_DNA) || (GetDataType(reg, loc) == dtype_SNP))
166             {
167                 return true;
168             }
169         }
170     }
171     return false;
172 }
173 
174 bool
HasSomeMsatData() const175 UIVarsDataPackPlus::HasSomeMsatData() const
176 {
177     for (long reg=0; reg<GetNumRegions(); reg++)
178     {
179         for (long loc=0; loc<GetNumLoci(reg); loc++)
180         {
181             if (GetDataType(reg, loc) == dtype_msat)
182             {
183                 return true;
184             }
185         }
186     }
187     return false;
188 }
189 
190 bool
HasSomeKAlleleData() const191 UIVarsDataPackPlus::HasSomeKAlleleData() const
192 {
193     for (long reg=0; reg<GetNumRegions(); reg++)
194     {
195         for (long loc=0; loc<GetNumLoci(reg); loc++)
196         {
197             if (GetDataType(reg, loc) == dtype_kallele)
198             {
199                 return true;
200             }
201         }
202     }
203     return false;
204 }
205 
206 string
GetCrossPartitionName(long index) const207 UIVarsDataPackPlus::GetCrossPartitionName(long index) const
208 {
209     return GetCrossPartitionNames()[index];
210 }
211 
212 StringVec1d
GetCrossPartitionNames() const213 UIVarsDataPackPlus::GetCrossPartitionNames() const
214 {
215     return datapack.GetAllCrossPartitionNames();
216 }
217 
218 string
GetForcePartitionName(force_type ft,long index) const219 UIVarsDataPackPlus::GetForcePartitionName(force_type ft, long index) const
220 {
221     StringVec1d names = GetForcePartitionNames(ft);
222     return names[index];
223 }
224 
225 StringVec1d
GetForcePartitionNames(force_type ft) const226 UIVarsDataPackPlus::GetForcePartitionNames(force_type ft) const
227 {
228     return datapack.GetAllPartitionNames(ft);
229 }
230 
231 string
GetLocusName(long regionIndex,long locusIndex) const232 UIVarsDataPackPlus::GetLocusName(long regionIndex, long locusIndex) const
233 {
234     string name = datapack.GetRegion(regionIndex).GetLocus(locusIndex).GetName();
235     string locID;
236     //LS DEBUG MAPPING:  When IsMovable is no longer sufficient to tell if
237     // something is a trait or not, (i.e. if it's being used to partition data)
238     // this will need to be changed.
239     if (datapack.GetRegion(regionIndex).GetLocus(locusIndex).IsMovable())
240     {
241         locID = ", trait ";
242     }
243     else
244     {
245         if (datapack.GetRegion(regionIndex).GetNloci() == 1)
246         {
247             //We assume that if there is only one locus in a region, the thing
248             // that has better name recognition is the region, not the locus.
249             locID = ": ";
250             name = datapack.GetRegion(regionIndex).GetRegionName();
251         }
252         else
253         {
254             locID = ", segment " + indexToKey(locusIndex) + " : ";
255         }
256     }
257 
258     string fullname = "Region "+indexToKey(regionIndex) + locID + name;
259     return fullname;
260 }
261 
262 long
GetLocusIndex(long regionIndex,string locusName) const263 UIVarsDataPackPlus::GetLocusIndex(long regionIndex, string locusName) const
264 {
265     return datapack.GetRegion(regionIndex).GetLocusIndex(locusName);
266 }
267 
268 bool
HasLocus(long regionIndex,string locusName) const269 UIVarsDataPackPlus::HasLocus(long regionIndex, string locusName) const
270 {
271     return datapack.GetRegion(regionIndex).HasLocus(locusName);
272 }
273 
274 string
GetRegionName(long index) const275 UIVarsDataPackPlus::GetRegionName(long index) const
276 {
277     string name = datapack.GetRegion(index).GetRegionName();
278     string fullname = "Region "+indexToKey(index)+" : "+name;
279     return fullname;
280 }
281 
282 string
GetSimpleRegionName(long index) const283 UIVarsDataPackPlus::GetSimpleRegionName(long index) const
284 {
285     return datapack.GetRegion(index).GetRegionName();
286 }
287 
288 string
GetParamName(force_type ftype,long index,bool doLongName) const289 UIVarsDataPackPlus::GetParamName(force_type ftype, long index,bool doLongName) const
290 {
291     string pname = "";
292     long fromIndex;
293     long toIndex;
294     long nstates;
295     switch(ftype)
296     {
297         case force_COAL:
298             if(doLongName)
299             {
300                 pname += uistr::theta + " for ";
301                 pname += GetCrossPartitionName(index);
302             }
303             else
304             {
305                 pname += "Theta";
306                 pname += indexToKey(index);
307             }
308             break;
309         case force_DIVERGENCE:
310             // MDEBUG should use uistr:: variables here
311             if(doLongName)
312             {
313                 pname += uistr::divergenceEpochBoundaryTime + " for ";
314                 pname += ToString(index);
315             }
316             else
317             {
318 
319                 pname += "Epoch " + ToString(index);
320             }
321            break;
322         case force_DISEASE:
323             nstates = GetNPartitionsByForceType(ftype);
324             toIndex = index / nstates;
325             fromIndex = index % nstates;
326             if(doLongName)
327             {
328                 pname += uistr::muRate + " from ";
329                 pname += GetForcePartitionName(ftype,fromIndex);
330                 pname += " to ";
331                 pname += GetForcePartitionName(ftype,toIndex);
332             }
333             else
334             {
335                 pname += "D";
336                 pname += indexToKey(fromIndex);
337                 pname += indexToKey(toIndex);
338             }
339             break;
340         case force_EXPGROWSTICK:
341         case force_GROW:
342             if(doLongName)
343             {
344                 pname += uistr::growthRate + " for ";
345                 pname += GetCrossPartitionName(index);
346             }
347             else
348             {
349                 pname += "Growth";
350                 pname += indexToKey(index);
351             }
352             break;
353         case force_MIG:
354         case force_DIVMIG:
355             nstates = GetNPartitionsByForceType(ftype);
356             toIndex = index / nstates;
357             fromIndex = index % nstates;
358             if(doLongName)
359             {
360                 pname += uistr::migrationByID;
361                 pname += GetForcePartitionName(ftype,toIndex);
362                 pname += uistr::migrationByID2;
363                 pname += GetForcePartitionName(ftype,fromIndex);
364             }
365             else
366             {
367                 pname += "M";
368                 pname += indexToKey(fromIndex);
369                 pname += indexToKey(toIndex);
370             }
371             break;
372         case force_REC:
373             if(doLongName)
374             {
375                 pname += uistr::recRate;
376             }
377             else
378             {
379                 pname += "Rec";
380             }
381             break;
382         case force_REGION_GAMMA:
383             if(doLongName)
384             {
385                 pname += uistr::regGammaShape;
386             }
387             else
388             {
389                 pname += "ShapeParam";
390             }
391             break;
392         case force_LOGSELECTSTICK:
393         case force_LOGISTICSELECTION:
394             if(doLongName)
395             {
396                 pname += uistr::logisticSelectionCoefficient;
397             }
398             else
399             {
400                 pname += "Sel. Coeff.";
401             }
402             break;
403         case force_NONE:
404             assert(false);
405             pname += "No force";
406             break;
407     }
408     return pname;
409 }
410 
411 string
GetParamNameOfForce(force_type ftype) const412 UIVarsDataPackPlus::GetParamNameOfForce(force_type ftype) const
413 {
414     switch(ftype)
415     {
416         case force_COAL:
417             return "Theta";
418             break;
419         case force_DISEASE:
420             return "Disease Mutation Rate";
421             break;
422         case force_GROW:
423             return "Growth Rate";
424             break;
425         case force_DIVERGENCE:
426             return "Epoch Boundary Time";
427             break;
428         case force_DIVMIG:
429         case force_MIG:
430             return "Migration Rate";
431             break;
432         case force_REC:
433             return "Recombination Rate";
434             break;
435         case force_REGION_GAMMA:
436             return "Gamma Over Regions";
437             break;
438         case force_EXPGROWSTICK:
439             return "Exponential Growth via stick";
440             break;
441         case force_LOGISTICSELECTION:
442             return "Logistic Selection Coefficient";
443             break;
444         case force_LOGSELECTSTICK:
445             return "Logistic Selection via stick";
446             break;
447         case force_NONE:
448             assert(false);
449             throw implementation_error("UIVarsDataPackPlus::GetParamNameOfForce for force_NONE!");
450             break;
451     };
452     assert(false);
453     throw implementation_error("UIVarsDataPackPlus::GetParamNameOfForce missing switch case");
454 }
455 
456 data_type
GetDataType(long regionId,long locusId) const457 UIVarsDataPackPlus::GetDataType(long regionId, long locusId) const
458 {
459     const Region & thisRegion = datapack.GetRegion(regionId);
460     const Locus & thisLocus = thisRegion.GetLocus(locusId);
461     return thisLocus.GetDataType();
462 }
463 
IsMovable(long regionId,long locusId) const464 bool UIVarsDataPackPlus::IsMovable(long regionId, long locusId) const
465 {
466     const Region & thisRegion = datapack.GetRegion(regionId);
467     const Locus & thisLocus = thisRegion.GetLocus(locusId);
468     return thisLocus.IsMovable();
469 }
470 
GetName(long regionId,long locusId) const471 string UIVarsDataPackPlus::GetName(long regionId, long locusId) const
472 {
473     const Region & thisRegion = datapack.GetRegion(regionId);
474     const Locus & thisLocus = thisRegion.GetLocus(locusId);
475     return thisLocus.GetName();
476 }
477 
GetRange(long regionId,long locusId) const478 rangeset UIVarsDataPackPlus::GetRange(long regionId, long locusId) const
479 {
480     const Region & thisRegion = datapack.GetRegion(regionId);
481     const Locus & thisLocus = thisRegion.GetLocus(locusId);
482     return thisLocus.GetAllowedRange();
483 }
484 
GetRegionSiteSpan(long regionId) const485 rangepair UIVarsDataPackPlus::GetRegionSiteSpan(long regionId) const
486 {
487     return datapack.GetRegion(regionId).GetSiteSpan();
488 }
489 
GetNumSites(long regionId) const490 long UIVarsDataPackPlus::GetNumSites(long regionId) const
491 {
492     const Region & thisRegion = datapack.GetRegion(regionId);
493     return thisRegion.GetNumSites();
494 }
495 
GetNumSites(long regionId,long locusId) const496 long UIVarsDataPackPlus::GetNumSites(long regionId, long locusId) const
497 {
498     const Region & thisRegion = datapack.GetRegion(regionId);
499     const Locus & thisLocus = thisRegion.GetLocus(locusId);
500     return thisLocus.GetNsites();
501 }
502 
GetUniqueAlleles(long regionId,long locusId) const503 StringVec2d UIVarsDataPackPlus::GetUniqueAlleles(long regionId,
504                                                  long locusId) const
505 {
506     StringVec2d retVec;
507     const Region& thisRegion = datapack.GetRegion(regionId);
508     const Locus& thisLocus = thisRegion.GetLocus(locusId);
509     vector<TipData> tips = thisLocus.GetTipData();
510     const IndVec individuals = thisRegion.GetIndividuals();
511     for (long marker = 0; marker < thisLocus.GetNmarkers(); marker++)
512     {
513         std::set<string> uniqueAlleles;
514         //First, get any alleles from the unknown haplotypes
515         for (unsigned long ind=0; ind<individuals.size(); ind++)
516         {
517             StringVec1d alleles = individuals[ind].GetAllelesFor(thisLocus.GetName(), marker);
518             for (unsigned long nallele=0; nallele<alleles.size(); nallele++)
519             {
520                 if (alleles[nallele] != "?")
521                 {
522                     uniqueAlleles.insert(alleles[nallele]);
523                 }
524             }
525         }
526         //Now get any alleles from the tips
527         for (unsigned long tip = 0; tip < tips.size(); ++tip)
528         {
529             if (!tips[tip].m_nodata)
530             {
531                 string allele = tips[tip].data[marker];
532                 if (allele != "?")
533                 {
534                     uniqueAlleles.insert(allele);
535                 }
536             }
537         }
538         //Convert the set to a vector (for simplicity for our clients)
539         StringVec1d alleleStrings;
540         for (std::set<string>::iterator unique=uniqueAlleles.begin(); unique != uniqueAlleles.end(); unique++)
541         {
542             alleleStrings.push_back(*unique);
543         }
544         retVec.push_back(alleleStrings);
545     }
546     return retVec;
547 
548 }
549 
GetPloidies(long region) const550 std::set<long> UIVarsDataPackPlus::GetPloidies(long region) const
551 {
552     return datapack.GetRegion(region).GetPloidies();
553 }
554 
GetConstLocusPointer(long region,long locus) const555 const Locus* UIVarsDataPackPlus::GetConstLocusPointer(long region, long locus) const
556 {
557     return &datapack.GetRegion(region).GetLocus(locus);
558 }
559 
AnySimulation() const560 bool UIVarsDataPackPlus::AnySimulation() const
561 {
562     for (unsigned long region=0; region<m_simulateData.size(); region++)
563     {
564         for (unsigned long locus=0; locus<m_simulateData[region].size(); locus++)
565         {
566             if (m_simulateData[region][locus]) return true;
567         }
568     }
569     return false;
570 }
571 
AnyRelativeHaplotypes() const572 bool UIVarsDataPackPlus::AnyRelativeHaplotypes() const
573 {
574     for (long region=0; region<GetNumRegions(); region++)
575     {
576         const Region& reg = datapack.GetRegion(region);
577         for (long ind=0; ind<reg.GetNIndividuals(); ind++)
578         {
579             const Individual& indiv = reg.GetIndividual(ind);
580             if (indiv.MultipleTraitHaplotypes()) return true;
581         }
582     }
583     return false;
584 }
585 
AnySNPDataWithDefaultLocations() const586 bool UIVarsDataPackPlus::AnySNPDataWithDefaultLocations() const
587 {
588     for (long region=0; region<GetNumRegions(); region++)
589     {
590         if (datapack.GetRegion(region).AnySNPDataWithDefaultLocations())
591         {
592             return true;
593         }
594     }
595     return false;
596 }
597 
GetAncestorName(long index) const598 string UIVarsDataPackPlus::GetAncestorName(long index) const
599 {
600     //const Region & thisRegion = datapack.GetRegion(regionId);
601     //const Locus & thisLocus = thisRegion.GetLocus(locusId);
602     //uiInterface.GetCurrentVars().forces.AddAncestor(ancname);
603 
604     //return thisLocus.GetName();
605     //string pname = datapack.forces.UIVarsDivergenceForceGetParent(index).GetName();
606     //datapack.GetRegion(index).GetRegionName();
607     string pname = uistr::divergenceEpochAncestor;
608     pname += ToString(index + 1);
609 
610     return pname;
611 }
612 
GetDescendentNames(long index) const613 string UIVarsDataPackPlus::GetDescendentNames(long index) const
614 {
615     //const Region & thisRegion = datapack.GetRegion(regionId);
616     //const Locus & thisLocus = thisRegion.GetLocus(locusId);
617     //uiInterface.GetCurrentVars().forces.AddAncestor(ancname);
618 
619     //return thisLocus.GetName();
620     //string pname = datapack.forces.GetAncestor(index);
621     string pname = uistr::divergenceEpochDescendent;
622     pname += ToString(index + 1);
623     pname += "-1 ";
624     pname += uistr::divergenceEpochDescendent;
625     pname += ToString(index + 1);
626     pname += "-2";
627 
628     return pname;
629 }
630 
631 //____________________________________________________________________________________
632