public void TestGetFeatureSequence()
 {
     Sequence seq = new Sequence(AlphabetType.DNA, "acgta");
     FeatureList featureList = new FeatureList("test");
     Feature feature = new Feature("feature1", 2, 4, +1);
     featureList.Add(feature);
     seq.AddFeatures(featureList);
     Assert.AreEqual("cgt", feature.Letters());
 }
        public void TestDistanceStartEnd()
        {
            Sequence seq = new Sequence(AlphabetType.DNA, "acgtactg");
            Feature feature1 = new Feature("feature1", 2, 4, +1);
            Feature feature2 = new Feature("feature2", 5, 7, +1);

            feature1.SetSequence(seq);
            feature2.SetSequence(seq);

            Assert.AreEqual(5, feature1.DistanceStartEnd(feature2));
            Assert.AreEqual(7, feature2.DistanceStartEnd(feature1));
        }
        public void TestConstructor()
        {
            Feature feature = new Feature("test", 1, 2, +1);
			Assert.AreEqual("test", feature.Name);

            Sequence seq = new Sequence(AlphabetType.DNA, "acgta");
			seq.Annotations.Add( new Annotation("Name", "test"));
            feature = new Feature(seq, 2, 4, +1);

            Assert.AreEqual("test", feature.Name);
            Assert.AreEqual("cgt", feature.Letters());
        }
		/** Tests the adding of features */
		public void TestAdd () {
			Sequence seq = new Sequence( AlphabetType.DNA, "acgt" );
			FeatureList featureList = new FeatureList( "Test" );
			seq.AddFeatures( featureList );
			Feature feature1 = new Feature( "Test1", 1, 3, +1 );
			Feature feature2 = new Feature( "Test2", 1, 3, +1 );
			featureList.Add( feature1, false );
			featureList.Add( feature2, true );
			Assert.AreEqual( 2, featureList.Count );
			Assert.AreEqual( null, feature1.BaseSequence );
			Assert.AreEqual( seq, feature2.BaseSequence );
		}
		/** Tests the getter of features */
		public void TestFeature () {
			FeatureList featureList = new FeatureList( "Test" );
			Feature feature1 = new Feature( "Test1", 1, 3, +1 );
			Feature feature2 = new Feature( "Test2", 1, 3, +1 );
			featureList.Add( feature1, false );
			featureList.Add( feature2, true );

			var t = featureList[ 0 ];
			bool ans = feature1.Equals( featureList[0] );

			Assert.IsTrue( feature1.Equals( featureList[0] ) );
			Assert.IsTrue( feature2.Equals( featureList[1] ) );
			Assert.IsTrue( feature2.Equals( featureList[-1] ) );
			Assert.IsTrue( feature1.Equals( featureList[2] ) );
			Assert.IsTrue( feature2.Equals( featureList[-3] ) );
			Assert.IsTrue( feature1.Equals( featureList[4] ) );
			Assert.IsTrue( feature1.Equals( featureList["Test1"] ) );
			Assert.IsTrue( feature2.Equals( featureList["Test2"] ) );


		}
        public void TestDistanceDownStream()
        {
			Sequence seq = new Sequence( AlphabetType.DNA, "acgtactgactg", true );

            Feature feature1;
            Feature feature2;

            feature1 = new Feature("feature1", 6, 8, +1);
            feature2 = new Feature("feature2", 2, 3, +1);

            feature1.SetSequence(seq);
            feature2.SetSequence(seq);

            Assert.AreEqual(5, feature1.DistanceDownstream(feature2));
            Assert.AreEqual(2, feature2.DistanceDownstream(feature1));

            //Reverse circular strand
            feature1 = new Feature("feature1", 6, 8, -1);
            feature2 = new Feature("feature2", 2, 3, -1);

            feature1.SetSequence(seq);
            feature2.SetSequence(seq);

            Assert.AreEqual(5, feature2.DistanceDownstream(feature1));
            Assert.AreEqual(2, feature1.DistanceDownstream(feature2));

            //Circular mixed strand
            feature1 = new Feature("feature1", 6, 8, +1);
            feature2 = new Feature("feature2", 2, 3, -1);

            feature1.SetSequence(seq);
            feature2.SetSequence(seq);

            Assert.AreEqual(5, feature2.DistanceDownstream(feature1));
            Assert.AreEqual(5, feature1.DistanceDownstream(feature2));

            seq = new Sequence(AlphabetType.DNA, "acgtactgactg", false);
            //linear strand
            feature1 = new Feature("feature1", 6, 8, +1);
            feature2 = new Feature("feature2", 2, 3, +1);

            feature1.SetSequence(seq);
            feature2.SetSequence(seq);

            Assert.AreEqual(4, feature1.DistanceDownstream(feature2));
            Assert.AreEqual(2, feature2.DistanceDownstream(feature1));

            //Linear mixed strand
            feature1 = new Feature("feature1", 6, 8, +1);
            feature2 = new Feature("feature2", 2, 3, -1);

            feature1.SetSequence(seq);
            feature2.SetSequence(seq);

            Assert.AreEqual(4, feature1.DistanceDownstream(feature2));
            Assert.AreEqual(1, feature2.DistanceDownstream(feature1));
        }
        public void TestIsInside()
        {
            Sequence seq = new Sequence(AlphabetType.DNA, "acgtgat");
            Feature feature1 = new Feature("feature1", 2, 4, +1);
            feature1.SetSequence(seq);

            Assert.AreEqual(true, feature1.IsInside(seq, 2));
            Assert.AreEqual(false, feature1.IsInside(seq, 1));
            Assert.AreEqual(true, feature1.IsInside(seq, 4));
            Assert.AreEqual(false, feature1.IsInside(seq, 5));

            Sequence sub1 = new Sequence(seq, 2, 4, +1);
            Assert.AreEqual(true, feature1.IsInside(sub1, 1));
            Assert.AreEqual(false, feature1.IsInside(sub1, 0));
            Assert.AreEqual(true, feature1.IsInside(sub1, 3));
            Assert.AreEqual(false, feature1.IsInside(sub1, 4));

            Sequence sub2 = new Sequence(sub1, 1, 3, +1);
            Assert.AreEqual(true, feature1.IsInside(sub2, 1));
            Assert.AreEqual(false, feature1.IsInside(sub2, 0));
            Assert.AreEqual(true, feature1.IsInside(sub2, 3));
            Assert.AreEqual(false, feature1.IsInside(sub2, 4));

            sub2 = new Sequence(sub1, 1, 3, -1);
            Assert.AreEqual(true, feature1.IsInside(sub2, 1));
            Assert.AreEqual(false, feature1.IsInside(sub2, 0));
            Assert.AreEqual(true, feature1.IsInside(sub2, 3));
            Assert.AreEqual(false, feature1.IsInside(sub2, 4));

            sub1 = new Sequence(seq, 2, 4, -1);
            Assert.AreEqual(true, feature1.IsInside(sub1, 1));
            Assert.AreEqual(false, feature1.IsInside(sub1, 0));
            Assert.AreEqual(true, feature1.IsInside(sub1, 3));
            Assert.AreEqual(false, feature1.IsInside(sub1, 4));

            sub2 = new Sequence(sub1, 1, 3, +1);
            Assert.AreEqual(true, feature1.IsInside(sub2, 1));
            Assert.AreEqual(false, feature1.IsInside(sub2, 0));
            Assert.AreEqual(true, feature1.IsInside(sub2, 3));
            Assert.AreEqual(false, feature1.IsInside(sub2, 4));

            sub2 = new Sequence(sub1, 1, 3, -1);
            Assert.AreEqual(true, feature1.IsInside(sub2, 1));
            Assert.AreEqual(false, feature1.IsInside(sub2, 0));
            Assert.AreEqual(true, feature1.IsInside(sub2, 3));
            Assert.AreEqual(false, feature1.IsInside(sub2, 4));
        }
        public void TestIsOverlaaping()
        {
            Feature feature1 = new Feature("feature", 10, 14, +1);

            Assert.AreEqual(true, feature1.IsOverlapping(new Feature("f", 10,14, +1)));
            Assert.AreEqual(true, feature1.IsOverlapping(new Feature("f", 10, 14, -1)));
            Assert.AreEqual(true, feature1.IsOverlapping(new Feature("f", 7, 11, -1)));

            Assert.AreEqual(true, feature1.IsOverlapping(new Feature("f", 12, 16, -1)));
            Assert.AreEqual(false, feature1.IsOverlapping(new Feature("f", 5, 9, +1)));
            Assert.AreEqual(true, feature1.IsOverlapping(new Feature("f", 5, 19, +1)));

            Assert.AreEqual(false, feature1.IsOverlapping(new Feature("f", 15, 19, +1)));
            Assert.AreEqual(true, feature1.IsOverlapping(new Feature("f", 14, 18, +1)));
        }
		/** Tests the search for a feature which covers a given position */
		public void TestInside () {
			Sequence seq = new Sequence( AlphabetType.DNA, "acgtactgactg" );
			FeatureList featureList = new FeatureList( "Test" );
			Feature feature1 = new Feature( "Test1", 2, 4, +1 );
			Feature feature2 = new Feature( "Test2", 7, 10, +1 );
			featureList.Add( feature1 );
			featureList.Add( feature2 );
			featureList.AttachSequence( seq );
			Assert.AreEqual( feature1, featureList.Inside( seq, 2 ) );
			Assert.AreEqual( feature1, featureList.Inside( seq, 4 ) );
			Assert.AreEqual( null, featureList.Inside( seq, 1 ) );
			Assert.AreEqual( null, featureList.Inside( seq, 5 ) );
			Assert.AreEqual( feature2, featureList.Inside( seq, 7 ) );
			Assert.AreEqual( feature2, featureList.Inside( seq, 10 ) );
			Assert.AreEqual( null, featureList.Inside( seq, 6 ) );
			Assert.AreEqual( null, featureList.Inside( seq, 11 ) );
		}
        /// <summary>
        ///  Calculates the upstream distance to the given feature. Attention:  The
        ///  calculated distance can be negative if the features are overlapping. 
        ///  The method takes into account circular sequences and features 
        ///  on both strands.
        /// </summary>
        /// <param name="feature">
        ///  Feature the upstream distance is calculated to. If the
        ///  feature is not in the upstream region to the end of the sequnce but the
        ///  sequence is circular, the distance is calculated accross the sequence 
        ///  boundary. For linear sequences the distance to the corresponding sequence 
        ///  terminus is calculated. 
        /// </param>
        /// <returns></returns>
        public int DistanceUpstream(Feature feature)
        {
            int dist = (Strand > 0 ? Start - feature.End : feature.Start - End) - 1;

            if ((feature.Start - Start) * Strand > 0)
            {
                if (BaseSequence.IsCircular())
                    dist = BaseSequence.Length + dist;

                else
                    dist = Strand > 0 ? Start - 1 : BaseSequence.Length - End;
            }

            return dist;

        }
        /// <summary>
        /// Calculates the downstream distance to the given feature. Attention:  The
        /// calculated distance can be negative if the features are overlapping. 
        /// The method takes into account circular sequences and features 
        /// on both strands.
        /// </summary>
        /// <param name="feature">
        /// Feature the downstream distance is calculated to. If the
        /// feature is not in the downstream region to the end of the sequnce but the
        /// sequence is circular, the distance is calculated accross the sequence 
        /// boundary. For linear sequences the distance to the corresponding sequence 
        /// terminus is calculated. 
        /// </param>
        /// <returns>
        /// Returns the downstream distance to the given feature.
        /// </returns>
        public int DistanceDownstream(Feature feature)
        {
            int dist = (Strand > 0 ? feature.Start - End : Start - feature.End) - 1;

            if ((End - feature.End) * Strand > 0)
            {
                if (BaseSequence.IsCircular())
                    dist = BaseSequence.Length + dist;

                else
                    dist = Strand > 0 ? BaseSequence.Length - End : Start - 1;
            }

            return dist;
        }
        /// <summary>
        /// Determines if the region of the current feature overlaps with the region
        /// of the given feature.
        /// </summary>
        /// <param name="feature"> A feature. </param>
        /// <returns>
        /// True, if the regions of the features are overlapping. False,
        /// otherwise.
        /// </returns>
        public bool IsOverlapping(Feature feature)
        {
            if (feature.End >= this.Start
                        && feature.End <= this.End)
                return true;

            if (feature.Start >= this.Start
                        && feature.Start <= this.End)
                return true;

            if (feature.Start <= this.Start
                        && feature.End >= this.End)
                return true;


            return false;
        }
        /// <summary>
        /// Calculates the distance between the end position of the current feature
        /// and the start position of the second feature. If the  second feature has a 
        /// smaller start position than the current feature it is assumed 
        /// that the sequence is cyclic and the distance is calculated the other way
        /// around. Therefore the distance is always positive. 
        /// Note that the feature MUST be attached to a sequence! Otherwise a null
        /// pointer exception will occur.
        /// </summary>
        /// <param name="feature"> Second feature. </param>
        /// <returns> Returns the distance between the two features (feature.start -
        /// this.end if feature.start >= this.end). 
        /// </returns>
        public int DistanceEndStart(Feature feature)
        {
            if (feature.Start < this.End)
                return (this.BaseSequence.Length - this.End + feature.Start);

            return (feature.Start - this.End);
        }
        /// <summary>
        ///  Calculates the distance between the start position of the current feature
        ///  and the end position of the second feature. If the  second feature has a 
        ///  smaller end position than the current feature it is assumed 
        ///  that the sequence is cyclic and the distance is calculated the other way
        ///  around. Therefore the distance is always positive. 
        ///  Note that the feature MUST be attached to a sequence! Otherwise a null
        ///  pointer exception will occur.
        /// </summary>
        /// <param name="feature"> Second feature. </param>
        /// <returns>
        /// Returns the distance between the two features (feature.end -
        /// this.start if feature.end >= this.start).
        /// </returns>
        public int DistanceStartEnd(Feature feature)
        {
            if (feature.End < this.Start)
                return (this.BaseSequence.Length - this.Start + feature.End);

            return (feature.End - this.Start);
        }
        /// <summary>
        /// Calculates the distance between the end positions of two features. If the 
        /// second feature has a smaller position than the current feature it is assumed
        /// that the sequence is cyclic and the distance is calculated the other way
        /// around. Therefore the distance is always positive. 
        /// Note that the feature MUST be attached to a sequence! Otherwise a null
        /// pointer exception will occur.
        /// </summary>
        /// <param name="feature"> Second feature. </param>
        /// <returns>
        /// Returns the distance between the two features (feature.end -
        /// this.end if feature.end >= this.end).
        /// </returns>
        public int DistanceEndEnd(Feature feature)
        {
            if (feature.End < this.End)
                return (this.BaseSequence.Length - this.End + feature.End);

            return (feature.End - this.End);
        }
        /// <summary>
        /// Calculates the distance between the start positions of two features. If the 
        /// second feature has a smaller position than the current feature it is assumed 
        /// that the sequence is cyclic and the distance is calculated the other way
        /// around. Therefore the distance is always positive. 
        /// Note that the feature MUST be attached to a sequence! Otherwise a null
        /// pointer exception will occur.
        /// </summary>
        /// <param name="feature"> Second feature. </param>
        /// <returns> 
        /// Returns the distance between the two features (feature.start -
        /// this.start if feature.start >= this.start).
        /// </returns>
        public int DistanceStartStart(Feature feature)
        {
            if (feature.Start < this.Start)
                return (base.Length - this.Start + feature.Start);

            return (feature.Start - this.Start);
        }