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? _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);
        }