Beispiel #1
0
        private static FeatureStruct GetFeatureStruct(FeatureSystem featSys, IFsFeatStruc fs)
        {
            var featStruct = new FeatureStruct();

            foreach (IFsFeatureSpecification featSpec in fs.FeatureSpecsOC)
            {
                var complexVal = featSpec as IFsComplexValue;
                if (complexVal != null)
                {
                    var cfs = complexVal.ValueOA as IFsFeatStruc;
                    if (complexVal.FeatureRA != null && cfs != null && !cfs.IsEmpty)
                    {
                        featStruct.AddValue(featSys.GetFeature(complexVal.FeatureRA.Hvo.ToString(CultureInfo.InvariantCulture)), GetFeatureStruct(featSys, cfs));
                    }
                }
                else
                {
                    var closedVal = featSpec as IFsClosedValue;
                    if (closedVal != null && closedVal.FeatureRA != null)
                    {
                        var           symFeat = featSys.GetFeature <SymbolicFeature>(closedVal.FeatureRA.Hvo.ToString(CultureInfo.InvariantCulture));
                        FeatureSymbol symbol;
                        if (symFeat.PossibleSymbols.TryGetValue(closedVal.ValueRA.Hvo.ToString(CultureInfo.InvariantCulture), out symbol))
                        {
                            featStruct.AddValue(symFeat, symbol);
                        }
                    }
                }
            }
            return(featStruct);
        }
		public override PatternNode<ComplexConcParagraphData, ShapeNode> GeneratePattern(FeatureSystem featSys)
		{
			var fs = new FeatureStruct();
			var typeFeat = featSys.GetFeature<SymbolicFeature>("type");
			fs.AddValue(typeFeat, typeFeat.PossibleSymbols["word"]);
			AddStringValue(featSys, fs, Form, "form");
			AddStringValue(featSys, fs, Gloss, "gloss");
			if (Category != null)
			{
				var catFeat = featSys.GetFeature<SymbolicFeature>("cat");
				IEnumerable<FeatureSymbol> symbols = Category.ReallyReallyAllPossibilities.Concat(Category).Select(pos => catFeat.PossibleSymbols[pos.Hvo.ToString(CultureInfo.InvariantCulture)]);
				if (NegateCategory)
					symbols = catFeat.PossibleSymbols.Except(symbols);
				fs.AddValue(catFeat, symbols);
			}
			if (m_inflFeatures.Count > 0)
			{
				var inflFeat = featSys.GetFeature<ComplexFeature>("infl");
				fs.AddValue(inflFeat, GetFeatureStruct(featSys, m_inflFeatures));
			}

			var wordBdryFS = FeatureStruct.New(featSys).Symbol("bdry").Symbol("wordBdry").Value;
			var group = new Group<ComplexConcParagraphData, ShapeNode>();
			group.Children.Add(new Quantifier<ComplexConcParagraphData, ShapeNode>(0, 1, new Constraint<ComplexConcParagraphData, ShapeNode>(wordBdryFS)) {IsGreedy = false});
			group.Children.Add(new Constraint<ComplexConcParagraphData, ShapeNode>(fs));
			group.Children.Add(new Quantifier<ComplexConcParagraphData, ShapeNode>(0, 1, new Constraint<ComplexConcParagraphData, ShapeNode>(wordBdryFS)) {IsGreedy = false});

			return AddQuantifier(group);
		}
