JensKrumsieck/ChemSharp

View on GitHub
ChemSharp.Spectroscopy/Formats/CSVFormat.cs

Summary

Maintainability
A
0 mins
Test Coverage
using ChemSharp.Memory;
using ChemSharp.Spectroscopy.Extensions;

namespace ChemSharp.Spectroscopy.Formats;

public class CSVFormat : FileFormat
{
    private readonly List<List<DataPoint>> MultiXYData = new();
    private readonly List<DataPoint> XYData = new();
    private char _delimiter = ',';
    private bool _firstDataRow = true;
    private bool _multiple;

    private CSVFormat()
    {
        ValidationMethod = FileExtensions.ValidateWithExtensions;
        NeededFiles = new Dictionary<string, Action<string>> {{".csv", ReadCSV}};
    }

    private void ReadCSV(string file)
    {
        using var fs = File.OpenRead(file);
        using var sr = new StreamReader(fs);
        while (sr.Peek() > 0)
        {
            var line = sr.ReadLine().AsSpan();
            ParseLine(line);
        }
    }

    private void ParseLine(ReadOnlySpan<char> line)
    {
        var cols = line.Split(new[] {_delimiter}.AsSpan());
        if (cols.Length == 0) return;
        var firstItem = line.Slice(cols[0].start, cols[0].length);
        if (!double.TryParse(firstItem.ToString(), out _)) return; //is header column
        var lastX = 0d;
        for (var i = 0; i < cols.Length; i++)
        {
            if (i % 2 == 1 && _multiple && _firstDataRow) MultiXYData.Add(new List<DataPoint>());
            var item = line.Slice(cols[i].start, cols[i].length).ToSingle();
            if (i % 2 == 0) lastX = item;
            else if (!_multiple) XYData.Add(new DataPoint(lastX, item));
            else MultiXYData[(i - 1) / 2].Add(new DataPoint(lastX, item));
        }

        _firstDataRow = false;
    }

    public static Spectrum Read(string filename, char delimiter)
    {
        var format = new CSVFormat {_delimiter = delimiter};
        format.Load(filename);
        return new Spectrum(format.XYData) {Title = filename};
    }

    public static List<Spectrum> ReadAll(string filename, char delimiter)
    {
        var format = new CSVFormat {_delimiter = delimiter, _multiple = true};
        format.Load(filename);
        return format.MultiXYData.Select(list => new Spectrum(list) {Title = filename}).ToList();
    }
}