public RParentChild( LinksDataSet dsLinks, LinksDataSet.tblRelatedStructureRow drLeft )
        {
            //ImportDataSet dsImport, , LinksDataSet.tblRelatedStructureRow drRight
            if ( dsLinks == null ) throw new ArgumentNullException("dsLinks");
            if ( drLeft == null ) throw new ArgumentNullException("drLeft");
            if ( dsLinks.tblSubject.Count == 0 ) throw new InvalidOperationException("tblSubject must NOT be empty before assigning R values from it.");
            _dsLinks = dsLinks;
            _drLeft = drLeft;
            _idRelatedLeft = _drLeft.ID;
            _drBare1 = _dsLinks.tblSubject.FindBySubjectTag(drLeft.SubjectTag_S1);
            _drBare2 = _dsLinks.tblSubject.FindBySubjectTag(drLeft.SubjectTag_S2);
            Trace.Assert(_drBare1.Generation != _drBare2.Generation, "The generation should not be the same for a parent-child relationship.");

            _multipleBirth = MultipleBirth.No;
            _isMZ = Tristate.No;

            //For IAssignPass1
            _rImplicitPass1 = RCoefficients.ParentChild;
            _rImplicit2004 = RCoefficients.ParentChild;
            _rExplicitOldestSibVersion = null;
            _rExplicitYoungestSibVersion = null;
            _rExplicitPass1 = RCoefficients.ParentChild;
            _rPass1 = RCoefficients.ParentChild;

            //For IAssignPass2
            _rImplicit = RCoefficients.ParentChild;
            _rImplicitSubject = RCoefficients.ParentChild;
            _rImplicitMother = RCoefficients.ParentChild;
            _rExplicit = RCoefficients.ParentChild;
            _rFull = RCoefficients.ParentChild;
            _rPeek = RCoefficients.ParentChild;
        }
        private float? _rPeek = null; //float.NaN;

        #endregion Fields

        #region Constructors

        public RGen1Pass2( LinksDataSet dsLinks, LinksDataSet.tblRelatedStructureRow drLeft, LinksDataSet.tblRelatedStructureRow drRight )
        {
            if ( dsLinks == null ) throw new ArgumentNullException("dsLinks");
            if ( drLeft == null ) throw new ArgumentNullException("drLeft");
            if ( drRight == null ) throw new ArgumentNullException("drRight");
            if ( dsLinks.tblRelatedValues.Count == 0 ) throw new InvalidOperationException("tblRelatedValues must be empty before updating rows for it.");
            if ( dsLinks.tblMzManual.Count == 0 ) throw new InvalidOperationException("tblMzManual must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblSubject.Count == 0 ) throw new InvalidOperationException("tblSubject must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblSubjectDetails.Count == 0 ) throw new InvalidOperationException("tblSubjectDetails must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblMarkerGen1.Count == 0 ) throw new InvalidOperationException("tblMarkerGen1 must NOT be empty before assigning R values from it.");
            _dsLinks = dsLinks;
            _drLeft = drLeft;
            _drRight = drRight;
            _idRelatedLeft = _drLeft.ID;
            _idRelatedRight = _drRight.ID;
            _drSubjectDetails1 = _dsLinks.tblSubjectDetails.FindBySubjectTag(drLeft.SubjectTag_S1);
            _drSubjectDetails2 = _dsLinks.tblSubjectDetails.FindBySubjectTag(drLeft.SubjectTag_S2);
            _extendedID = _drLeft.tblSubjectRowByFK_tblRelatedStructure_tblSubject_Subject1.ExtendedID;

            if ( _drSubjectDetails1.BirthOrderInNls <= _drSubjectDetails2.BirthOrderInNls ) {//This is the way it usually is.  Recall twins were assigned tied birth orders
                _idRelatedOlderAboutYounger = _idRelatedLeft; //_idRelatedYoungerAboutOlder = _idRelatedRight;
            }
            else if ( _drSubjectDetails1.BirthOrderInNls > _drSubjectDetails2.BirthOrderInNls ) {
                _idRelatedOlderAboutYounger = _idRelatedRight;
            }

            _drValue = _dsLinks.tblRelatedValues.FindByID(_idRelatedLeft);
            _dtMarkersGen1 = MarkerGen1.PairRelevantMarkerRows(_idRelatedLeft, _idRelatedRight, _dsLinks, _extendedID);

            Tristate explicitShareBiomom = AddressExplicitBiomom();
            Tristate explicitShareBiodad = AddressExplicitBiodad();

            Tristate implicitShareBiomom = AddressImplicitBiomom();
            Tristate implicitShareBiodad = AddressImplicitBiodad();

            _rExplicit = CommonFunctions.TranslateToR(shareBiomom: explicitShareBiomom, shareBiodad: explicitShareBiodad, mustDecide: true);
            _rImplicit = CommonFunctions.TranslateToR(shareBiomom: implicitShareBiomom, shareBiodad: implicitShareBiodad, mustDecide: false);//Possibly 'true' later one

            //_rFull = RGen1Pass1.CalculateRFull(shareBiomom: shareBiomom, shareBiodad: shareBiodad,
            //   multiple: (MultipleBirth)_drValue.MultipleBirthIfSameSex, isMZ: (Tristate)_drValue.IsMz, isRelatedInMZManual: (Tristate)_drValue.IsRelatedInMzManual,
            //   idRelated: _idRelatedLeft, dtRoster: _dsLinks.tblRosterGen1);

            if ( !_drValue.IsRPass1Null() ) {
                _rFull = (float)_drValue.RPass1;
            }
            else { //Don't do the expensive interpolation unless it will be used
                Tristate shareBiomom = AddressBiomom(explicitShareBiomom, implicitShareBiomom);
                Tristate shareBiodad = AddressBiodad(explicitShareBiodad, implicitShareBiodad);
                _rFull = CommonFunctions.TranslateToR(shareBiomom: shareBiomom, shareBiodad: shareBiodad, mustDecide: true);
            }

            LinksDataSet.tblRosterGen1Row drRoster = _dsLinks.tblRosterGen1.FindByRelatedID(_drValue.ID);
            _r = CalculateR(_rFull, (Tristate)drRoster.SameGeneration);
        }
        public RGen2Pass2( LinksDataSet dsLinks, LinksDataSet.tblRelatedStructureRow drLeft, LinksDataSet.tblRelatedStructureRow drRight )
        {
            //ImportDataSet dsImport,
            if ( dsLinks == null ) throw new ArgumentNullException("dsLinks");
            if ( drLeft == null ) throw new ArgumentNullException("drLeft");
            if ( drRight == null ) throw new ArgumentNullException("drRight");
            if ( dsLinks.tblRelatedValues.Count == 0 ) throw new InvalidOperationException("tblRelatedValues must be empty before updating rows for it.");
            if ( dsLinks.tblMzManual.Count == 0 ) throw new InvalidOperationException("tblMzManual must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblSubject.Count == 0 ) throw new InvalidOperationException("tblSubject must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblSubjectDetails.Count == 0 ) throw new InvalidOperationException("tblSubjectDetails must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblMarkerGen2.Count == 0 ) throw new InvalidOperationException("tblMarkerGen2 must NOT be empty before assigning R values from it.");
            _dsLinks = dsLinks;
            _drLeft = drLeft;
            _drRight = drRight;
            _idRelatedLeft = _drLeft.ID;
            _idRelatedRight = _drRight.ID;
            _drSubjectDetails1 = _dsLinks.tblSubjectDetails.FindBySubjectTag(drLeft.SubjectTag_S1);
            _drSubjectDetails2 = _dsLinks.tblSubjectDetails.FindBySubjectTag(drLeft.SubjectTag_S2);
            _extendedID = _drLeft.tblSubjectRowByFK_tblRelatedStructure_tblSubject_Subject1.ExtendedID;

            if ( _drSubjectDetails1.BirthOrderInNls <= _drSubjectDetails2.BirthOrderInNls ) {//This is the way it usually is.  Recall twins were assigned tied birth orders
                _idRelatedOlderAboutYounger = _idRelatedLeft;
            }
            else if ( _drSubjectDetails1.BirthOrderInNls > _drSubjectDetails2.BirthOrderInNls ) {
                _idRelatedOlderAboutYounger = _idRelatedRight;
            }

            _drValue = _dsLinks.tblRelatedValues.FindByID(_idRelatedLeft);
            _dtMarkersGen2 = MarkerGen2.PairRelevantMarkerRows(_idRelatedLeft, _idRelatedRight, _dsLinks, _extendedID);

            MarkerEvidence babyDaddyDeathDate = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyDeathDate, _dtMarkersGen2);
            MarkerEvidence babyDaddyAlive = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyAlive, _dtMarkersGen2);
            MarkerEvidence babyDaddyInHH = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyInHH, _dtMarkersGen2);
            MarkerEvidence babyDaddyLeftHHDate = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyLeftHHDate, _dtMarkersGen2);
            MarkerEvidence babyDaddyDistanceFromHH = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyDistanceFromHH, _dtMarkersGen2);

            MarkerEvidence fatherAlive = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.Gen2CFatherAlive, _dtMarkersGen2);
            MarkerEvidence fatherInHH = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.Gen2CFatherInHH, _dtMarkersGen2);
            MarkerEvidence fatherDistanceFromHH = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.Gen2CFatherDistanceFromHH, _dtMarkersGen2);

            _rImplicitMother = CalculateRImplicitMother(babyDaddyDeathDate, babyDaddyAlive, babyDaddyInHH, babyDaddyLeftHHDate, babyDaddyDistanceFromHH);
            _rImplicitSubject = CalculateRImplicitSubject(fatherAlive, fatherInHH, fatherDistanceFromHH);
            _rImplicit = CalculateRImplicit(_rImplicitMother, _rImplicitSubject);
            _rExplicit = CalculateRExplicit();
            _rFull = CalculateRFull();
            _rPeek = CalculateRPeek();
        }
        private float? _rPass1 = float.NaN; //  float.NaN;

        #endregion Fields

        #region Constructors

        public RGen1Pass1( ImportDataSet dsImport, LinksDataSet dsLinks, LinksDataSet.tblRelatedStructureRow drLeft, LinksDataSet.tblRelatedStructureRow drRight )
        {
            if ( dsImport == null ) throw new ArgumentNullException("dsImport");
            if ( dsLinks == null ) throw new ArgumentNullException("dsLinks");
            if ( drLeft == null ) throw new ArgumentNullException("drLeft");
            if ( drRight == null ) throw new ArgumentNullException("drRight");
            if ( dsImport.tblLinks2004Gen1.Count == 0 ) throw new InvalidOperationException("tblLinks2004Gen1 must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblMzManual.Count == 0 ) throw new InvalidOperationException("tblMzManual must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblSubject.Count == 0 ) throw new InvalidOperationException("tblSubject must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblRosterGen1.Count == 0 ) throw new InvalidOperationException("tblRosterGen1 must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblMarkerGen1.Count == 0 ) throw new InvalidOperationException("tblMarkerGen2 must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblSubjectDetails.Count == 0 ) throw new InvalidOperationException("tblSubjectDetails must NOT be empty before assigning R values from it.");

            _dsImport = dsImport;
            _dsLinks = dsLinks;
            _drLeft = drLeft;
            _drRight = drRight;
            _idRelatedLeft = _drLeft.ID;
            _idRelatedRight = _drRight.ID;
            _drSubjectDetails1 = _dsLinks.tblSubjectDetails.FindBySubjectTag(drLeft.SubjectTag_S1);
            _drSubjectDetails2 = _dsLinks.tblSubjectDetails.FindBySubjectTag(drLeft.SubjectTag_S2);
            _extendedID = _drLeft.tblSubjectRowByFK_tblRelatedStructure_tblSubject_Subject1.ExtendedID;

            //LinksDataSet.tblRosterGen1Row drRoster = _dsLinks.tblRosterGen1.FindByRelatedID(drLeft.ID);
            //Tristate rosterShareBiomom = (Tristate)drRoster.ShareBiomom;
            //Tristate rosterShareBiodad = (Tristate)drRoster.ShareBiodad;
            //if ( drRoster.IsRNull() ) _rRoster = null;
            //else _rRoster = (float)drRoster.R;

            if ( _drSubjectDetails1.BirthOrderInNls <= _drSubjectDetails2.BirthOrderInNls ) {//This is the way it usually is.  Remember that twins were assigned tied birth orders
                _idRelatedOlderAboutYounger = _idRelatedLeft;
                _idRelatedYoungerAboutOlder = _idRelatedRight;
            }
            else if ( _drSubjectDetails1.BirthOrderInNls > _drSubjectDetails2.BirthOrderInNls ) {
                _idRelatedOlderAboutYounger = _idRelatedRight;
                _idRelatedYoungerAboutOlder = _idRelatedLeft;
            }

            _dtMarkersGen1 = MarkerGen1.PairRelevantMarkerRows(_idRelatedLeft, _idRelatedRight, _dsLinks, _extendedID);

            LinksDataSet.tblMzManualRow drMz = Retrieve.MzManualRecord(_drLeft.SubjectTag_S1, _drLeft.SubjectTag_S2, _dsLinks);

            if ( drMz == null ) {
                _multipleBirth = MultipleBirth.No;
                _isMZ = Tristate.No;
                _isRelatedInMzManual = Tristate.DoNotKnow;
            }
            else {
                _multipleBirth = (MultipleBirth)drMz.MultipleBirthIfSameSex;
                _isMZ = (Tristate)drMz.IsMz;
                if ( drMz.IsRelatedNull() ) _isRelatedInMzManual = Tristate.DoNotKnow;
                else if ( drMz.Related ) _isRelatedInMzManual = Tristate.Yes;
                else _isRelatedInMzManual = Tristate.No;
            }

            MarkerEvidence explicitBiomomFromOlder = ReduceShareBioparentToOne(MarkerType.ShareBiomom, ItemYears.Gen1ShareBioparent.Length, _idRelatedOlderAboutYounger);
            MarkerEvidence explicitBiodadFromOlder = ReduceShareBioparentToOne(MarkerType.ShareBiodad, ItemYears.Gen1ShareBioparent.Length, _idRelatedOlderAboutYounger);
            MarkerEvidence explicitBiomomFromYounger = ReduceShareBioparentToOne(MarkerType.ShareBiomom, ItemYears.Gen1ShareBioparent.Length, _idRelatedYoungerAboutOlder);
            MarkerEvidence explicitBiodadFromYounger = ReduceShareBioparentToOne(MarkerType.ShareBiodad, ItemYears.Gen1ShareBioparent.Length, _idRelatedYoungerAboutOlder);

            MarkerEvidence biomomInHH1979 = MarkerGen1.RetrieveParentMarkerMultiYear(_idRelatedOlderAboutYounger, MarkerType.Gen1BiomomInHH, 1979, Bioparent.Mom, _dtMarkersGen1);
            MarkerEvidence biodadInHH1979 = MarkerGen1.RetrieveParentMarkerMultiYear(_idRelatedOlderAboutYounger, MarkerType.Gen1BiodadInHH, 1979, Bioparent.Dad, _dtMarkersGen1);

            MarkerEvidence biomomDeathAge = MarkerGen1.RetrieveParentMarkerSingleYear(_idRelatedOlderAboutYounger, MarkerType.Gen1BiomomDeathAge, Bioparent.Mom, _dtMarkersGen1);
            MarkerEvidence biodadDeathAge = MarkerGen1.RetrieveParentMarkerSingleYear(_idRelatedOlderAboutYounger, MarkerType.Gen1BiodadDeathAge, Bioparent.Dad, _dtMarkersGen1);

            _explicitShareBiomomPass1 = CommonFunctions.TranslateEvidenceToTristate(explicitBiomomFromOlder, explicitBiomomFromYounger);
            _explicitShareBiodadPass1 = CommonFunctions.TranslateEvidenceToTristate(explicitBiodadFromOlder, explicitBiodadFromYounger);

            _implicitShareBiomomPass1 = ImplicitShareBioparent(inHH1979: biomomInHH1979, deathAge: biomomDeathAge);
            _implicitShareBiodadPass1 = ImplicitShareBioparent(inHH1979: biodadInHH1979, deathAge: biodadDeathAge);

            _shareBiomomPass1 = CommonFunctions.TakePriority(_explicitShareBiomomPass1, _implicitShareBiomomPass1);
            _shareBiodadPass1 = CommonFunctions.TakePriority(_explicitShareBiodadPass1, _implicitShareBiodadPass1);

            _rExplicitOldestSibVersion = CalculateRExplicitSingleSibVersion(explicitBiomomFromOlder, explicitBiodadFromOlder);
            _rExplicitYoungestSibVersion = CalculateRExplicitSingleSibVersion(explicitBiomomFromYounger, explicitBiodadFromYounger);
            _rExplicitPass1 = CommonFunctions.TranslateToR(shareBiomom: _explicitShareBiomomPass1, shareBiodad: _explicitShareBiodadPass1, mustDecide: false);

            _rImplicitPass1 = CommonFunctions.TranslateToR(shareBiomom: _implicitShareBiomomPass1, shareBiodad: _implicitShareBiodadPass1, mustDecide: false);
            _rImplicit2004 = RetrieveRImplicit2004();

            _rPass1 = CalculateRFull(shareBiomom: _shareBiomomPass1, shareBiodad: _shareBiodadPass1,
                multiple: _multipleBirth, isMZ: _isMZ, isRelatedInMZManual: _isRelatedInMzManual, idRelated: _idRelatedLeft, dtRoster: _dsLinks.tblRosterGen1);
        }
        public RGen2Pass1( ImportDataSet dsImport, LinksDataSet dsLinks, LinksDataSet.tblRelatedStructureRow drLeft, LinksDataSet.tblRelatedStructureRow drRight )
        {
            if ( dsImport == null ) throw new ArgumentNullException("dsImport");
            if ( dsLinks == null ) throw new ArgumentNullException("dsLinks");
            if ( drLeft == null ) throw new ArgumentNullException("drLeft");
            if ( drRight == null ) throw new ArgumentNullException("drRight");
            if ( dsImport.tblLinks2004Gen2.Count == 0 ) throw new InvalidOperationException("tblLinks2004Gen2 must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblMzManual.Count == 0 ) throw new InvalidOperationException("tblMzManual must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblSubject.Count == 0 ) throw new InvalidOperationException("tblSubject must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblSubjectDetails.Count == 0 ) throw new InvalidOperationException("tblSubjectDetails must NOT be empty before assigning R values from it.");
            if ( dsLinks.tblMarkerGen2.Count == 0 ) throw new InvalidOperationException("tblMarkerGen2 must NOT be empty before assigning R values from it.");
            _dsImport = dsImport;
            _dsLinks = dsLinks;
            _drLeft = drLeft;
            _drRight = drRight;
            _idRelatedLeft = _drLeft.ID;
            _idRelatedRight = _drRight.ID;
            _drBare1 = _dsLinks.tblSubject.FindBySubjectTag(drLeft.SubjectTag_S1);
            _drBare2 = _dsLinks.tblSubject.FindBySubjectTag(drLeft.SubjectTag_S2);
            _drSubjectDetails1 = _dsLinks.tblSubjectDetails.FindBySubjectTag(drLeft.SubjectTag_S1);
            _drSubjectDetails2 = _dsLinks.tblSubjectDetails.FindBySubjectTag(drLeft.SubjectTag_S2);
            _extendedID = _drLeft.tblSubjectRowByFK_tblRelatedStructure_tblSubject_Subject1.ExtendedID;

            if ( _drSubjectDetails1.BirthOrderInNls <= _drSubjectDetails2.BirthOrderInNls ) {//This is the way it usually is.  Recall twins were assigned tied birth orders
                _idRelatedOlderAboutYounger = _idRelatedLeft;
                _idRelatedYoungerAboutOlder = _idRelatedRight;
            }
            else if ( _drSubjectDetails1.BirthOrderInNls > _drSubjectDetails2.BirthOrderInNls ) {
                _idRelatedOlderAboutYounger = _idRelatedRight;
                _idRelatedYoungerAboutOlder = _idRelatedLeft;
            }

            _dtMarkersGen2 = MarkerGen2.PairRelevantMarkerRows(_idRelatedLeft, _idRelatedRight, _dsLinks, _extendedID);

            LinksDataSet.tblMzManualRow drMzManual = Retrieve.MzManualRecord(_drBare1, _drBare2, _dsLinks);
            if ( drMzManual == null ) {
                _multipleBirth = MultipleBirth.No;
                _isMZ = Tristate.No;
            }
            else {
                _multipleBirth = (MultipleBirth)drMzManual.MultipleBirthIfSameSex;
                _isMZ = (Tristate)drMzManual.IsMz;
            }
            MarkerEvidence babyDaddyDeathDate = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyDeathDate, _dtMarkersGen2);
            MarkerEvidence babyDaddyAlive = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyAlive, _dtMarkersGen2);
            MarkerEvidence babyDaddyInHH = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyInHH, _dtMarkersGen2);
            MarkerEvidence babyDaddyLeftHHDate = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyLeftHHDate, _dtMarkersGen2);
            MarkerEvidence babyDaddyDistanceFromHH = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyDistanceFromHH, _dtMarkersGen2);
            MarkerEvidence babyDaddyAsthma = MarkerGen2.RetrieveBiodadMarkerFromGen1(_idRelatedOlderAboutYounger, MarkerType.BabyDaddyAsthma, _dtMarkersGen2);

            _rImplicitPass1 = CalculateRImplicitPass1(babyDaddyDeathDate, babyDaddyAlive, babyDaddyInHH, babyDaddyLeftHHDate, babyDaddyDistanceFromHH, babyDaddyAsthma);
            //_rImplicit not set;
            _rImplicit2004 = RetrieveRImplicit2004();
            _rExplicitOldestSibVersion = CalculateRExplicitOldestSibVersion();
            _rExplicitYoungestSibVersion = CalculateRExplicitYoungestSibVersion();
            _rExplicitPass1 = CalculateRExplicitPass1(_isMZ, _multipleBirth);
            //_rExplicit not set;
            _rPass1 = CalculateRPass1();
            //_r not set;
            //_rPeek not set;
        }