Beispiel #3
0
        public override PatternNode <ComplexConcParagraphData, ShapeNode> GeneratePattern(FeatureSystem featSys)
        {
            var fs       = new FeatureStruct();
            var typeFeat = featSys.GetFeature <SymbolicFeature>("type");

            fs.AddValue(typeFeat, typeFeat.PossibleSymbols["morph"]);
            AddStringValue(featSys, fs, Form, "form");
            AddStringValue(featSys, fs, Gloss, "gloss");
            AddStringValue(featSys, fs, Entry, "entry");
            if (Category != null)
            {
                var catFeat = featSys.GetFeature <SymbolicFeature>("cat");
                IEnumerable <FeatureSymbol> symbols = Category.ReallyReallyAllPossibilities.Concat(Category).Select(pos => catFeat.PossibleSymbols[pos.Hvo.ToString(CultureInfo.InvariantCulture)]);
                if (NegateCategory)
                {
                    symbols = catFeat.PossibleSymbols.Except(symbols);
                }
                fs.AddValue(catFeat, symbols);
            }
            if (m_inflFeatures.Count > 0)
            {
                var inflFeat = featSys.GetFeature <ComplexFeature>("infl");
                fs.AddValue(inflFeat, GetFeatureStruct(featSys, m_inflFeatures));
            }

            return(AddQuantifier(new Constraint <ComplexConcParagraphData, ShapeNode>(fs)));
        }
		public override PatternNode<ComplexConcParagraphData, ShapeNode> GeneratePattern(FeatureSystem featSys)
		{
			var fs = new FeatureStruct();
			var typeFeat = featSys.GetFeature<SymbolicFeature>("type");
			fs.AddValue(typeFeat, typeFeat.PossibleSymbols["ttag"]);

			if (Tag != null)
			{
				var tagFeat = featSys.GetFeature<SymbolicFeature>("tag");
				fs.AddValue(tagFeat, tagFeat.PossibleSymbols[Tag.Hvo.ToString(CultureInfo.InvariantCulture)]);
			}

			return AddQuantifier(new Constraint<ComplexConcParagraphData, ShapeNode>(fs));
		}
Beispiel #5
0
        public override PatternNode <ComplexConcParagraphData, ShapeNode> GeneratePattern(FeatureSystem featSys)
        {
            var fs       = new FeatureStruct();
            var typeFeat = featSys.GetFeature <SymbolicFeature>("type");

            fs.AddValue(typeFeat, typeFeat.PossibleSymbols["ttag"]);

            if (Tag != null)
            {
                var tagFeat = featSys.GetFeature <SymbolicFeature>("tag");
                fs.AddValue(tagFeat, tagFeat.PossibleSymbols[Tag.Hvo.ToString(CultureInfo.InvariantCulture)]);
            }

            return(AddQuantifier(new Constraint <ComplexConcParagraphData, ShapeNode>(fs)));
        }
Beispiel #6
0
        public void AlineFeatures()
        {
            var manner = _featSys.GetFeature <SymbolicFeature>("manner");
            var aline  = new Aline(_segmentPool, Enumerable.Empty <SymbolicFeature>(), manner.ToEnumerable(),
                                   new Dictionary <SymbolicFeature, int> {
                { manner, 50 }
            },
                                   new Dictionary <FeatureSymbol, int>
            {
                { manner.PossibleSymbols["stop"], 100 },
                { manner.PossibleSymbols["affricate"], 95 },
                { manner.PossibleSymbols["fricative"], 90 },
                { manner.PossibleSymbols["approximant"], 80 }
            });

            _project.WordAligners["primary"] = aline;
            var pm = new ProjectMigration2();

            pm.Migrate(_segmentPool, _project);

            aline = (Aline)_project.WordAligners["primary"];
            Assert.That(aline.RelevantConsonantFeatures.Select(f => f.ID), Is.EquivalentTo(new[] { "manner", "airstream" }));
            Assert.That(aline.FeatureWeights.Select(kvp => Tuple.Create(kvp.Key.ID, kvp.Value)), Is.EquivalentTo(new[] { Tuple.Create("manner", 50), Tuple.Create("airstream", 5) }));
            Assert.That(aline.ValueMetrics.Select(kvp => Tuple.Create(kvp.Key.ID, kvp.Value)), Is.EquivalentTo(new[]
            {
                Tuple.Create("stop", 100),
                Tuple.Create("affricate", 95),
                Tuple.Create("fricative", 90),
                Tuple.Create("approximant", 80),
                Tuple.Create("pulmonic", 100),
                Tuple.Create("ejective", 66),
                Tuple.Create("implosive", 33),
                Tuple.Create("click", 0)
            }));
        }
