Refactor: instruments have sensors - #328

Merged
j-atkins merged 79 commits into
mainfrom
refactor-sensors
May 1, 2026
Merged

Refactor: instruments have sensors#328
j-atkins merged 79 commits into
mainfrom
refactor-sensors

Conversation

@j-atkins

@j-atkinsj-atkins commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR centralises/abstracts instrument sensor/variable sampling logic so that each instrument declares which sensors it carries (e.g. TEMPERATURE, SALINITY, VELOCITY). Users can configure which sensors are active for each instrument in the expedition YAML.

This helps pave the way for easy addition of BGC sensors to the Argo float in a future PR (#234), and consolidation of CTD + CTD_BGC into a single instrument (#260) with a combined sensor allowlist. Also makes it straightforward to add new sensors to any instrument in the future (e.g., #312, #313), and streamlines them process for developers to add new instruments (i.e. #237)

Major changes

  • sensors.py in instruments/ defines the SensorType class and per-instrument allowlists (so that there is control over which sensors each instrument supports and users cannot configure unsupported sensors).
  • New SensorConfig pydantic model and sensors field in every instrument config in expedition.py.
  • New SensorRegistry in utils.py that maps each SensorType to its FieldSet key, Copernicus variable name, category (phys/bgc), and Parcels particle variable name(s).
    • Per-instrument parcticle classes are now built dynamically at runtime based on which sensors are active, but the fixed/mechanical variables are still hard-coded in the instrument files, e.g. cycle_phase for Argo Floats.

API change

As mentioned above, the instruments config section of the expedition YAML now has a sensors list field, where users specify which sensors are active. For example, below the CTD is configured to sample TEMPERATURE and SALINITY:

ctd_config:
stationkeeping_time_minutes: 50min_depth_meter: -11max_depth_meter: -2000sensors:
- TEMPERATURE
- SALINITY
  • If the sensors list is omitted, it default to all valid sensors for that instrument.
  • By using allowlists for each instrument, it will not allow non-sensical sensor combinations (e.g. BGC sensors on an ADCP).
  • Will also not allow an empty sensor list, at least one sensor must be active.

Additional change

  • Argo Float sampling kernels have been separated from the vertical-movement kernel, making it easier to add BGC sensors in a future PR.

Follow-up PRs

  • The plan CLI tool will need updating to account for sensor configuration options. Currently not broken but doesn't give option to configure sensors. (New issue to be opened)
  • Docs update to clearly communicate which sensors each instrument accepts, and how to configure them in either the plan tool or the expedition YAML. (New issue to be opened)
  • Merge CTD + CTD_BGC into a single instrument. (Unify CTD and CTD_BGC to one instrument #260)
  • Add BGC sampling to Argo Floats (New ARGO_BGC instrument #234)

Tests

  • Update existing tests and add new tests to cover new sensor logic

… kernels from the argo vertical movement kernel to enable easier scalability
@j-atkins

Copy link
Copy Markdown
CollaboratorAuthor

I have addressed various comments from the first round of review on this PR. See below for a list of main changes:

  • Renamed all _*_FIXED_VARIABLES lists to _*_NONSENSOR_VARIABLES
  • Renamed _SensorMeta to _Sensor, added type_: SensorType as a field so each sensor object is self-describing, and moved the class + SENSOR_REGISTRY from utils.py into sensors.py
  • New _InstrumentConfigMixin in expedition.py defines shared methods that can be flexibly inherited across the InstrumentConfig models, addresses duplication flagged.
    • Note, though, also that this logic has been extended to other preexisting datetime related parts of the InstrumetConfigs, e.g. minutes and lifetime params (so this is some 'bonus' refactoring).
    • The tests associated with each method are maintained and a new test added to test_expedition.py to check that all InstrumentConfig models inherit from the mixin.
  • Instrument subclasses (e.g. CTDInstrument) must now define sensor_kernel dictionary to map the sensor types to the relevant sampling kernels as a class attribute. This is checked by the Instrument base class and also a test added to test_base.py. Means the allowlists for different sensor types are now explicitly defined and managed within each instrument class, which is nice for further centralising instrument characteristics and behaviours.

@j-atkins
j-atkins merged commit 47f4ab8 into mainMay 1, 2026
11 checks passed
@j-atkins
j-atkins deleted the refactor-sensors branch May 1, 2026 13:24
Sign up for freeto 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.

3 participants

@j-atkins@erikvansebille@VeckoTheGecko
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Refactor: instruments have sensors - #328

Merged
j-atkins merged 79 commits into
mainfrom
refactor-sensors
May 1, 2026
Merged

Refactor: instruments have sensors#328
j-atkins merged 79 commits into
mainfrom
refactor-sensors

Conversation

@j-atkins

@j-atkinsj-atkins commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR centralises/abstracts instrument sensor/variable sampling logic so that each instrument declares which sensors it carries (e.g. TEMPERATURE, SALINITY, VELOCITY). Users can configure which sensors are active for each instrument in the expedition YAML.

This helps pave the way for easy addition of BGC sensors to the Argo float in a future PR (#234), and consolidation of CTD + CTD_BGC into a single instrument (#260) with a combined sensor allowlist. Also makes it straightforward to add new sensors to any instrument in the future (e.g., #312, #313), and streamlines them process for developers to add new instruments (i.e. #237)

Major changes

  • sensors.py in instruments/ defines the SensorType class and per-instrument allowlists (so that there is control over which sensors each instrument supports and users cannot configure unsupported sensors).
  • New SensorConfig pydantic model and sensors field in every instrument config in expedition.py.
  • New SensorRegistry in utils.py that maps each SensorType to its FieldSet key, Copernicus variable name, category (phys/bgc), and Parcels particle variable name(s).
    • Per-instrument parcticle classes are now built dynamically at runtime based on which sensors are active, but the fixed/mechanical variables are still hard-coded in the instrument files, e.g. cycle_phase for Argo Floats.

API change

As mentioned above, the instruments config section of the expedition YAML now has a sensors list field, where users specify which sensors are active. For example, below the CTD is configured to sample TEMPERATURE and SALINITY:

ctd_config:
stationkeeping_time_minutes: 50min_depth_meter: -11max_depth_meter: -2000sensors:
- TEMPERATURE
- SALINITY
  • If the sensors list is omitted, it default to all valid sensors for that instrument.
  • By using allowlists for each instrument, it will not allow non-sensical sensor combinations (e.g. BGC sensors on an ADCP).
  • Will also not allow an empty sensor list, at least one sensor must be active.

Additional change

  • Argo Float sampling kernels have been separated from the vertical-movement kernel, making it easier to add BGC sensors in a future PR.

Follow-up PRs

  • The plan CLI tool will need updating to account for sensor configuration options. Currently not broken but doesn't give option to configure sensors. (New issue to be opened)
  • Docs update to clearly communicate which sensors each instrument accepts, and how to configure them in either the plan tool or the expedition YAML. (New issue to be opened)
  • Merge CTD + CTD_BGC into a single instrument. (Unify CTD and CTD_BGC to one instrument #260)
  • Add BGC sampling to Argo Floats (New ARGO_BGC instrument #234)

Tests

  • Update existing tests and add new tests to cover new sensor logic

… kernels from the argo vertical movement kernel to enable easier scalability
@j-atkins

Copy link
Copy Markdown
CollaboratorAuthor

I have addressed various comments from the first round of review on this PR. See below for a list of main changes:

  • Renamed all _*_FIXED_VARIABLES lists to _*_NONSENSOR_VARIABLES
  • Renamed _SensorMeta to _Sensor, added type_: SensorType as a field so each sensor object is self-describing, and moved the class + SENSOR_REGISTRY from utils.py into sensors.py
  • New _InstrumentConfigMixin in expedition.py defines shared methods that can be flexibly inherited across the InstrumentConfig models, addresses duplication flagged.
    • Note, though, also that this logic has been extended to other preexisting datetime related parts of the InstrumetConfigs, e.g. minutes and lifetime params (so this is some 'bonus' refactoring).
    • The tests associated with each method are maintained and a new test added to test_expedition.py to check that all InstrumentConfig models inherit from the mixin.
  • Instrument subclasses (e.g. CTDInstrument) must now define sensor_kernel dictionary to map the sensor types to the relevant sampling kernels as a class attribute. This is checked by the Instrument base class and also a test added to test_base.py. Means the allowlists for different sensor types are now explicitly defined and managed within each instrument class, which is nice for further centralising instrument characteristics and behaviours.

@j-atkins
j-atkins merged commit 47f4ab8 into mainMay 1, 2026
11 checks passed
@j-atkins
j-atkins deleted the refactor-sensors branch May 1, 2026 13:24
Sign up for freeto 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.

3 participants

@j-atkins@erikvansebille@VeckoTheGecko
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor: instruments have sensors - #328

Merged
j-atkins merged 79 commits into
mainfrom
refactor-sensors
May 1, 2026
Merged

Refactor: instruments have sensors#328
j-atkins merged 79 commits into
mainfrom
refactor-sensors

Conversation

@j-atkins

@j-atkinsj-atkins commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR centralises/abstracts instrument sensor/variable sampling logic so that each instrument declares which sensors it carries (e.g. TEMPERATURE, SALINITY, VELOCITY). Users can configure which sensors are active for each instrument in the expedition YAML.

This helps pave the way for easy addition of BGC sensors to the Argo float in a future PR (#234), and consolidation of CTD + CTD_BGC into a single instrument (#260) with a combined sensor allowlist. Also makes it straightforward to add new sensors to any instrument in the future (e.g., #312, #313), and streamlines them process for developers to add new instruments (i.e. #237)

Major changes

  • sensors.py in instruments/ defines the SensorType class and per-instrument allowlists (so that there is control over which sensors each instrument supports and users cannot configure unsupported sensors).
  • New SensorConfig pydantic model and sensors field in every instrument config in expedition.py.
  • New SensorRegistry in utils.py that maps each SensorType to its FieldSet key, Copernicus variable name, category (phys/bgc), and Parcels particle variable name(s).
    • Per-instrument parcticle classes are now built dynamically at runtime based on which sensors are active, but the fixed/mechanical variables are still hard-coded in the instrument files, e.g. cycle_phase for Argo Floats.

API change

As mentioned above, the instruments config section of the expedition YAML now has a sensors list field, where users specify which sensors are active. For example, below the CTD is configured to sample TEMPERATURE and SALINITY:

ctd_config:
stationkeeping_time_minutes: 50min_depth_meter: -11max_depth_meter: -2000sensors:
- TEMPERATURE
- SALINITY
  • If the sensors list is omitted, it default to all valid sensors for that instrument.
  • By using allowlists for each instrument, it will not allow non-sensical sensor combinations (e.g. BGC sensors on an ADCP).
  • Will also not allow an empty sensor list, at least one sensor must be active.

Additional change

  • Argo Float sampling kernels have been separated from the vertical-movement kernel, making it easier to add BGC sensors in a future PR.

Follow-up PRs

  • The plan CLI tool will need updating to account for sensor configuration options. Currently not broken but doesn't give option to configure sensors. (New issue to be opened)
  • Docs update to clearly communicate which sensors each instrument accepts, and how to configure them in either the plan tool or the expedition YAML. (New issue to be opened)
  • Merge CTD + CTD_BGC into a single instrument. (Unify CTD and CTD_BGC to one instrument #260)
  • Add BGC sampling to Argo Floats (New ARGO_BGC instrument #234)

Tests

  • Update existing tests and add new tests to cover new sensor logic

… kernels from the argo vertical movement kernel to enable easier scalability
@j-atkins

Copy link
Copy Markdown
CollaboratorAuthor

I have addressed various comments from the first round of review on this PR. See below for a list of main changes:

  • Renamed all _*_FIXED_VARIABLES lists to _*_NONSENSOR_VARIABLES
  • Renamed _SensorMeta to _Sensor, added type_: SensorType as a field so each sensor object is self-describing, and moved the class + SENSOR_REGISTRY from utils.py into sensors.py
  • New _InstrumentConfigMixin in expedition.py defines shared methods that can be flexibly inherited across the InstrumentConfig models, addresses duplication flagged.
    • Note, though, also that this logic has been extended to other preexisting datetime related parts of the InstrumetConfigs, e.g. minutes and lifetime params (so this is some 'bonus' refactoring).
    • The tests associated with each method are maintained and a new test added to test_expedition.py to check that all InstrumentConfig models inherit from the mixin.
  • Instrument subclasses (e.g. CTDInstrument) must now define sensor_kernel dictionary to map the sensor types to the relevant sampling kernels as a class attribute. This is checked by the Instrument base class and also a test added to test_base.py. Means the allowlists for different sensor types are now explicitly defined and managed within each instrument class, which is nice for further centralising instrument characteristics and behaviours.

@j-atkins
j-atkins merged commit 47f4ab8 into mainMay 1, 2026
11 checks passed
@j-atkins
j-atkins deleted the refactor-sensors branch May 1, 2026 13:24
Sign up for freeto 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.

3 participants

@j-atkins@erikvansebille@VeckoTheGecko
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor: instruments have sensors - #328

Merged
j-atkins merged 79 commits into
mainfrom
refactor-sensors
May 1, 2026
Merged

Refactor: instruments have sensors#328
j-atkins merged 79 commits into
mainfrom
refactor-sensors

Conversation

@j-atkins

@j-atkinsj-atkins commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR centralises/abstracts instrument sensor/variable sampling logic so that each instrument declares which sensors it carries (e.g. TEMPERATURE, SALINITY, VELOCITY). Users can configure which sensors are active for each instrument in the expedition YAML.

This helps pave the way for easy addition of BGC sensors to the Argo float in a future PR (#234), and consolidation of CTD + CTD_BGC into a single instrument (#260) with a combined sensor allowlist. Also makes it straightforward to add new sensors to any instrument in the future (e.g., #312, #313), and streamlines them process for developers to add new instruments (i.e. #237)

Major changes

  • sensors.py in instruments/ defines the SensorType class and per-instrument allowlists (so that there is control over which sensors each instrument supports and users cannot configure unsupported sensors).
  • New SensorConfig pydantic model and sensors field in every instrument config in expedition.py.
  • New SensorRegistry in utils.py that maps each SensorType to its FieldSet key, Copernicus variable name, category (phys/bgc), and Parcels particle variable name(s).
    • Per-instrument parcticle classes are now built dynamically at runtime based on which sensors are active, but the fixed/mechanical variables are still hard-coded in the instrument files, e.g. cycle_phase for Argo Floats.

API change

As mentioned above, the instruments config section of the expedition YAML now has a sensors list field, where users specify which sensors are active. For example, below the CTD is configured to sample TEMPERATURE and SALINITY:

ctd_config:
stationkeeping_time_minutes: 50min_depth_meter: -11max_depth_meter: -2000sensors:
- TEMPERATURE
- SALINITY
  • If the sensors list is omitted, it default to all valid sensors for that instrument.
  • By using allowlists for each instrument, it will not allow non-sensical sensor combinations (e.g. BGC sensors on an ADCP).
  • Will also not allow an empty sensor list, at least one sensor must be active.

Additional change

  • Argo Float sampling kernels have been separated from the vertical-movement kernel, making it easier to add BGC sensors in a future PR.

Follow-up PRs

  • The plan CLI tool will need updating to account for sensor configuration options. Currently not broken but doesn't give option to configure sensors. (New issue to be opened)
  • Docs update to clearly communicate which sensors each instrument accepts, and how to configure them in either the plan tool or the expedition YAML. (New issue to be opened)
  • Merge CTD + CTD_BGC into a single instrument. (Unify CTD and CTD_BGC to one instrument #260)
  • Add BGC sampling to Argo Floats (New ARGO_BGC instrument #234)

Tests

  • Update existing tests and add new tests to cover new sensor logic

… kernels from the argo vertical movement kernel to enable easier scalability
@j-atkins

Copy link
Copy Markdown
CollaboratorAuthor

I have addressed various comments from the first round of review on this PR. See below for a list of main changes:

  • Renamed all _*_FIXED_VARIABLES lists to _*_NONSENSOR_VARIABLES
  • Renamed _SensorMeta to _Sensor, added type_: SensorType as a field so each sensor object is self-describing, and moved the class + SENSOR_REGISTRY from utils.py into sensors.py
  • New _InstrumentConfigMixin in expedition.py defines shared methods that can be flexibly inherited across the InstrumentConfig models, addresses duplication flagged.
    • Note, though, also that this logic has been extended to other preexisting datetime related parts of the InstrumetConfigs, e.g. minutes and lifetime params (so this is some 'bonus' refactoring).
    • The tests associated with each method are maintained and a new test added to test_expedition.py to check that all InstrumentConfig models inherit from the mixin.
  • Instrument subclasses (e.g. CTDInstrument) must now define sensor_kernel dictionary to map the sensor types to the relevant sampling kernels as a class attribute. This is checked by the Instrument base class and also a test added to test_base.py. Means the allowlists for different sensor types are now explicitly defined and managed within each instrument class, which is nice for further centralising instrument characteristics and behaviours.

@j-atkins
j-atkins merged commit 47f4ab8 into mainMay 1, 2026
11 checks passed
@j-atkins
j-atkins deleted the refactor-sensors branch May 1, 2026 13:24
Sign up for freeto 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.

3 participants

@j-atkins@erikvansebille@VeckoTheGecko
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Refactor: instruments have sensors - #328

Merged
j-atkins merged 79 commits into
mainfrom
refactor-sensors
May 1, 2026
Merged

Refactor: instruments have sensors#328
j-atkins merged 79 commits into
mainfrom
refactor-sensors

Conversation

@j-atkins

@j-atkinsj-atkins commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR centralises/abstracts instrument sensor/variable sampling logic so that each instrument declares which sensors it carries (e.g. TEMPERATURE, SALINITY, VELOCITY). Users can configure which sensors are active for each instrument in the expedition YAML.

This helps pave the way for easy addition of BGC sensors to the Argo float in a future PR (#234), and consolidation of CTD + CTD_BGC into a single instrument (#260) with a combined sensor allowlist. Also makes it straightforward to add new sensors to any instrument in the future (e.g., #312, #313), and streamlines them process for developers to add new instruments (i.e. #237)

Major changes

  • sensors.py in instruments/ defines the SensorType class and per-instrument allowlists (so that there is control over which sensors each instrument supports and users cannot configure unsupported sensors).
  • New SensorConfig pydantic model and sensors field in every instrument config in expedition.py.
  • New SensorRegistry in utils.py that maps each SensorType to its FieldSet key, Copernicus variable name, category (phys/bgc), and Parcels particle variable name(s).
    • Per-instrument parcticle classes are now built dynamically at runtime based on which sensors are active, but the fixed/mechanical variables are still hard-coded in the instrument files, e.g. cycle_phase for Argo Floats.

API change

As mentioned above, the instruments config section of the expedition YAML now has a sensors list field, where users specify which sensors are active. For example, below the CTD is configured to sample TEMPERATURE and SALINITY:

ctd_config:
stationkeeping_time_minutes: 50min_depth_meter: -11max_depth_meter: -2000sensors:
- TEMPERATURE
- SALINITY
  • If the sensors list is omitted, it default to all valid sensors for that instrument.
  • By using allowlists for each instrument, it will not allow non-sensical sensor combinations (e.g. BGC sensors on an ADCP).
  • Will also not allow an empty sensor list, at least one sensor must be active.

Additional change

  • Argo Float sampling kernels have been separated from the vertical-movement kernel, making it easier to add BGC sensors in a future PR.

Follow-up PRs

  • The plan CLI tool will need updating to account for sensor configuration options. Currently not broken but doesn't give option to configure sensors. (New issue to be opened)
  • Docs update to clearly communicate which sensors each instrument accepts, and how to configure them in either the plan tool or the expedition YAML. (New issue to be opened)
  • Merge CTD + CTD_BGC into a single instrument. (Unify CTD and CTD_BGC to one instrument #260)
  • Add BGC sampling to Argo Floats (New ARGO_BGC instrument #234)

Tests

  • Update existing tests and add new tests to cover new sensor logic

… kernels from the argo vertical movement kernel to enable easier scalability
@j-atkins

Copy link
Copy Markdown
CollaboratorAuthor

I have addressed various comments from the first round of review on this PR. See below for a list of main changes:

  • Renamed all _*_FIXED_VARIABLES lists to _*_NONSENSOR_VARIABLES
  • Renamed _SensorMeta to _Sensor, added type_: SensorType as a field so each sensor object is self-describing, and moved the class + SENSOR_REGISTRY from utils.py into sensors.py
  • New _InstrumentConfigMixin in expedition.py defines shared methods that can be flexibly inherited across the InstrumentConfig models, addresses duplication flagged.
    • Note, though, also that this logic has been extended to other preexisting datetime related parts of the InstrumetConfigs, e.g. minutes and lifetime params (so this is some 'bonus' refactoring).
    • The tests associated with each method are maintained and a new test added to test_expedition.py to check that all InstrumentConfig models inherit from the mixin.
  • Instrument subclasses (e.g. CTDInstrument) must now define sensor_kernel dictionary to map the sensor types to the relevant sampling kernels as a class attribute. This is checked by the Instrument base class and also a test added to test_base.py. Means the allowlists for different sensor types are now explicitly defined and managed within each instrument class, which is nice for further centralising instrument characteristics and behaviours.

@j-atkins
j-atkins merged commit 47f4ab8 into mainMay 1, 2026
11 checks passed
@j-atkins
j-atkins deleted the refactor-sensors branch May 1, 2026 13:24
Sign up for freeto 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.

3 participants

@j-atkins@erikvansebille@VeckoTheGecko
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor: instruments have sensors - #328

Merged
j-atkins merged 79 commits into
mainfrom
refactor-sensors
May 1, 2026
Merged

Refactor: instruments have sensors#328
j-atkins merged 79 commits into
mainfrom
refactor-sensors

Conversation

@j-atkins

@j-atkinsj-atkins commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR centralises/abstracts instrument sensor/variable sampling logic so that each instrument declares which sensors it carries (e.g. TEMPERATURE, SALINITY, VELOCITY). Users can configure which sensors are active for each instrument in the expedition YAML.

This helps pave the way for easy addition of BGC sensors to the Argo float in a future PR (#234), and consolidation of CTD + CTD_BGC into a single instrument (#260) with a combined sensor allowlist. Also makes it straightforward to add new sensors to any instrument in the future (e.g., #312, #313), and streamlines them process for developers to add new instruments (i.e. #237)

Major changes

  • sensors.py in instruments/ defines the SensorType class and per-instrument allowlists (so that there is control over which sensors each instrument supports and users cannot configure unsupported sensors).
  • New SensorConfig pydantic model and sensors field in every instrument config in expedition.py.
  • New SensorRegistry in utils.py that maps each SensorType to its FieldSet key, Copernicus variable name, category (phys/bgc), and Parcels particle variable name(s).
    • Per-instrument parcticle classes are now built dynamically at runtime based on which sensors are active, but the fixed/mechanical variables are still hard-coded in the instrument files, e.g. cycle_phase for Argo Floats.

API change

As mentioned above, the instruments config section of the expedition YAML now has a sensors list field, where users specify which sensors are active. For example, below the CTD is configured to sample TEMPERATURE and SALINITY:

ctd_config:
stationkeeping_time_minutes: 50min_depth_meter: -11max_depth_meter: -2000sensors:
- TEMPERATURE
- SALINITY
  • If the sensors list is omitted, it default to all valid sensors for that instrument.
  • By using allowlists for each instrument, it will not allow non-sensical sensor combinations (e.g. BGC sensors on an ADCP).
  • Will also not allow an empty sensor list, at least one sensor must be active.

Additional change

  • Argo Float sampling kernels have been separated from the vertical-movement kernel, making it easier to add BGC sensors in a future PR.

Follow-up PRs

  • The plan CLI tool will need updating to account for sensor configuration options. Currently not broken but doesn't give option to configure sensors. (New issue to be opened)
  • Docs update to clearly communicate which sensors each instrument accepts, and how to configure them in either the plan tool or the expedition YAML. (New issue to be opened)
  • Merge CTD + CTD_BGC into a single instrument. (Unify CTD and CTD_BGC to one instrument #260)
  • Add BGC sampling to Argo Floats (New ARGO_BGC instrument #234)

Tests

  • Update existing tests and add new tests to cover new sensor logic

… kernels from the argo vertical movement kernel to enable easier scalability
@j-atkins

Copy link
Copy Markdown
CollaboratorAuthor

I have addressed various comments from the first round of review on this PR. See below for a list of main changes:

  • Renamed all _*_FIXED_VARIABLES lists to _*_NONSENSOR_VARIABLES
  • Renamed _SensorMeta to _Sensor, added type_: SensorType as a field so each sensor object is self-describing, and moved the class + SENSOR_REGISTRY from utils.py into sensors.py
  • New _InstrumentConfigMixin in expedition.py defines shared methods that can be flexibly inherited across the InstrumentConfig models, addresses duplication flagged.
    • Note, though, also that this logic has been extended to other preexisting datetime related parts of the InstrumetConfigs, e.g. minutes and lifetime params (so this is some 'bonus' refactoring).
    • The tests associated with each method are maintained and a new test added to test_expedition.py to check that all InstrumentConfig models inherit from the mixin.
  • Instrument subclasses (e.g. CTDInstrument) must now define sensor_kernel dictionary to map the sensor types to the relevant sampling kernels as a class attribute. This is checked by the Instrument base class and also a test added to test_base.py. Means the allowlists for different sensor types are now explicitly defined and managed within each instrument class, which is nice for further centralising instrument characteristics and behaviours.

@j-atkins
j-atkins merged commit 47f4ab8 into mainMay 1, 2026
11 checks passed
@j-atkins
j-atkins deleted the refactor-sensors branch May 1, 2026 13:24
Sign up for freeto 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.

3 participants

@j-atkins@erikvansebille@VeckoTheGecko
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor: instruments have sensors - #328

Merged
j-atkins merged 79 commits into
mainfrom
refactor-sensors
May 1, 2026
Merged

Refactor: instruments have sensors#328
j-atkins merged 79 commits into
mainfrom
refactor-sensors

Conversation

@j-atkins

@j-atkinsj-atkins commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR centralises/abstracts instrument sensor/variable sampling logic so that each instrument declares which sensors it carries (e.g. TEMPERATURE, SALINITY, VELOCITY). Users can configure which sensors are active for each instrument in the expedition YAML.

This helps pave the way for easy addition of BGC sensors to the Argo float in a future PR (#234), and consolidation of CTD + CTD_BGC into a single instrument (#260) with a combined sensor allowlist. Also makes it straightforward to add new sensors to any instrument in the future (e.g., #312, #313), and streamlines them process for developers to add new instruments (i.e. #237)

Major changes

  • sensors.py in instruments/ defines the SensorType class and per-instrument allowlists (so that there is control over which sensors each instrument supports and users cannot configure unsupported sensors).
  • New SensorConfig pydantic model and sensors field in every instrument config in expedition.py.
  • New SensorRegistry in utils.py that maps each SensorType to its FieldSet key, Copernicus variable name, category (phys/bgc), and Parcels particle variable name(s).
    • Per-instrument parcticle classes are now built dynamically at runtime based on which sensors are active, but the fixed/mechanical variables are still hard-coded in the instrument files, e.g. cycle_phase for Argo Floats.

API change

As mentioned above, the instruments config section of the expedition YAML now has a sensors list field, where users specify which sensors are active. For example, below the CTD is configured to sample TEMPERATURE and SALINITY:

ctd_config:
stationkeeping_time_minutes: 50min_depth_meter: -11max_depth_meter: -2000sensors:
- TEMPERATURE
- SALINITY
  • If the sensors list is omitted, it default to all valid sensors for that instrument.
  • By using allowlists for each instrument, it will not allow non-sensical sensor combinations (e.g. BGC sensors on an ADCP).
  • Will also not allow an empty sensor list, at least one sensor must be active.

Additional change

  • Argo Float sampling kernels have been separated from the vertical-movement kernel, making it easier to add BGC sensors in a future PR.

Follow-up PRs

  • The plan CLI tool will need updating to account for sensor configuration options. Currently not broken but doesn't give option to configure sensors. (New issue to be opened)
  • Docs update to clearly communicate which sensors each instrument accepts, and how to configure them in either the plan tool or the expedition YAML. (New issue to be opened)
  • Merge CTD + CTD_BGC into a single instrument. (Unify CTD and CTD_BGC to one instrument #260)
  • Add BGC sampling to Argo Floats (New ARGO_BGC instrument #234)

Tests

  • Update existing tests and add new tests to cover new sensor logic

… kernels from the argo vertical movement kernel to enable easier scalability
@j-atkins

Copy link
Copy Markdown
CollaboratorAuthor

I have addressed various comments from the first round of review on this PR. See below for a list of main changes:

  • Renamed all _*_FIXED_VARIABLES lists to _*_NONSENSOR_VARIABLES
  • Renamed _SensorMeta to _Sensor, added type_: SensorType as a field so each sensor object is self-describing, and moved the class + SENSOR_REGISTRY from utils.py into sensors.py
  • New _InstrumentConfigMixin in expedition.py defines shared methods that can be flexibly inherited across the InstrumentConfig models, addresses duplication flagged.
    • Note, though, also that this logic has been extended to other preexisting datetime related parts of the InstrumetConfigs, e.g. minutes and lifetime params (so this is some 'bonus' refactoring).
    • The tests associated with each method are maintained and a new test added to test_expedition.py to check that all InstrumentConfig models inherit from the mixin.
  • Instrument subclasses (e.g. CTDInstrument) must now define sensor_kernel dictionary to map the sensor types to the relevant sampling kernels as a class attribute. This is checked by the Instrument base class and also a test added to test_base.py. Means the allowlists for different sensor types are now explicitly defined and managed within each instrument class, which is nice for further centralising instrument characteristics and behaviours.

@j-atkins
j-atkins merged commit 47f4ab8 into mainMay 1, 2026
11 checks passed
@j-atkins
j-atkins deleted the refactor-sensors branch May 1, 2026 13:24
Sign up for freeto 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.

3 participants

@j-atkins@erikvansebille@VeckoTheGecko
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Refactor: instruments have sensors - #328

Merged
j-atkins merged 79 commits into
mainfrom
refactor-sensors
May 1, 2026
Merged

Refactor: instruments have sensors#328
j-atkins merged 79 commits into
mainfrom
refactor-sensors

Conversation

@j-atkins

@j-atkinsj-atkins commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR centralises/abstracts instrument sensor/variable sampling logic so that each instrument declares which sensors it carries (e.g. TEMPERATURE, SALINITY, VELOCITY). Users can configure which sensors are active for each instrument in the expedition YAML.

This helps pave the way for easy addition of BGC sensors to the Argo float in a future PR (#234), and consolidation of CTD + CTD_BGC into a single instrument (#260) with a combined sensor allowlist. Also makes it straightforward to add new sensors to any instrument in the future (e.g., #312, #313), and streamlines them process for developers to add new instruments (i.e. #237)

Major changes

  • sensors.py in instruments/ defines the SensorType class and per-instrument allowlists (so that there is control over which sensors each instrument supports and users cannot configure unsupported sensors).
  • New SensorConfig pydantic model and sensors field in every instrument config in expedition.py.
  • New SensorRegistry in utils.py that maps each SensorType to its FieldSet key, Copernicus variable name, category (phys/bgc), and Parcels particle variable name(s).
    • Per-instrument parcticle classes are now built dynamically at runtime based on which sensors are active, but the fixed/mechanical variables are still hard-coded in the instrument files, e.g. cycle_phase for Argo Floats.

API change

As mentioned above, the instruments config section of the expedition YAML now has a sensors list field, where users specify which sensors are active. For example, below the CTD is configured to sample TEMPERATURE and SALINITY:

ctd_config:
stationkeeping_time_minutes: 50min_depth_meter: -11max_depth_meter: -2000sensors:
- TEMPERATURE
- SALINITY
  • If the sensors list is omitted, it default to all valid sensors for that instrument.
  • By using allowlists for each instrument, it will not allow non-sensical sensor combinations (e.g. BGC sensors on an ADCP).
  • Will also not allow an empty sensor list, at least one sensor must be active.

Additional change

  • Argo Float sampling kernels have been separated from the vertical-movement kernel, making it easier to add BGC sensors in a future PR.

Follow-up PRs

  • The plan CLI tool will need updating to account for sensor configuration options. Currently not broken but doesn't give option to configure sensors. (New issue to be opened)
  • Docs update to clearly communicate which sensors each instrument accepts, and how to configure them in either the plan tool or the expedition YAML. (New issue to be opened)
  • Merge CTD + CTD_BGC into a single instrument. (Unify CTD and CTD_BGC to one instrument #260)
  • Add BGC sampling to Argo Floats (New ARGO_BGC instrument #234)

Tests

  • Update existing tests and add new tests to cover new sensor logic

… kernels from the argo vertical movement kernel to enable easier scalability
@j-atkins

Copy link
Copy Markdown
CollaboratorAuthor

I have addressed various comments from the first round of review on this PR. See below for a list of main changes:

  • Renamed all _*_FIXED_VARIABLES lists to _*_NONSENSOR_VARIABLES
  • Renamed _SensorMeta to _Sensor, added type_: SensorType as a field so each sensor object is self-describing, and moved the class + SENSOR_REGISTRY from utils.py into sensors.py
  • New _InstrumentConfigMixin in expedition.py defines shared methods that can be flexibly inherited across the InstrumentConfig models, addresses duplication flagged.
    • Note, though, also that this logic has been extended to other preexisting datetime related parts of the InstrumetConfigs, e.g. minutes and lifetime params (so this is some 'bonus' refactoring).
    • The tests associated with each method are maintained and a new test added to test_expedition.py to check that all InstrumentConfig models inherit from the mixin.
  • Instrument subclasses (e.g. CTDInstrument) must now define sensor_kernel dictionary to map the sensor types to the relevant sampling kernels as a class attribute. This is checked by the Instrument base class and also a test added to test_base.py. Means the allowlists for different sensor types are now explicitly defined and managed within each instrument class, which is nice for further centralising instrument characteristics and behaviours.

@j-atkins
j-atkins merged commit 47f4ab8 into mainMay 1, 2026
11 checks passed
@j-atkins
j-atkins deleted the refactor-sensors branch May 1, 2026 13:24
Sign up for freeto 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.

3 participants

@j-atkins@erikvansebille@VeckoTheGecko