name: pg
file_type: pg_file
primary_key: [pg_id]
identity_composite: [pg_accessions, grouped_runs, label]
doc: "Protein groups with per-quantification-unit quantification (one row per label; label/intensity flattened from the old intensities list)"

fields:
  # Identity
  pg_id:
    type: int64
    required: true
    nullable: false
    doc: "Opaque identity of the pg (int64), supplied by the producer or derived from the identity_composite declared in the footer; the primary key of this view."

  # Protein group identity
  pg_accessions:
    type: "list<string>"
    required: true
    doc: "Protein accessions within this group. Part of the default identity composite: the FULL group membership (not just the leader) keys the pg_id, so two distinct groups that happen to share a leading protein get distinct ids. Hashed order-independently (membership is a set)."
  pg_names:
    type: "list<string>"
    doc: "Protein group names"
  gg_accessions:
    type: "list<string>"
    doc: "Gene group identifiers (gene symbols; Ensembl IDs when available)"
  gg_names:
    type: "list<string>"
    doc: "Gene group names (gene symbols from tool output)"
  gg_qvalue:
    type: float64
    nullable: true
    doc: "Gene group q-value (e.g., DIA-NN GG.Q.Value)"
  anchor_protein:
    type: string
    required: true
    doc: "Anchor/leading protein of the group — a descriptive representative for display only. NOT part of the pg_id identity (which keys on the full pg_accessions membership), and MUST NOT be used for feature->pg joins or per-protein statistics: it is not unique across groups that share a leading protein. Join feature->pg via feature.pg_ids/pg_id or full pg_accessions. See docs/spec/pg.md -> Protein group semantics."

  # Quantification-unit context
  grouped_runs:
    type: "list<string>"
    required: true
    doc: "Raw files grouped into this quantification unit (fractions aggregated together; single-element for unfractionated/DIA)"

  # Quality metrics
  global_qvalue:
    type: float64
    doc: "Global q-value at experiment level"
  pg_qvalue:
    type: float64
    doc: "Protein group q-value at run level"

  # Quantification (flattened: one row per label. label/intensity are null for
  # identification-only protein groups that carry no quantity, e.g. mzIdentML.)
  label:
    type: string
    nullable: true
    doc: "Channel/label of this quantification; null for identification-only groups (no intensity). Part of the default identity composite."
  intensity:
    type: float32
    nullable: true
    doc: "Primary intensity for this label; null for identification-only groups"
  additional_intensities:
    type: "list<additional_intensity>"
    doc: "Tool-provided intensities (normalized, LFQ, iBAQ) for this row's label, read from upstream output"

  # Flags
  is_decoy:
    type: bool
    required: true
    doc: "Decoy flag"
  contaminant:
    type: bool
    doc: "Contaminant flag"

  # Peptide/feature counts
  peptides:
    type: "list<peptide_per_protein>"
    required: true
    doc: "Peptide counts per protein in the group"
  peptide_counts:
    type: peptide_counts
    doc: "Unique/total peptide sequence counts"
  feature_counts:
    type: feature_counts
    doc: "Unique/total feature counts"

  # Protein properties
  sequence_coverage:
    type: float32
    doc: "Sequence coverage percentage"
  molecular_weight:
    type: float32
    doc: "Molecular weight (kDa)"

  # Scores and metadata
  additional_scores:
    type: "list<score>"
    doc: "Additional scores"
  cv_params:
    type: "list<cv_param>"
    doc: "CV parameters"