Beispiel #7
0
        private AlineScorer CreateScorer(bool soundChangeScoringEnabled, bool syllablePositionCostEnabled)
        {
            return(new AlineScorer(_segmentPool, new[] { _featSys.GetFeature <SymbolicFeature>("height"), _featSys.GetFeature <SymbolicFeature>("backness"), _featSys.GetFeature <SymbolicFeature>("round") },
                                   new[] { _featSys.GetFeature <SymbolicFeature>("place"), _featSys.GetFeature <SymbolicFeature>("manner"), _featSys.GetFeature <SymbolicFeature>("voice") },
                                   new Dictionary <SymbolicFeature, int>
            {
                { _featSys.GetFeature <SymbolicFeature>("height"), 10 },
                { _featSys.GetFeature <SymbolicFeature>("backness"), 10 },
                { _featSys.GetFeature <SymbolicFeature>("round"), 2 },
                { _featSys.GetFeature <SymbolicFeature>("place"), 40 },
                { _featSys.GetFeature <SymbolicFeature>("manner"), 50 },
                { _featSys.GetFeature <SymbolicFeature>("voice"), 5 }
            }, new Dictionary <FeatureSymbol, int>
            {
                { _featSys.GetSymbol("bilabial"), 100 },
                { _featSys.GetSymbol("labiodental"), 90 },
                { _featSys.GetSymbol("dental"), 80 },
                { _featSys.GetSymbol("alveolar"), 70 },
                { _featSys.GetSymbol("retroflex"), 60 },
                { _featSys.GetSymbol("palato-alveolar"), 50 },
                { _featSys.GetSymbol("palatal"), 40 },
                { _featSys.GetSymbol("velar"), 30 },
                { _featSys.GetSymbol("uvular"), 20 },
                { _featSys.GetSymbol("pharyngeal"), 10 },
                { _featSys.GetSymbol("glottal"), 0 },

                { _featSys.GetSymbol("stop"), 100 },
                { _featSys.GetSymbol("affricate"), 95 },
                { _featSys.GetSymbol("fricative"), 90 },
                { _featSys.GetSymbol("approximant"), 80 },
                { _featSys.GetSymbol("trill"), 60 },
                { _featSys.GetSymbol("flap"), 50 },
                { _featSys.GetSymbol("close-vowel"), 30 },
                { _featSys.GetSymbol("mid-vowel"), 15 },
                { _featSys.GetSymbol("open-vowel"), 0 },

                { _featSys.GetSymbol("voice+"), 100 },
                { _featSys.GetSymbol("voice-"), 0 },

                { _featSys.GetSymbol("close"), 100 },
                { _featSys.GetSymbol("near-close"), 85 },
                { _featSys.GetSymbol("close-mid"), 65 },
                { _featSys.GetSymbol("mid"), 50 },
                { _featSys.GetSymbol("open-mid"), 35 },
                { _featSys.GetSymbol("near-open"), 15 },
                { _featSys.GetSymbol("open"), 0 },

                { _featSys.GetSymbol("front"), 100 },
                { _featSys.GetSymbol("near-front"), 80 },
                { _featSys.GetSymbol("central"), 50 },
                { _featSys.GetSymbol("near-back"), 20 },
                { _featSys.GetSymbol("back"), 0 },

                { _featSys.GetSymbol("round+"), 100 },
                { _featSys.GetSymbol("round-"), 0 }
            }, Enumerable.Empty <SoundClass>(), soundChangeScoringEnabled, syllablePositionCostEnabled));
        }
Beispiel #8
0
 protected void AddStringValue(FeatureSystem featSys, FeatureStruct fs, ITsString tss, string id)
 {
     if (tss != null)
     {
         var feat = featSys.GetFeature <StringFeature>(string.Format("{0}-{1}", id, tss.get_WritingSystemAt(0).ToString(CultureInfo.InvariantCulture)));
         fs.AddValue(feat, tss.Text);
     }
 }
 IFeatureValueSyntax IFeatureStructSyntax.Feature(string featureID)
 {
     if (_featSys == null)
     {
         throw new NotSupportedException("A feature system must be specified.");
     }
     _lastFeature = _featSys.GetFeature(featureID);
     return(this);
 }
