Table of Contents

Extract Chart Data from Documents

Reports, filings and papers put their key numbers in charts, where text extraction sees only a picture. DocumentParser reads a chart as the data it plots: every chart of a document comes back as a ChartContent holding its data table, the title it prints, its legend, and one table per panel for a figure of several plots.


Prerequisites

Requirement Minimum
.NET SDK 8.0+
GPU Recommended; the parser runs on the CPU too, much more slowly
Disk About 2.5 GB for the parser's models, downloaded on first use

Step 1: Find Every Chart of a Document

using LMKit.Document.Parsing;

using var parser = new DocumentParser(ParsingEffort.High);
ParsedDocument document = parser.Parse("annual-report.pdf");

foreach (ParsedPage page in document.Pages)
{
    foreach (ParsedElement element in page.Elements)
    {
        if (element.Content is ChartContent chart && !chart.IsEmpty)
        {
            Console.WriteLine($"Page {page.PageNumber}: {chart.Caption}");
            Console.WriteLine(chart.Text);
        }
    }
}

ChartContent.Text is a Markdown table: the series names head the columns and the categories label the rows. High is the effort level to choose when the numbers matter most.

Member Holds
Text The plotted data as a Markdown table
Caption The title the chart prints for itself, when no caption element of the page names it
PieceTitle The title printed inside the plot's own box
Legend The legend words and axis titles the table does not carry
Panels One ChartContent.Panel (Title, Table) per plot of a multi-panel figure; HasPanels says whether there are two or more

A figure whose data was not read (a photograph, a diagram, a chart the parser could not read) stays a FigureContent: a picture with an optional description.


Step 2: Export Each Chart as CSV

The data table converts to CSV in a few lines, one file per chart and one per panel.

using System.Text;

int index = 0;

foreach (ParsedPage page in document.Pages)
{
    foreach (ChartContent chart in page.Elements.Select(e => e.Content).OfType<ChartContent>())
    {
        IEnumerable<(string Name, string Table)> tables = chart.HasPanels
            ? chart.Panels.Select((panel, p) => ($"{index}-{p + 1}", panel.Table))
            : new[] { (index.ToString(), chart.Text) };

        foreach ((string name, string table) in tables)
        {
            File.WriteAllText($"chart-p{page.PageNumber}-{name}.csv", ToCsv(table));
        }

        index++;
    }
}

static string ToCsv(string markdownTable)
{
    var csv = new StringBuilder();

    foreach (string line in markdownTable.Split('\n'))
    {
        string row = line.Trim();

        // Skip the separator row (|---|---|) and blank lines.
        if (row.Length == 0 || row.Replace("|", "").Replace("-", "").Replace(":", "").Trim().Length == 0)
        {
            continue;
        }

        IEnumerable<string> cells = row.Trim('|').Split('|')
            .Select(cell => cell.Trim())
            .Select(cell => cell.Contains(',') || cell.Contains('"') ? $"\"{cell.Replace("\"", "\"\"")}\"" : cell);

        csv.AppendLine(string.Join(",", cells));
    }

    return csv.ToString();
}

Step 3: Keep the Chart Picture Beside Its Data

Set IncludeFigureImages to keep the picture of each chart, so a reviewer can check the numbers against the plot:

using LMKit.Media.Image;

using var parser = new DocumentParser(ParsingEffort.High) { IncludeFigureImages = true };
ParsedDocument document = parser.Parse("annual-report.pdf");

foreach (ParsedPage page in document.Pages)
{
    foreach (ParsedElement element in page.Elements.Where(e => e.Content is ChartContent))
    {
        using ImageBuffer picture = element.GetImage();
        picture?.SaveAsPng($"chart-p{page.PageNumber}-{element.ReadingIndex}.png");
    }
}

document.SaveHtml("report.html") writes a page that shows each chart's picture next to its data table, a quick way to review a whole report.


DocumentParser or VlmOcr for Charts?

VlmOcr with the chart intent converts one chart image you already hold with the vision model you choose. DocumentParser finds the charts in a whole document by itself, names each with the title and legend the page prints, splits multi-panel figures, and returns them in reading order among the page's other elements.


Next Steps

Share