Skip to content

Data

Anatomy of a line record

4 min readUpdated Verified against fe1ff7d on 2026-09-25

Page actions

ChatGPT and Claude are third-party services. The link gives them this page's public address and a short instruction. This site records nothing.

One display line of the Granth is one row of the lines table. What its 23 columns mean, how a printed page becomes rows, which columns search reads — with a live explorer over the real API.

Every unit the source prints between two double dandas becomes one row of the lines table. The poster follows one page from the PDF to that row; the explorer below it shows real rows, verbatim, straight from the API.

Anatomy of a line record A PDF page (54–1483) is an Ang (1–1430). The page text is segmented into units on the double danda; a unit that is a heading carries the raag, section, author, ghar and comp_type for the lines that follow; comp_id groups a whole composition with its heading run and line_no counts within it. Each row keeps the verbatim Gurmukhi with its markers, a clean text form, search forms (translit, translit_norm, first letters, skeleton) and the v2 structural columns. The FTS5 index covers six search columns with bm25 weights 10, 5, 4, 3, 3, 1; English is a separate layer. 03 · Anatomy of a line record How a page of the source Bir becomes rows of the lines table — one display lineper row — and which columns search reads One row of the lines table Source Bir PDF — pages 54–1483, attestedSource Bir PDFpages 54–1483, attestedOne page, one Ang — Angs 1–1430, borders goneOne page, one AngAngs 1–1430, borders gonesegment_units — split on the double danda — one unit becomes one rowsegment_unitssplit on the double dandaone unit becomes one rowFlags from segmentation — is_rahao · is_headerFlags from segmentationis_rahao · is_headerdetect_header — a heading carries raag, — section, author, formdetect_headera heading carries raag,section, author, formFrom the heading — raag · section · author · gharFrom the headingraag · section · author · gharcomp_id groups it — heading run + body: one id — body lines keep their idcomp_id groups itheading run + body: one idbody lines keep their idPlacement — id · ang · pdf_page — comp_id · line_noPlacementid · ang · pdf_pagecomp_id · line_no/api/ang/{n} — 15 columns, verbatim/api/ang/{n}15 columns, verbatimThe text: never edited — gurmukhi · text · markersThe text: never editedgurmukhi · text · markersSearch forms, derived — translit · translit_norm — fl_g · fl_r · skeletonSearch forms, derivedtranslit · translit_normfl_g · fl_r · skeletonStructure (enrich_v2) — stanza_index · pada_totalStructure (enrich_v2)stanza_index · pada_totalfts: the FTS5 index — bm25 10·5·4·3·3·1fts: the FTS5 indexbm25 10·5·4·3·3·1Beside it — fts_en — fts_shabadBeside itfts_enfts_shabad data at restcomponent in this projectexplanationflow: data or control moves this wayreference: pins, reads or derives from Source of truth: sggs-data/pipeline/build_corpus.py ·sggs-data/pipeline/sggs_pipeline.py · webapp/sggs/search.py ·webapp/sggs/core.py v1.3.10 · verified 2026-09-27 · 017091bSri Guru Granth Sahib Ji — Knowledge Base · engineering wiki
Poster 03 — Anatomy of a line record: from a PDF page to units to the 23 columns of the lines table and the FTS index · open full size

Explore real records

On the rendered wiki this is a live explorer: choose an Ang and every line record of it is listed, verbatim from /api/ang/{n}, with the placement and heading columns beside it and a definition of each column on hover. On GitHub, open Ang 1 in the website’s reader instead.

Try the quick picks. Ang 1 opens with a heading and then Japji, whose author is null because the print has no ਮਹਲਾ line. Ang 151 shows a raag title and its invocation sharing one heading run. Ang 462 is where Asa Ki Vaar begins, saloks and pauris interleaving. Ang 712’s first composition began on Ang 711 (continued_from). Ang 1256 prints one refrain twice — a legitimate repeat that the pipeline must never de-duplicate.

The 23 columns