Beispiel #10
0
        private static FeatureStruct LoadFeatureStruct(FeatureSystem featSys, XElement elem)
        {
            var fs = new FeatureStruct();

            foreach (XElement featureValueElem in elem.Elements(Cog + "FeatureValue"))
            {
                var feature = (SymbolicFeature)featSys.GetFeature((string)featureValueElem.Attribute("feature"));
                fs.AddValue(feature, ((string)featureValueElem.Attribute("value")).Split(' ').Select(featSys.GetSymbol));
            }
            return(fs);
        }
        public override PatternNode <ComplexConcParagraphData, ShapeNode> GeneratePattern(FeatureSystem featSys)
        {
            var fs       = new FeatureStruct();
            var typeFeat = featSys.GetFeature <SymbolicFeature>("type");

            fs.AddValue(typeFeat, typeFeat.PossibleSymbols["word"]);
            AddStringValue(featSys, fs, Form, "form");
            AddStringValue(featSys, fs, Gloss, "gloss");
            if (Category != null)
            {
                var catFeat = featSys.GetFeature <SymbolicFeature>("cat");
                IEnumerable <FeatureSymbol> symbols = Category.ReallyReallyAllPossibilities.Concat(Category).Select(pos => catFeat.PossibleSymbols[pos.Hvo.ToString(CultureInfo.InvariantCulture)]);
                if (NegateCategory)
                {
                    symbols = catFeat.PossibleSymbols.Except(symbols);
                }
                fs.AddValue(catFeat, symbols);
            }
            if (m_inflFeatures.Count > 0)
            {
                var inflFeat = featSys.GetFeature <ComplexFeature>("infl");
                fs.AddValue(inflFeat, GetFeatureStruct(featSys, m_inflFeatures));
            }

            var wordBdryFS = FeatureStruct.New(featSys).Symbol("bdry").Symbol("wordBdry").Value;
            var group      = new Group <ComplexConcParagraphData, ShapeNode>();

            group.Children.Add(new Quantifier <ComplexConcParagraphData, ShapeNode>(0, 1, new Constraint <ComplexConcParagraphData, ShapeNode>(wordBdryFS))
            {
                IsGreedy = false
            });
            group.Children.Add(new Constraint <ComplexConcParagraphData, ShapeNode>(fs));
            group.Children.Add(new Quantifier <ComplexConcParagraphData, ShapeNode>(0, 1, new Constraint <ComplexConcParagraphData, ShapeNode>(wordBdryFS))
            {
                IsGreedy = false
            });

            return(AddQuantifier(group));
        }
Beispiel #12
0
        protected FeatureStruct GetFeatureStruct(FeatureSystem featSys, IDictionary <IFsFeatDefn, object> values)
        {
            var fs = new FeatureStruct();

            foreach (KeyValuePair <IFsFeatDefn, object> kvp in values)
            {
                if (kvp.Key is IFsComplexFeature)
                {
                    var childValues = (IDictionary <IFsFeatDefn, object>)kvp.Value;
                    fs.AddValue(featSys.GetFeature(kvp.Key.Hvo.ToString(CultureInfo.InvariantCulture)), GetFeatureStruct(featSys, childValues));
                }
                else if (kvp.Key is IFsClosedFeature)
                {
                    var value   = (ClosedFeatureValue)kvp.Value;
                    var symFeat = featSys.GetFeature <SymbolicFeature>(kvp.Key.Hvo.ToString(CultureInfo.InvariantCulture));

                    FeatureSymbol symbol = symFeat.PossibleSymbols[value.Symbol.Hvo.ToString(CultureInfo.InvariantCulture)];
                    fs.AddValue(symFeat, value.Negate ? new SymbolicFeatureValue(symFeat.PossibleSymbols.Except(symbol.ToEnumerable())) : new SymbolicFeatureValue(symbol));
                }
            }

            return(fs);
        }
		public override PatternNode<ComplexConcParagraphData, ShapeNode> GeneratePattern(FeatureSystem featSys)
		{
			var fs = new FeatureStruct();
			var typeFeat = featSys.GetFeature<SymbolicFeature>("type");
			fs.AddValue(typeFeat, typeFeat.PossibleSymbols["morph"]);
			AddStringValue(featSys, fs, Form, "form");
			AddStringValue(featSys, fs, Gloss, "gloss");
			AddStringValue(featSys, fs, Entry, "entry");
			if (Category != null)
			{
				var catFeat = featSys.GetFeature<SymbolicFeature>("cat");
				IEnumerable<FeatureSymbol> symbols = Category.ReallyReallyAllPossibilities.Concat(Category).Select(pos => catFeat.PossibleSymbols[pos.Hvo.ToString(CultureInfo.InvariantCulture)]);
				if (NegateCategory)
					symbols = catFeat.PossibleSymbols.Except(symbols);
				fs.AddValue(catFeat, symbols);
			}
			if (m_inflFeatures.Count > 0)
			{
				var inflFeat = featSys.GetFeature<ComplexFeature>("infl");
				fs.AddValue(inflFeat, GetFeatureStruct(featSys, m_inflFeatures));
			}

			return AddQuantifier(new Constraint<ComplexConcParagraphData, ShapeNode>(fs));
		}
