Skip to content

Add scheme-based SECTOR/MSECTOR lookups and mapped EMISSIONS form#1777

Draft
louispt1 wants to merge 3 commits into
emissionsfrom
emissions-mapping
Draft

Add scheme-based SECTOR/MSECTOR lookups and mapped EMISSIONS form#1777
louispt1 wants to merge 3 commits into
emissionsfrom
emissions-mapping

Conversation

@louispt1

@louispt1 louispt1 commented Jul 8, 2026

Copy link
Copy Markdown
Member

Context

Adds the ETEngine surface for the sector mapping feature: Enabling SECTOR lookup by external classification schemes as recorded in the sector_mapping.csv config in ETSource.

Implemented changes

  • Etsource::Sectors: Rails-cached mapping hash and per-graph-type (label, use) -> node keys index (mirrors the merit order import).
  • Qernel::Sectors: per-graph-instance resolver — scheme?, pairs(scheme, values), lookup(scheme, values) — memoized per instance, reached via a new Graph#sector_map accessor.
  • SECTOR/MSECTOR now dispatch on arity: one argument is the legacy namespace-sector filter (byte-for-byte unchanged); two or more is scheme, value(s), returning the union of matching live nodes. Works identically on the molecule graph via MSECTOR.
  • EMISSIONS dispatches on whether the first argument is a known scheme: EMISSIONS(scheme, value, ghg[, 1990]) sums the emissions store over the mapping's resolved (label, use) pairs (missing store keys treated as 0); all legacy EMISSIONS forms are unchanged.
  • Unknown scheme/value raises (Gql::UnknownSectorSchemeError / UnknownSectorValueError) naming the valid options; a valid value with no labelled nodes returns [].
  • Spec additions in spec/models/gql/runtime/functions/lookup_spec.rb covering legacy back-compat, multi-value union, pair-correctness (energetic vs non-energetic), unknown scheme/value errors, blank/- cells, and the mapped EMISSIONS form.

Related

atlas
etengine
etsource

Checklist

  • I have tested these changes
  • I have updated documentation as needed
  • I have tagged the relevant people for review


# Public: The inverted mapping index, keyed by scheme then normalized value.
def mapping
Rails.cache.fetch('sector_mapping_hash') do

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on how much the new sector is used, we might want to use process memory (NastyCache) vs the Rails cache

@noracato noracato left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Already left a few questions for you to think about.

I was also contemplating if the Qernel::Sector could benefit from Dry, what do you think about that?


# Scheme-based sector mapping lookups. `energy`/`molecule` select the
# graph whose live nodes are returned; the mapping itself is shared.
def energy_sector_map(scheme, values)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def energy_sector_map(scheme, values)
def energy_sector_map_nodes(scheme, values)

This method is returning nodes, not a map. It's more clear to put that already in the methods name

Comment on lines +403 to +421
# Internal: Sums the emissions store over every (sector label, use) pair
# the mapping resolves for `scheme`/`value`. Present year is implicit;
# only 1990 is suffixed. Missing store keys count as zero.
def mapped_emissions(keys)
scheme, value, ghg, year = keys

if ghg.nil?
raise Gql::GqlError, "EMISSIONS(#{scheme.inspect}, ...) needs a GHG argument, e.g. " \
"EMISSIONS(#{scheme.inspect}, #{value.inspect}, co2)"
end

suffix = ('1990' if year.to_i == 1990)
emissions = scope.graph.emissions

scope.sector_resolver.pairs(scheme, value).sum do |label, use|
key = [label, use, ghg, suffix].compact.join('_').to_sym
emissions[key] || 0.0
end
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's think about if summing logic should live in GQL lookup. Did you consider a (class) method on emissions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants