Exemplo n.º 1
0
        /// <summary>
        /// Reads the atom type mappings from the data file.
        /// </summary>
        /// <returns>a <see cref="IReadOnlyDictionary{TKey, TValue}"/> with atom type mappings. <see langword="null"/>, if some reading error occurred.</returns>
        public IReadOnlyDictionary <string, string> ReadAtomTypeMappings()
        {
            IReadOnlyDictionary <string, string> mappings = null;

            var setting = new XmlReaderSettings
            {
                DtdProcessing   = DtdProcessing.Parse,
                ValidationFlags = XmlSchemaValidationFlags.None
            };
            var handler = new OWLAtomTypeMappingHandler();
            var parser  = XmlReader.Create(input, setting);
            var reader  = new XReader
            {
                Handler = handler
            };

            try
            {
                var doc = XDocument.Load(parser);
                reader.Read(doc);
                mappings = handler.GetAtomTypeMappings();
            }
            catch (IOException exception)
            {
                Trace.TraceError(nameof(IOException) + ": " + exception.Message);
                Debug.WriteLine(exception);
            }
            catch (XmlException saxe)
            {
                Trace.TraceError(nameof(XmlException) + ": " + saxe.Message);
                Debug.WriteLine(saxe);
            }
            return(mappings ?? Dictionaries.Empty <string, string>());
        }
Exemplo n.º 2
0
        public bool ContainsPrimaryKeyValue(TPrimaryKey primaryKey, TValue value)
        {
            var secondaryEntry = dictionary.ContainsKey(primaryKey)
                ? dictionary[primaryKey]
                : Dictionaries.Empty <TSecondaryKey, TValue>();

            return(secondaryEntry.Any(entry => Objects.Equal(entry.Value, value)));
        }
Exemplo n.º 3
0
        public ICollection <KeyValuePair <TSecondaryKey, TValue> > PrimaryKeyEntries(TPrimaryKey primaryKey)
        {
            var secondaryDictionary = dictionary.ContainsKey(primaryKey)
                ? dictionary[primaryKey]
                : Dictionaries.Empty <TSecondaryKey, TValue>();

            return(secondaryDictionary.Entries());
        }
        public void ShouldCreateEmptyDictionary()
        {
            // when
            var dictionary = Dictionaries.Empty <string, int>();

            // then
            Check.That(dictionary).IsEmpty();
        }
Exemplo n.º 5
0
        public ICollection <TValue> RemoveByPrimaryKey(TPrimaryKey primaryKey)
        {
            var removed = dictionary.ContainsKey(primaryKey)
                ? dictionary[primaryKey]
                : Dictionaries.Empty <TSecondaryKey, TValue>();

            dictionary.Remove(primaryKey);
            RecalculateSize();
            return(removed.Values);
        }
Exemplo n.º 6
0
        public void ShouldReturnNullObjectIfNotPresentInDictionary()
        {
            // given
            var dictionary = Dictionaries.Empty <string, string>();

            // when
            var value = dictionary.GetIfPresent("not exising");

            // then
            Check.That(value).IsNull();
        }
Exemplo n.º 7
0
        private IRenderingElement GenerateMultipleSgroup(Sgroup sgroup)
        {
            // just draw the brackets - multiplied group parts have already been hidden in prep phase
            var brackets = (IList <SgroupBracket>)sgroup.GetValue(SgroupKey.CtabBracket);

            if (brackets != null)
            {
                return(GenerateSgroupBrackets(sgroup,
                                              brackets,
                                              Dictionaries.Empty <IAtom, AtomSymbol>(),
                                              (string)sgroup.GetValue(SgroupKey.CtabSubScript),
                                              null));
            }
            else
            {
                return(new ElementGroup());
            }
        }