Beispiel #14
0
        private bool GenerateShape(SpanFactory <ShapeNode> spanFactory, FeatureSystem featSys)
        {
            m_shape.Add(FeatureStruct.New(featSys).Symbol("bdry").Symbol("wordBdry").Value);
            var typeFeat = featSys.GetFeature <SymbolicFeature>("type");
            var catFeat  = featSys.GetFeature <SymbolicFeature>("cat");
            var inflFeat = featSys.GetFeature <ComplexFeature>("infl");
            var segments = new Dictionary <ISegment, List <Annotation <ShapeNode> > >();

            foreach (ISegment segment in m_para.SegmentsOS)
            {
                var annotations = new List <Annotation <ShapeNode> >();
                foreach (Tuple <IAnalysis, int, int> analysis in segment.GetAnalysesAndOffsets())
                {
                    // check if analyses are out-of-sync with the baseline
                    ITsString baselineStr = m_para.Contents.GetSubstring(analysis.Item2, analysis.Item3);
                    ITsString formStr     = analysis.Item1.GetForm(baselineStr.get_WritingSystemAt(0));
                    if (!baselineStr.Text.Equals(formStr.Text, StringComparison.InvariantCultureIgnoreCase))
                    {
                        return(false);
                    }

                    var wordform = analysis.Item1 as IWfiWordform;
                    if (wordform != null)
                    {
                        var wordFS = new FeatureStruct();
                        wordFS.AddValue(typeFeat, typeFeat.PossibleSymbols["word"]);
                        foreach (int ws in wordform.Form.AvailableWritingSystemIds)
                        {
                            StringFeature strFeat;
                            if (featSys.TryGetFeature(string.Format("form-{0}", ws), out strFeat))
                            {
                                wordFS.AddValue(strFeat, wordform.Form.get_String(ws).Text);
                            }
                        }
                        ShapeNode node = m_shape.Add(wordFS);
                        node.Annotation.Data = analysis;
                        annotations.Add(node.Annotation);
                    }
                    else
                    {
                        if (analysis.Item1 is IPunctuationForm)
                        {
                            annotations.Add(null);
                            continue;
                        }

                        FeatureStruct wordInflFS    = null;
                        IWfiAnalysis  wanalysis     = analysis.Item1.Analysis;
                        ShapeNode     analysisStart = null;
                        foreach (IWfiMorphBundle mb in wanalysis.MorphBundlesOS)
                        {
                            var morphFS = new FeatureStruct();
                            morphFS.AddValue(typeFeat, typeFeat.PossibleSymbols["morph"]);
                            foreach (int ws in mb.Form.AvailableWritingSystemIds.Union(mb.MorphRA == null ? Enumerable.Empty <int>() : mb.MorphRA.Form.AvailableWritingSystemIds))
                            {
                                StringFeature strFeat;
                                if (!featSys.TryGetFeature(string.Format("form-{0}", ws), out strFeat))
                                {
                                    continue;
                                }

                                IEnumerable <string> forms  = Enumerable.Empty <string>();
                                ITsString            mbForm = mb.Form.StringOrNull(ws);
                                if (mbForm != null)
                                {
                                    forms = forms.Concat(mbForm.Text);
                                }
                                if (mb.MorphRA != null)
                                {
                                    ITsString morphForm = mb.MorphRA.Form.StringOrNull(ws);
                                    if (morphForm != null)
                                    {
                                        forms = forms.Concat(morphForm.Text);
                                    }
                                }

                                morphFS.AddValue(strFeat, forms.Distinct());
                            }
                            if (mb.SenseRA != null)
                            {
                                foreach (int ws in mb.SenseRA.Gloss.AvailableWritingSystemIds)
                                {
                                    StringFeature strFeat;
                                    if (featSys.TryGetFeature(string.Format("gloss-{0}", ws), out strFeat))
                                    {
                                        morphFS.AddValue(strFeat, mb.SenseRA.Gloss.get_String(ws).Text);
                                    }
                                }
                            }

                            if (mb.MorphRA != null)
                            {
                                var entry = (ILexEntry)mb.MorphRA.Owner;
                                foreach (int ws in entry.LexemeFormOA.Form.AvailableWritingSystemIds)
                                {
                                    StringFeature strFeat;
                                    if (featSys.TryGetFeature(string.Format("entry-{0}", ws), out strFeat))
                                    {
                                        morphFS.AddValue(strFeat, entry.LexemeFormOA.Form.get_String(ws).Text);
                                    }
                                }
                            }

                            if (mb.MsaRA != null && mb.MsaRA.ComponentsRS != null)
                            {
                                FeatureSymbol[] catSymbols = GetHvoOfMsaPartOfSpeech(mb.MsaRA).Select(hvo => catFeat.PossibleSymbols[hvo.ToString(CultureInfo.InvariantCulture)]).ToArray();
                                if (catSymbols.Length > 0)
                                {
                                    morphFS.AddValue(catFeat, catSymbols);
                                }
                                var inflFS = GetFeatureStruct(featSys, mb.MsaRA);
                                if (inflFS != null)
                                {
                                    morphFS.AddValue(inflFeat, inflFS);
                                    if (wordInflFS == null)
                                    {
                                        wordInflFS = inflFS.DeepClone();
                                    }
                                    else
                                    {
                                        wordInflFS.Union(inflFS);
                                    }
                                }
                            }

                            ShapeNode node = m_shape.Add(morphFS);
                            if (analysisStart == null)
                            {
                                analysisStart = node;
                            }
                        }

                        var wordFS = new FeatureStruct();
                        wordFS.AddValue(typeFeat, typeFeat.PossibleSymbols["word"]);
                        if (wanalysis.CategoryRA != null)
                        {
                            wordFS.AddValue(catFeat, catFeat.PossibleSymbols[wanalysis.CategoryRA.Hvo.ToString(CultureInfo.InvariantCulture)]);
                        }
                        if (wordInflFS != null && !wordInflFS.IsEmpty)
                        {
                            wordFS.AddValue(inflFeat, wordInflFS);
                        }
                        wordform = wanalysis.Wordform;
                        foreach (int ws in wordform.Form.AvailableWritingSystemIds)
                        {
                            StringFeature strFeat;
                            if (featSys.TryGetFeature(string.Format("form-{0}", ws), out strFeat))
                            {
                                wordFS.AddValue(strFeat, wordform.Form.get_String(ws).Text);
                            }
                        }
                        var gloss = analysis.Item1 as IWfiGloss;
                        if (gloss != null)
                        {
                            foreach (int ws in gloss.Form.AvailableWritingSystemIds)
                            {
                                StringFeature strFeat;
                                if (featSys.TryGetFeature(string.Format("gloss-{0}", ws), out strFeat))
                                {
                                    wordFS.AddValue(strFeat, gloss.Form.get_String(ws).Text);
                                }
                            }
                        }
                        Annotation <ShapeNode> ann;
                        if (analysisStart != null)
                        {
                            ann = m_shape.Annotations.Add(analysisStart, m_shape.Last, wordFS);
                            m_shape.Add(FeatureStruct.New(featSys).Symbol("bdry").Symbol("wordBdry").Value);
                        }
                        else
                        {
                            ShapeNode node = m_shape.Add(wordFS);
                            ann = node.Annotation;
                        }
                        ann.Data = analysis;
                        annotations.Add(ann);
                    }
                }

                segments[segment] = annotations;
                m_shape.Add(FeatureStruct.New(featSys).Symbol("bdry").Symbol("segBdry").Value);
            }

            foreach (ITextTag tag in m_para.OwnerOfClass <IStText>().TagsOC)
            {
                // skip invalid tags
                // TODO: should these tags be cleaned up somewhere?
                if (tag.BeginAnalysisIndex >= tag.BeginSegmentRA.AnalysesRS.Count || tag.EndAnalysisIndex >= tag.EndSegmentRA.AnalysesRS.Count ||
                    tag.BeginAnalysisIndex > tag.EndAnalysisIndex)
                {
                    continue;
                }
                List <Annotation <ShapeNode> > beginSegment, endSegment;
                if (!segments.TryGetValue(tag.BeginSegmentRA, out beginSegment) || !segments.TryGetValue(tag.EndSegmentRA, out endSegment))
                {
                    continue;
                }
                Annotation <ShapeNode> beginAnnotation = beginSegment[tag.BeginAnalysisIndex];
                Annotation <ShapeNode> endAnnotation   = endSegment[tag.EndAnalysisIndex];
                ICmPossibility         tagType         = tag.TagRA;
                if (tagType == null || beginAnnotation == null || endAnnotation == null)
                {
                    continue;                     // guard against LT-14549 crash
                }
                Annotation <ShapeNode> tagAnn = new Annotation <ShapeNode>(spanFactory.Create(beginAnnotation.Span.Start, endAnnotation.Span.End),
                                                                           FeatureStruct.New(featSys).Symbol("ttag").Symbol(tagType.Hvo.ToString(CultureInfo.InvariantCulture)).Value)
                {
                    Data = tag
                };
                m_shape.Annotations.Add(tagAnn, false);
            }

            return(true);
        }
		protected void AddStringValue(FeatureSystem featSys, FeatureStruct fs, ITsString tss, string id)
		{
			if (tss != null)
			{
				var feat = featSys.GetFeature<StringFeature>(string.Format("{0}-{1}", id, tss.get_WritingSystemAt(0).ToString(CultureInfo.InvariantCulture)));
				fs.AddValue(feat, tss.Text);
			}
		}
		protected FeatureStruct GetFeatureStruct(FeatureSystem featSys, IDictionary<IFsFeatDefn, object> values)
		{
			var fs = new FeatureStruct();
			foreach (KeyValuePair<IFsFeatDefn, object> kvp in values)
			{
				if (kvp.Key is IFsComplexFeature)
				{
					var childValues = (IDictionary<IFsFeatDefn, object>) kvp.Value;
					fs.AddValue(featSys.GetFeature(kvp.Key.Hvo.ToString(CultureInfo.InvariantCulture)), GetFeatureStruct(featSys, childValues));
				}
				else if (kvp.Key is IFsClosedFeature)
				{
					var value = (ClosedFeatureValue) kvp.Value;
					var symFeat = featSys.GetFeature<SymbolicFeature>(kvp.Key.Hvo.ToString(CultureInfo.InvariantCulture));

					FeatureSymbol symbol = symFeat.PossibleSymbols[value.Symbol.Hvo.ToString(CultureInfo.InvariantCulture)];
					fs.AddValue(symFeat, value.Negate ? new SymbolicFeatureValue(symFeat.PossibleSymbols.Except(symbol.ToEnumerable())) : new SymbolicFeatureValue(symbol));
				}
			}

			return fs;
		}