Skip to content

[ENH] Fetch imaging modality options from an API endpoint#684

Merged
rmanaem merged 19 commits into
mainfrom
enh-643
Dec 11, 2025
Merged

[ENH] Fetch imaging modality options from an API endpoint#684
rmanaem merged 19 commits into
mainfrom
enh-643

Conversation

@rmanaem
Copy link
Copy Markdown
Contributor

@rmanaem rmanaem commented Dec 5, 2025

Changes proposed in this pull request:

  • Added imaging modality-specific types (ImagingModalityOption, ImagingModalitiesMetadata) and a generic AttributeResponse
  • Extended the shared attribute fetch helper in App to pull the imaging-modalities endpoint with DataType/Abbreviation casing.
  • Built the imaging modality metadata map from the API with both prefixed TermURL and full IRI keys to resemble the old hard-coded modalities structure
  • Introduced a data type to color mapping to replace the old hardcoded modality list in constants
  • Updated ResultContainer and ResultCard to consume API-driven modality metadata for labels/abbreviations/colors and to skip modalities missing DataType or Abbreviation
  • Expanded mocks with imaging modality success/empty/partial/failure responses and added intercepts for /imaging-modalities in relevant component and e2e tests
  • Added assertions for imaging modality notifications (info/warning/error)APIRequests e2e suite
  • Ensured modality chips render from API metadata in ResultCard and ResultContainer component tests

Checklist

This section is for the PR reviewer

  • PR has an interpretable title with a prefix ([ENH], [FIX], [REF], [TST], [CI], [MNT], [INF], [MODEL], [DOC]) (see our Contributing Guidelines for more info)
  • PR has a label for the release changelog or skip-release (to be applied by maintainers only)
  • PR links to GitHub issue with mention Closes #XXXX
  • Tests pass
  • Checks pass
  • If the PR changes the participant-level and/or the dataset-level result file, the query-tool-results files in the neurobagel_examples repo have been regenerated

For new features:

  • Tests have been added

For bug fixes:

  • There is at least one test that would fail under the original bug conditions.

Summary by Sourcery

Fetch imaging modality options and metadata from a new API endpoint instead of hardcoded constants, and propagate this data through the query form and results views.

New Features:

  • Load imaging modality options and metadata from an /imaging-modalities API endpoint and surface them in the query form for filtering.
  • Provide API-driven imaging modality labels, abbreviations, and colors in result cards and containers using a data type–to–color mapping.

Enhancements:

  • Generalize the shared attribute-fetching helper to support typed responses, configurable label filtering, and imaging modality–specific notifications.
  • Replace the static imaging modalities constant with a data-type-to-color mapping and metadata lookup keyed by both prefixed and full IRIs.

Tests:

  • Extend Cypress e2e and component tests with mocks and assertions for imaging modality API responses, notifications, and rendered modality chips in the results and TSV flows.

@rmanaem rmanaem added the pr-minor-breaking Feature or enhancement that breaks compatibility, will increment minor version (0.+1.0) label Dec 5, 2025
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Dec 5, 2025

Reviewer's Guide

Replaces the hard-coded imaging modality list with data-driven options fetched from a new /imaging-modalities API endpoint, plumbs modality metadata through App → QueryForm/ResultContainer/ResultCard, and extends tests and fixtures to cover the new behavior and notifications for success/empty/partial/failure cases.

Sequence diagram for fetching imaging modalities and rendering chips

sequenceDiagram
  participant App
  participant axios
  participant Snackbar as NotificationSystem
  participant QueryForm
  participant ResultContainer
  participant ResultCard

  App->>App: useEffect()
  App->>App: getAttributes(imaging-modalities, nb:Image, onSuccess)
  App->>axios: GET baseAPIURL + imaging-modalities
  axios-->>App: AttributeResponse_ImagingModalityOption_

  alt nodes_response_status == fail
    App->>Snackbar: enqueueSnackbar("Failed to retrieve imaging-modalities options", error)
    App-->>App: return
  else nodes_response_status != fail
    App->>App: record warning notifications for errors[]
    App->>App: items = responses[nb:Image]
    alt items is empty or undefined
      App->>Snackbar: add info notification "No imaging modalities options were available"
    else items nonempty
      App->>App: filter items with null Label (if removeMissingLabels)
      App->>App: build ImagingModalitiesMetadata map
      App->>App: setImagingModalityOptions(items)
      App->>App: setImagingModalitiesMetadata(map)
    end
  end

  App-->>QueryForm: props.imagingModalityOptions
  App-->>ResultContainer: props.imagingModalitiesMetadata

  QueryForm->>QueryForm: render CategoricalField "Imaging modality" using imagingModalityOptions

  ResultContainer->>ResultCard: pass imagingModalitiesMetadata and imageModals
  ResultCard->>ResultCard: filter imageModals with valid metadata (DataType, Abbreviation)
  ResultCard->>ResultCard: lookup color via modalitiesDataTypeColorMapping[DataType]
  ResultCard->>ResultCard: render modality chips with Abbreviation or Label