The table is created by build_db.py in sggs-data; the platform reads it read-only.

GroupColumnMeaning
PlacementidThe row’s identity across the corpus (1–60,658); never reused.
angThe Ang, 1–1430.
pdf_pageThe page of the source PDF (54–1483) the line was read from.
comp_idGroups every line of one composition, heading run included; vacated ids are permanent gaps.
line_noPosition inside the composition, 1..N, contiguous.
From the headingraagThe musical mode; null after Ang 1353, where the Granth leaves the raag framework.
sectionThe bani or section, header-detected.
authorFrom the ਮਹਲਾ or Bhagat label; null where the print has none (all of Japji).
gharThe musical “house” (ਘਰੁ) of the composition.
comp_typeThe form word on the heading; known to be mislabelled in places, suppressed at the display layer — prefer comp_id and section.
is_header1 on a heading line: a title, the ੴ invocation, a ਮਃ label.
Flagsis_rahao1 on the refrain line, from its ਰਹਾਉ marker.
markersThe numerals that closed the unit, as a JSON list (for example ["੧"]).
The textgurmukhiThe line as printed, verbatim, dandas and markers included. Never edited anywhere.
textThe same line without its markers, for indexing.
Search formstranslitRoman transliteration — a reading aid, not scripture.
translit_normThe spelling-tolerant fold of translit (roman_norm), built in the database, not in the corpus file.
fl_g / fl_rFirst letters of each word, Gurmukhi and Roman, for first-letter search.
skeletonThe line with its vowel signs stripped, for the typo tier.
Structure (v2)stanza_indexWhich stanza of its composition the line belongs to.
pada_totalHow many padas the composition has.
source_categoryA coarse category of the source unit (for layout).

The API’s LINE_COLS returns 15 of them on every line (/api/ang, /api/shabad, search results), always including gurmukhi:

webapp/sggs/core.py · LINE_COLS · lines 57–59
LINE_COLS = ('id, ang, raag, section, author, comp_type, comp_id, line_no, '
'is_rahao, is_header, gurmukhi, translit, '
'stanza_index, pada_total, source_category') # v2.0 structural metadata

Read from the source at build time — view these lines on GitHub at c3d9360.

Source: webapp/sggs/core.py, the LINE_COLS tuple.

Headings, compositions and the comp_id rule

A heading is detected by detect_header from the unit’s text — a raag title, the invocation, a ਮਹਲਾ or Bhagat label — and the lines that follow inherit its metadata. A run of consecutive heading lines opens one composition together with the body that follows (post-pass 1b in build_corpus.py), so /api/shabad/{comp_id} returns the printed title. The run adopts its last heading’s id, so no body line ever changes comp_id and vacated ids become permanent gaps: 4,527 distinct compositions and max(comp_id) 5,376 in the pinned dataset, comp_id 1 a gap because the Mool Mantar folds into Japji (comp_id 2). The full model, the before/after diagram and the invariants are in the canonical database schema.

Three closing rubrics (TRAILING_RUBRICS) belong to the preceding unit and stay one-line compositions, flagged for scholarly review; a verse that merely contains a raag or form word is not a heading (the v1.1.4 weak-signal rule, which demoted 233 mis-flagged verses).

What search reads

fts is an FTS5 table with external content over lines, covering text, translit, translit_norm, fl_g, fl_r and skeleton, tokenised so Gurmukhi signs and ੴ stay inside tokens. do_search ranks with bm25 and column weights 10 · 5 · 4 · 3 · 3 · 1 in that order: a hit in the verbatim text outranks a transliteration hit, which outranks a first-letter or skeleton hit. Beside it, fts_en serves the English tier and fts_shabad cross-line passages; the database also carries a trigram index, fts_tri, which no route reads. How the tiers cascade is the search waterfall.

The English translations (Dr. Sant Singh Khalsa via ShabadOS) are a separate table, attached to a line as en by the API and labelled as a translation everywhere; they are never blended into the Gurmukhi.

Read next: Corpus pipeline and gates.