JensKrumsieck/ChemSharp

View on GitHub
ChemSharp.Molecules/Export/PDBExporter.cs

Summary

Maintainability
A
1 hr
Test Coverage
using ChemSharp.Export;
using ChemSharp.Extensions;

namespace ChemSharp.Molecules.Export;

public class PDBExporter : AbstractMoleculeExporter
{
    public static void Export(Molecule mol, string filename)
    {
        var exporter = new PDBExporter();
        using var stream = File.Create(filename);
        exporter.Export(mol, stream);
    }

    public override void Export(IExportable exportable, Stream stream)
    {
        base.Export(exportable, stream);
        if (Molecule == null) return;
        var atomsCount = Molecule.Atoms.Count;
        using var sw = new StreamWriter(stream);
        sw.WriteLine("HEADER");
        sw.WriteLine($"TITLE{StringUtil.Spaces(5)}{Molecule.Title}");

        var line = new char[80];
        for (var i = 0; i < atomsCount; i++)
        {
            var atom = Molecule.Atoms[i];
            Array.Fill(line, ' ');
            AppendToCharArrayAt(in line, "ATOM", 0, PdbAlign.Left);
            AppendToCharArrayAt(in line, i.ToString(), 11);
            AppendToCharArrayAt(in line, atom.Title, 13, PdbAlign.Left);
            AppendToCharArrayAt(in line, atom.Residue, 20);
            AppendToCharArrayAt(in line, atom.ChainId != default ? atom.ChainId : ' ', 22);
            AppendToCharArrayAt(in line, atom.ResidueId.ToString(), 26);
            AppendToCharArrayAt(in line, atom.Location.X.ToInvariantString(), 38);
            AppendToCharArrayAt(in line, atom.Location.Y.ToInvariantString(), 46);
            AppendToCharArrayAt(in line, atom.Location.Z.ToInvariantString(), 54);
            AppendToCharArrayAt(in line, atom.Symbol, 78);
            AppendToCharArrayAt(in line, atom.Charge.ToString(), 80);
            sw.WriteLine(line);
        }
    }

    private static void AppendToCharArrayAt(in char[] arr, char chr, int index) => arr[index] = chr;

    //if align is right, give end column index
    private static void AppendToCharArrayAt(in char[] arr, ReadOnlySpan<char> str, int index,
        PdbAlign align = PdbAlign.Right)
    {
        switch (align)
        {
            case PdbAlign.Left:
            {
                for (var i = 0; i < str.Length; i++) arr[index + i] = str[i];
                break;
            }
            case PdbAlign.Right:
            {
                for (var i = 0; i < str.Length; i++) arr[index - str.Length + i] = str[i];
                break;
            }
            default:
                throw new ArgumentOutOfRangeException(nameof(align), align, null);
        }
    }

    private enum PdbAlign
    {
        Left,
        Right
    }
}