Loading

File-Level Changes

Change Details Files
Generalize attribute fetching helper and add support for imaging modality options and metadata in the main app state.
  • Refactored getAttributes into a generic helper that accepts a success callback and optional removeMissingLabels flag while preserving notification behavior for failures, partial successes, empty responses, and missing labels.
  • Introduced AttributeResponse type and ImagingModalityOption/ImagingModalitiesMetadata interfaces to model imaging modality responses and metadata maps.
  • Added imagingModalityOptions and imagingModalitiesMetadata state in App, fetching nb:Image from the imaging-modalities endpoint and building a metadata map keyed by both prefixed TermURL and full IRI.
  • Adjusted pipeline fetching to use the new generic helper without stripping null labels.
src/App.tsx
src/utils/types.ts
Replace hard-coded modality definitions with a data-type-to-color mapping and render modality chips based on API metadata.
  • Removed the static modalities map and added modalitiesDataTypeColorMapping keyed by BIDS-like DataType abbreviations.
  • Updated ResultCard to derive modality visibility, label/abbreviation, and chip color from imagingModalitiesMetadata and the new color mapping, skipping entries missing DataType or Abbreviation.
  • Changed ResultContainer to use imagingModalitiesMetadata to resolve human-readable modality labels from URIs, and plumb this metadata into ResultCard.
  • Propagated imaging modality options into QueryForm to populate the Imaging modality categorical field from API data rather than constants.
src/utils/constants.ts
src/components/ResultCard.tsx
src/components/ResultContainer.tsx
src/components/QueryForm.tsx
Extend Cypress fixtures and tests to cover imaging modality API behavior and UI rendering.
  • Added imaging modality fixtures for success, empty, partial, and failed responses, including nodes_response_status and error payloads.
  • Hooked /imaging-modalities intercepts into existing APIRequests, ResultsTSV, Auth, and other E2E suites, adding waits for the new alias and assertions for info/warning/error notifications specific to imaging modalities.
  • Updated component tests for ResultCard and ResultContainer to provide imagingModalitiesMetadata props and assert correct chip labels/colors and behavior with unknown modalities.
  • Updated QueryForm component tests to pass imagingModalityOptions props and ensure the imaging modality field renders options from the API-driven list.
cypress/fixtures/mocked-responses.ts
cypress/e2e/APIRequests.cy.ts
cypress/e2e/ResultsTSV.cy.ts
cypress/e2e/Auth.cy.ts
cypress/component/ResultCard.cy.tsx
cypress/component/ResultContainer.cy.tsx
cypress/component/QueryForm.cy.tsx

Assessment against linked issues

Issue Objective Addressed Explanation
#643 Replace the hardcoded imaging modality list with data fetched from the imaging-modalities API (nb:Image), storing full modality metadata (Label, TermURL, Abbreviation, DataType) and using this metadata (via TermURL/IRI keys) throughout the UI and download/label-conversion logic.
#643 Color-code imaging modalities based on their BIDS DataType using a deterministic palette (with a defined fallback when DataType is missing) and apply these colors to modality chips in result cards while preserving existing hover/disabled styling behavior. The PR introduces a deterministic DataType → color map and applies it to modality chips, preserving the hover behavior, but there is no fallback when DataType is missing. Instead, modalities without DataType or Abbreviation are filtered out and not rendered at all, so modalities lacking DataType do not get a fallback color as requested.
#643 Update tests to reflect the new API-driven imaging modality behavior, including notifications and TSV/download behavior.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@netlify
Copy link
Copy Markdown

netlify Bot commented Dec 5, 2025

Deploy Preview for neurobagel-query ready!

Name Link
🔨 Latest commit 9eb2cd5
🔍 Latest deploy log https://app.netlify.com/projects/neurobagel-query/deploys/693b15b726e8380008a51a2a
😎 Deploy Preview https://deploy-preview-684--neurobagel-query.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