Exemplo n.º 8
0
        private IRenderingElement GenerateSgroupBrackets(Sgroup sgroup,
                                                         IList <SgroupBracket> brackets,
                                                         IReadOnlyDictionary <IAtom, AtomSymbol> symbols,
                                                         string subscriptSuffix,
                                                         string superscriptSuffix)
        {
            // brackets are square by default (style:0)
            var  style  = (int?)sgroup.GetValue(SgroupKey.CtabBracketStyle);
            bool round  = style != null && style == 1;
            var  result = new ElementGroup();

            var atoms         = sgroup.Atoms;
            var crossingBonds = sgroup.Bonds;

            // easy to depict in correct orientation, we just
            // point each bracket at the atom of a crossing
            // bond that is 'in' the group - this scales
            // to more than two brackets

            // first we need to pair the brackets with the bonds
            var pairs = crossingBonds.Count == brackets.Count ? BracketBondPairs(brackets, crossingBonds) : Dictionaries.Empty <SgroupBracket, IBond>();

            // override bracket layout around single atoms to bring them in closer
            if (atoms.Count == 1)
            {
                var atom = atoms.First();

                // e.g. 2 HCL, 8 H2O etc.
                if (IsUnsignedInt(subscriptSuffix) &&
                    !crossingBonds.Any() &&
                    symbols.ContainsKey(atom))
                {
                    var prefix       = new TextOutline('·' + subscriptSuffix, font, emSize).Resize(1 / scale, 1 / -scale);
                    var prefixBounds = prefix.LogicalBounds;

                    var symbol = symbols[atom];

                    var bounds = symbol.GetConvexHull().Outline.Bounds;

                    // make slightly large
                    bounds = new Rect(bounds.Bottom - 2 * stroke,
                                      bounds.Left - 2 * stroke,
                                      bounds.Width + 4 * stroke,
                                      bounds.Height + 4 * stroke);

                    prefix = prefix.Translate(bounds.Bottom - prefixBounds.Top,
                                              symbol.GetAlignmentCenter().Y - prefixBounds.CenterY());

                    result.Add(GeneralPath.ShapeOf(prefix.GetOutline(), foreground));
                }
                // e.g. CC(O)nCC
                else if (crossingBonds.Count > 0)
                {
                    var scriptscale = labelScale;

                    var leftBracket  = new TextOutline("(", font, emSize).Resize(1 / scale, 1 / -scale);
                    var rightBracket = new TextOutline(")", font, emSize).Resize(1 / scale, 1 / -scale);

                    var leftCenter  = leftBracket.GetCenter();
                    var rightCenter = rightBracket.GetCenter();

                    if (symbols.ContainsKey(atom))
                    {
                        var symbol = symbols[atom];

                        var bounds = symbol.GetConvexHull().Outline.Bounds;
                        // make slightly large
                        bounds = new Rect(bounds.Left - 2 * stroke,
                                          bounds.Top - 2 * stroke,
                                          bounds.Width + 4 * stroke,
                                          bounds.Height + 4 * stroke);

                        leftBracket = leftBracket.Translate(bounds.Left - 0.1 - leftCenter.X,
                                                            symbol.GetAlignmentCenter().Y - leftCenter.Y);
                        rightBracket = rightBracket.Translate(bounds.Right + 0.1 - rightCenter.X,
                                                              symbol.GetAlignmentCenter().Y - rightCenter.Y);
                    }
                    else
                    {
                        var p = atoms.First().Point2D.Value;
                        leftBracket  = leftBracket.Translate(p.X - 0.2 - leftCenter.X, p.Y - leftCenter.Y);
                        rightBracket = rightBracket.Translate(p.X + 0.2 - rightCenter.X, p.Y - rightCenter.Y);
                    }

                    result.Add(GeneralPath.ShapeOf(leftBracket.GetOutline(), foreground));
                    result.Add(GeneralPath.ShapeOf(rightBracket.GetOutline(), foreground));

                    var rightBracketBounds = rightBracket.GetBounds();

                    // subscript/superscript suffix annotation
                    if (subscriptSuffix != null && subscriptSuffix.Any())
                    {
                        TextOutline subscriptOutline = LeftAlign(MakeText(subscriptSuffix.ToLowerInvariant(),
                                                                          new Vector2(rightBracketBounds.Right,
                                                                                      rightBracketBounds.Top - 0.1),
                                                                          new Vector2(-0.5 * rightBracketBounds.Width, 0),
                                                                          scriptscale));
                        result.Add(GeneralPath.ShapeOf(subscriptOutline.GetOutline(), foreground));
                    }
                    if (superscriptSuffix != null && superscriptSuffix.Any())
                    {
                        var superscriptOutline = LeftAlign(MakeText(superscriptSuffix.ToLowerInvariant(),
                                                                    new Vector2(rightBracketBounds.Right,
                                                                                rightBracketBounds.Bottom + 0.1),
                                                                    new Vector2(-rightBracketBounds.Width, 0),
                                                                    scriptscale));
                        result.Add(GeneralPath.ShapeOf(superscriptOutline.GetOutline(), foreground));
                    }
                }
            }
            else if (pairs.Any())
            {
                SgroupBracket suffixBracket     = null;
                Vector2?      suffixBracketPerp = null;

                foreach (var e in pairs)
                {
                    var bracket     = e.Key;
                    var bond        = e.Value;
                    var inGroupAtom = atoms.Contains(bond.Begin) ? bond.Begin : bond.End;

                    var p1 = bracket.FirstPoint;
                    var p2 = bracket.SecondPoint;

                    var perp = VecmathUtil.NewPerpendicularVector(VecmathUtil.NewUnitVector(p1, p2));

                    // point the vector at the atom group
                    var midpoint = VecmathUtil.Midpoint(p1, p2);
                    if (Vector2.Dot(perp, VecmathUtil.NewUnitVector(midpoint, inGroupAtom.Point2D.Value)) < 0)
                    {
                        perp = Vector2.Negate(perp);
                    }
                    perp *= bracketDepth;

                    if (round)
                    {
                        result.Add(CreateRoundBracket(p1, p2, perp, midpoint));
                    }
                    else
                    {
                        result.Add(CreateSquareBracket(p1, p2, perp));
                    }

                    if (suffixBracket == null)
                    {
                        suffixBracket     = bracket;
                        suffixBracketPerp = perp;
                    }
                    else
                    {
                        // is this bracket better as a suffix?
                        var sp1      = suffixBracket.FirstPoint;
                        var sp2      = suffixBracket.SecondPoint;
                        var bestMaxX = Math.Max(sp1.X, sp2.X);
                        var thisMaxX = Math.Max(p1.X, p2.X);
                        var bestMaxY = Math.Max(sp1.Y, sp2.Y);
                        var thisMaxY = Math.Max(p1.Y, p2.Y);

                        // choose the most eastern or.. the most southern
                        var xDiff = thisMaxX - bestMaxX;
                        var yDiff = thisMaxY - bestMaxY;
                        if (xDiff > EQUIV_THRESHOLD || (xDiff > -EQUIV_THRESHOLD && yDiff < -EQUIV_THRESHOLD))
                        {
                            suffixBracket     = bracket;
                            suffixBracketPerp = perp;
                        }
                    }
                }

                // write the labels
                if (suffixBracket != null)
                {
                    var subSufPnt = suffixBracket.FirstPoint;
                    var supSufPnt = suffixBracket.SecondPoint;

                    // try to put the subscript on the bottom
                    var xDiff = subSufPnt.X - supSufPnt.X;
                    var yDiff = subSufPnt.Y - supSufPnt.Y;
                    if (yDiff > EQUIV_THRESHOLD || (yDiff > -EQUIV_THRESHOLD && xDiff > EQUIV_THRESHOLD))
                    {
                        var tmpP = subSufPnt;
                        subSufPnt = supSufPnt;
                        supSufPnt = tmpP;
                    }

                    // subscript/superscript suffix annotation
                    if (subscriptSuffix != null && subscriptSuffix.Any())
                    {
                        var subscriptOutline = LeftAlign(MakeText(subscriptSuffix.ToLowerInvariant(), subSufPnt, suffixBracketPerp.Value, labelScale));
                        result.Add(GeneralPath.ShapeOf(subscriptOutline.GetOutline(), foreground));
                    }
                    if (superscriptSuffix != null && superscriptSuffix.Any())
                    {
                        var superscriptOutline = LeftAlign(MakeText(superscriptSuffix.ToLowerInvariant(), supSufPnt, suffixBracketPerp.Value, labelScale));
                        result.Add(GeneralPath.ShapeOf(superscriptOutline.GetOutline(), foreground));
                    }
                }
            }
            else if (brackets.Count == 2)
            {
                var b1p1 = brackets[0].FirstPoint;
                var b1p2 = brackets[0].SecondPoint;
                var b2p1 = brackets[1].FirstPoint;
                var b2p2 = brackets[1].SecondPoint;

                var b1vec = VecmathUtil.NewUnitVector(b1p1, b1p2);
                var b2vec = VecmathUtil.NewUnitVector(b2p1, b2p2);

                var b1pvec = VecmathUtil.NewPerpendicularVector(b1vec);
                var b2pvec = VecmathUtil.NewPerpendicularVector(b2vec);

                // Point the vectors at each other
                if (Vector2.Dot(b1pvec, VecmathUtil.NewUnitVector(b1p1, b2p1)) < 0)
                {
                    b1pvec = Vector2.Negate(b1pvec);
                }
                if (Vector2.Dot(b2pvec, VecmathUtil.NewUnitVector(b2p1, b1p1)) < 0)
                {
                    b2pvec = Vector2.Negate(b2pvec);
                }

                // scale perpendicular vectors by how deep the brackets need to be
                b1pvec *= bracketDepth;
                b2pvec *= bracketDepth;

                // bad brackets
                if (double.IsNaN(b1pvec.X) || double.IsNaN(b1pvec.Y) ||
                    double.IsNaN(b2pvec.X) || double.IsNaN(b2pvec.Y))
                {
                    return(result);
                }

                {
                    var path = new PathGeometry();

                    if (round)
                    {
                        {
                            // bracket 1 (cp: control point)
                            var pf = new PathFigure
                            {
                                StartPoint = new Point(b1p1.X + b1pvec.X, b1p1.Y + b1pvec.Y)
                            };
                            Vector2 cpb1 = VecmathUtil.Midpoint(b1p1, b1p2);
                            cpb1 += VecmathUtil.Negate(b1pvec);
                            var seg = new QuadraticBezierSegment
                            {
                                Point1 = new Point(cpb1.X, cpb1.Y),
                                Point2 = new Point(b1p2.X + b1pvec.X, b1p2.Y + b1pvec.Y)
                            };
                            pf.Segments.Add(seg);
                            path.Figures.Add(pf);
                        }

                        {
                            // bracket 2 (cp: control point)
                            var pf = new PathFigure
                            {
                                StartPoint = new Point(b2p1.X + b2pvec.X, b2p1.Y + b2pvec.Y)
                            };
                            var cpb2 = VecmathUtil.Midpoint(b2p1, b2p2);
                            cpb2 += VecmathUtil.Negate(b2pvec);
                            var seg = new QuadraticBezierSegment
                            {
                                Point1 = new Point(cpb2.X, cpb2.Y),
                                Point2 = new Point(b2p2.X + b2pvec.X, b2p2.Y + b2pvec.Y)
                            };
                            pf.Segments.Add(seg);
                            path.Figures.Add(pf);
                        }
                    }
                    else
                    {
                        {
                            // bracket 1
                            var pf = new PathFigure
                            {
                                StartPoint = new Point(b1p1.X + b1pvec.X, b1p1.Y + b1pvec.Y)
                            };
                            var seg = new PolyLineSegment();
                            seg.Points.Add(new Point(b1p1.X, b1p1.Y));
                            seg.Points.Add(new Point(b1p2.X, b1p2.Y));
                            seg.Points.Add(new Point(b1p2.X + b1pvec.X, b1p2.Y + b1pvec.Y));
                            pf.Segments.Add(seg);
                            path.Figures.Add(pf);
                        }

                        {
                            // bracket 2
                            var pf = new PathFigure
                            {
                                StartPoint = new Point(b2p1.X + b2pvec.X, b2p1.Y + b2pvec.Y)
                            };
                            var seg = new PolyLineSegment();
                            seg.Points.Add(new Point(b2p1.X, b2p1.Y));
                            seg.Points.Add(new Point(b2p2.X, b2p2.Y));
                            seg.Points.Add(new Point(b2p2.X + b2pvec.X, b2p2.Y + b2pvec.Y));
                            pf.Segments.Add(seg);
                            path.Figures.Add(pf);
                        }
                    }

                    result.Add(GeneralPath.OutlineOf(path, stroke, foreground));
                }

                // work out where to put the suffix labels (e.g. ht/hh/eu) superscript
                // and (e.g. n, xl, c, mix) subscript
                // TODO: could be improved
                var b1MaxX = Math.Max(b1p1.X, b1p2.X);
                var b2MaxX = Math.Max(b2p1.X, b2p2.X);
                var b1MaxY = Math.Max(b1p1.Y, b1p2.Y);
                var b2MaxY = Math.Max(b2p1.Y, b2p2.Y);

                var subSufPnt = b2p2;
                var supSufPnt = b2p1;
                var subpvec   = b2pvec;

                var bXDiff = b1MaxX - b2MaxX;
                var bYDiff = b1MaxY - b2MaxY;

                if (bXDiff > EQUIV_THRESHOLD || (bXDiff > -EQUIV_THRESHOLD && bYDiff < -EQUIV_THRESHOLD))
                {
                    subSufPnt = b1p2;
                    supSufPnt = b1p1;
                    subpvec   = b1pvec;
                }

                var xDiff = subSufPnt.X - supSufPnt.X;
                var yDiff = subSufPnt.Y - supSufPnt.Y;

                if (yDiff > EQUIV_THRESHOLD || (yDiff > -EQUIV_THRESHOLD && xDiff > EQUIV_THRESHOLD))
                {
                    var tmpP = subSufPnt;
                    subSufPnt = supSufPnt;
                    supSufPnt = tmpP;
                }

                // subscript/superscript suffix annotation
                if (subscriptSuffix != null && subscriptSuffix.Any())
                {
                    var subscriptOutline = LeftAlign(MakeText(subscriptSuffix.ToLowerInvariant(), subSufPnt, subpvec, labelScale));
                    result.Add(GeneralPath.ShapeOf(subscriptOutline.GetOutline(), foreground));
                }
                if (superscriptSuffix != null && superscriptSuffix.Any())
                {
                    var superscriptOutline = LeftAlign(MakeText(superscriptSuffix.ToLowerInvariant(), supSufPnt, subpvec, labelScale));
                    result.Add(GeneralPath.ShapeOf(superscriptOutline.GetOutline(), foreground));
                }
            }
            return(result);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Depict a reaction.
        /// </summary>
        /// <param name="rxn">reaction instance</param>
        /// <returns>depiction</returns>
        /// <exception cref="CDKException">a depiction could not be generated</exception>
        public Depiction Depict(IReaction rxn, IReadOnlyDictionary <IChemObject, Color> highlight = null)
        {
            if (highlight == null)
            {
                highlight = Dictionaries.Empty <IChemObject, Color>();
            }

            Ensure2DLayout(rxn); // can reorder components!

            var fgcol = templateModel.GetAtomColorer().GetAtomColor(rxn.Builder.NewAtom("C"));

            var reactants = rxn.Reactants.ToList();
            var products  = rxn.Products.ToList();
            var agents    = rxn.Agents.ToList();
            List <LayoutBackup> layoutBackups = new List <LayoutBackup>();

            // set ids for tagging elements
            int molId = 0;

            foreach (var mol in reactants)
            {
                SetIfMissing(mol, MarkedElement.IdKey, "mol" + ++molId);
                SetIfMissing(mol, MarkedElement.ClassKey, "reactant");
                layoutBackups.Add(new LayoutBackup(mol));
            }
            foreach (var mol in products)
            {
                SetIfMissing(mol, MarkedElement.IdKey, "mol" + ++molId);
                SetIfMissing(mol, MarkedElement.ClassKey, "product");
                layoutBackups.Add(new LayoutBackup(mol));
            }
            foreach (var mol in agents)
            {
                SetIfMissing(mol, MarkedElement.IdKey, "mol" + ++molId);
                SetIfMissing(mol, MarkedElement.ClassKey, "agent");
                layoutBackups.Add(new LayoutBackup(mol));
            }

            var myHighlight = new Dictionary <IChemObject, Color>();

            if (atomMapColors != null)
            {
                foreach (var e in MakeHighlightAtomMap(reactants, products))
                {
                    myHighlight[e.Key] = e.Value;
                }
            }
            // user highlight buffer pushes out the atom-map highlight if provided
            foreach (var e in highlight)
            {
                myHighlight[e.Key] = e.Value;
            }

            PrepareCoords(reactants);
            PrepareCoords(products);
            PrepareCoords(agents);

            // highlight parts
            foreach (var e in myHighlight)
            {
                e.Key.SetProperty(StandardGenerator.HighlightColorKey, e.Value);
            }

            // setup the model scale based on bond length
            var scale = this.CaclModelScale(rxn);
            var model = CreateModel();

            model.SetScale(scale);

            // reactant/product/agent element generation, we number the reactants, then products then agents
            var reactantBounds = Generate(reactants, model, 1);
            var productBounds  = Generate(rxn.Products.ToList(), model, rxn.Reactants.Count);
            var agentBounds    = Generate(rxn.Agents.ToList(), model, rxn.Reactants.Count + rxn.Products.Count);

            // remove current highlight buffer
            foreach (var obj in myHighlight.Keys)
            {
                obj.RemoveProperty(StandardGenerator.HighlightColorKey);
            }

            // generate a 'plus' element
            var plus = GeneratePlusSymbol(scale, fgcol);

            // reset the coordinates to how they were before we invoked depict
            foreach (LayoutBackup backup in layoutBackups)
            {
                backup.Reset();
            }

            var emptyBounds    = new Bounds();
            var title          = model.GetShowReactionTitle() ? GenerateTitle(model, rxn, scale) : emptyBounds;
            var reactantTitles = new List <Bounds>();
            var productTitles  = new List <Bounds>();

            if (model.GetShowMoleculeTitle())
            {
                foreach (IAtomContainer reactant in reactants)
                {
                    reactantTitles.Add(GenerateTitle(model, reactant, scale));
                }
                foreach (IAtomContainer product in products)
                {
                    productTitles.Add(GenerateTitle(model, product, scale));
                }
            }

            Bounds conditions = GenerateReactionConditions(rxn, fgcol, model.GetScale());

            return(new ReactionDepiction(model,
                                         reactantBounds, productBounds, agentBounds,
                                         plus, rxn.Direction, dimensions,
                                         reactantTitles,
                                         productTitles,
                                         title,
                                         conditions,
                                         fgcol));
        }
Exemplo n.º 10
0
        /// <summary>
        /// Depict a set of molecules, they will be depicted in a grid with the
        /// specified number of rows and columns. Rows are filled first and then
        /// columns.
        /// </summary>
        /// <param name="mols">molecules</param>
        /// <param name="nrow">number of rows</param>
        /// <param name="ncol">number of columns</param>
        /// <returns>depiction</returns>
        /// <exception cref="CDKException">a depiction could not be generated</exception>
        public Depiction Depict(IEnumerable <IAtomContainer> mols, int nrow, int ncol, IReadOnlyDictionary <IChemObject, Color> highlight = null)
        {
            if (highlight == null)
            {
                highlight = Dictionaries.Empty <IChemObject, Color>();
            }

            var layoutBackups = new List <LayoutBackup>();
            int molId         = 0;

            foreach (var mol in mols)
            {
                SetIfMissing(mol, MarkedElement.IdKey, "mol" + ++molId);
                layoutBackups.Add(new LayoutBackup(mol));
            }

            // ensure we have coordinates, generate them if not
            // we also rescale the molecules such that all bond
            // lengths are the same.
            PrepareCoords(mols);

            // highlight parts
            foreach (var e in highlight)
            {
                e.Key.SetProperty(StandardGenerator.HighlightColorKey, e.Value);
            }

            // generate bound rendering elements
            var model = CreateModel();
            // setup the model scale
            var molList = mols.ToList();

            model.SetScale(CaclModelScale(molList));

            var molElems = Generate(molList, model, 1);

            // reset molecule coordinates
            foreach (LayoutBackup backup in layoutBackups)
            {
                backup.Reset();
            }

            // generate titles (if enabled)
            var titles = new List <Bounds>();

            if (model.GetShowMoleculeTitle())
            {
                foreach (var mol in mols)
                {
                    titles.Add(GenerateTitle(model, mol, model.GetScale()));
                }
            }

            // remove current highlight buffer
            foreach (var obj in highlight.Keys)
            {
                obj.RemoveProperty(StandardGenerator.HighlightColorKey);
            }

            return(new MolGridDepiction(model, molElems, titles, dimensions, nrow, ncol));
        }