We've reviewed this pull request using the Sourcery rules engine

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR transitions the imaging modality options from hardcoded constants to a dynamic API-driven approach, fetching modality metadata from a new /imaging-modalities endpoint. The changes enable more flexible and maintainable imaging modality management by allowing the backend to control available options and their metadata.

Key changes:

  • Introduced new types (ImagingModalityOption, ImagingModalitiesMetadata, generic AttributeResponse<T>) to support imaging modality metadata with DataType and Abbreviation fields
  • Replaced the hardcoded modalities constant with a modalitiesDataTypeColorMapping that maps BIDS data types to colors, enabling API-driven modality metadata while preserving color associations
  • Enhanced the shared getAttributes helper function to be generic and support configurable label filtering, allowing it to handle imaging modalities alongside diagnoses, assessments, and pipelines

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/utils/types.ts Added ImagingModalityOption extending AttributeOption with optional Abbreviation and DataType fields; added ImagingModalitiesMetadata map type and generic AttributeResponse<T>
src/utils/constants.ts Replaced the hardcoded modalities object with modalitiesDataTypeColorMapping that maps BIDS data types to colors
src/App.tsx Generalized getAttributes function to support typed responses and configurable label filtering; added imaging modality fetch with metadata map construction keyed by both prefixed and full IRI formats
src/components/QueryForm.tsx Updated to consume imagingModalityOptions from API instead of hardcoded modalities constant
src/components/ResultContainer.tsx Updated modality label lookup to use API-driven imagingModalitiesMetadata map
src/components/ResultCard.tsx Refactored modality chip rendering to use API metadata for labels/abbreviations, filter out incomplete metadata, and apply colors based on DataType mapping
cypress/fixtures/mocked-responses.ts Added comprehensive mock responses for imaging modalities including success, empty, partial failure, and complete failure scenarios
cypress/e2e/ResultsTSV.cy.ts Added imaging modality API intercepts and wait conditions
cypress/e2e/Auth.cy.ts Added imaging modality API intercepts to authentication flow tests
cypress/e2e/APIRequests.cy.ts Added comprehensive test coverage for imaging modality API responses including empty, partial failure, and failure cases with notification assertions
cypress/component/ResultContainer.cy.tsx Updated all test cases to provide imagingModalitiesMetadata prop
cypress/component/ResultCard.cy.tsx Updated test fixtures with imaging modality metadata and verified correct color rendering based on DataType
cypress/component/QueryForm.cy.tsx Updated to provide imagingModalityOptions prop in all test cases

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/components/ResultCard.tsx
Comment thread src/components/ResultCard.tsx
Comment thread src/components/ResultCard.tsx
Comment thread src/components/ResultContainer.tsx
Comment thread src/utils/types.ts
Comment thread src/components/ResultCard.tsx
Comment thread src/App.tsx Outdated
Copy link
Copy Markdown
Contributor

@surchs surchs left a comment

Choose a reason for hiding this comment

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

Thanks @rmanaem. It seems you have inconsistent type requirements between AttributeOption (requires Label) and getAttributes (optional Label / can be null).

Could you take a look at that before merging please. also left a couple of other comments.

Sidenote: preview does not work in this case because it's testing against fAPI that does not return the expected imaging data. This is a bigger problem but would be good to come up with some ideas for how to address this (i.e. preview build against staging rather than production)

I'm approving with the above changes
🧑‍🍳

Comment thread src/utils/constants.ts Outdated
Comment thread src/utils/constants.ts Outdated
Comment thread src/App.tsx Outdated
Comment thread src/App.tsx
Comment thread src/App.tsx
Comment thread src/App.tsx
Comment thread src/App.tsx Outdated
@alyssadai alyssadai added the release Create a release when this PR is merged label Dec 11, 2025
@rmanaem rmanaem merged commit 3cebf02 into main Dec 11, 2025
15 checks passed
@rmanaem rmanaem deleted the enh-643 branch December 11, 2025 19:08
@neurobagel-bot
Copy link
Copy Markdown
Contributor

🚀 PR was released in v0.14.0 🚀

@neurobagel-bot neurobagel-bot Bot added the released This issue/pull request has been released. label Dec 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-minor-breaking Feature or enhancement that breaks compatibility, will increment minor version (0.+1.0) release Create a release when this PR is merged released This issue/pull request has been released.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fetch imaging modality options from an API endpoint instead of a using hardcoded list

4 participants