Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Choose mag when training models on multiple annotations #8266

Merged
merged 25 commits into from
Jan 7, 2025

Conversation

knollengewaechs
Copy link
Contributor

@knollengewaechs knollengewaechs commented Dec 9, 2024

URL of deployed dev instance (used for testing):

  • https://___.webknossos.xyz

Steps to test:

  • Enable jobs

  • Open an annotation and go to AI Analysis > Train a model

  • Select a ground truth and a color layer

  • Select a mag. Check that all available mags are present in both layers

  • Start a training / check network tab that the right mag was sent in the request

  • Do the same thing, but for multiple annotations. Do that by navigating to Administration > AI models > Train new model.

  • TODOs:

  • update mags after any of the input layers change

    • deselect mag
    • move value to upper component
  • find union of data and ground truth layer

    • datastructure: save map annotation id -> datalayermags, groundtruthlayermags
  • check that it works from within annotation and with multiple annotations

  • fix spacing (required vs not required fields in form, see pic)

  • address first review

  • regarding testing: does this need to be tested after the request was sent? if yes, how?

  • when opening the modal, there is a ground truth layer option for the active segmentation layer, and for the fallback layer. the first one's name is simply the tracing id, which makes it harder to understand what is happening.
    image

Issues:


(Please delete unneeded items, merge only when none are left open)

@knollengewaechs knollengewaechs self-assigned this Dec 9, 2024
Copy link
Contributor

coderabbitai bot commented Dec 9, 2024

📝 Walkthrough

Walkthrough

This pull request updates the WEBKNOSSOS application with several user-facing changes, including the introduction of a magnification selection feature for AI model training. The term "resolution" has been replaced with "magnification" throughout the codebase. Enhancements to layer naming and dataset management have been implemented, along with performance optimizations for data loading. The bounding box tool has been improved for better user feedback, and multiple bugs have been fixed. Overall, these changes enhance the functionality and usability of the application.

Changes

File Change Summary
CHANGELOG.unreleased.md Updated with new features, performance improvements, and bug fixes
frontend/javascripts/admin/voxelytics/ai_model_list_view.tsx Renamed getMagForSegmentationLayer to getMagsForSegmentationLayer and updated function return logic
frontend/javascripts/components/layer_selection.tsx Added onChange prop to layer selection components for improved interactivity
frontend/javascripts/components/mag_selection.tsx New file with MagSelectionFormItem and MagSelection components for magnification selection
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx Updated magnification handling, added MagSelectionFormItem, and modified training annotation processing

Possibly related PRs

Suggested labels

bug, frontend, documentation

Suggested reviewers

  • daniel-wer

Poem

🐰 In the world of magnification,
Layers dance with new sensation,
Hopping code, selections bright,
AI models take their flight,
WEBKNOSSOS leaps, a joyful sight! 🚀


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ca90f2 and e12ab6f.

📒 Files selected for processing (1)
  • frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: circleci_build

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@knollengewaechs knollengewaechs marked this pull request as ready for review December 16, 2024 15:31
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (5)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (5)

136-138: Remove unused parameter in getMagsForSegmentationLayer

The parameter _annotationId is not used within the getMagsForSegmentationLayer function. Consider removing it to improve code clarity.


169-169: Address TODO: Rename getMagsForSegmentationLayer method

There's a TODO comment indicating the need to rename the getMagsForSegmentationLayer method. Please rename the method to reflect its functionality accurately.

If you need assistance choosing an appropriate name, I can help suggest one.


186-186: Remove console.log statement

The console.log statement is useful for debugging but should be removed before production to avoid unnecessary console output.


414-414: Remove console.log statement

The console.log(layer); statement should be removed or replaced with proper logging if necessary.


417-417: Address TODO: Display fallback layers correctly

There's a TODO comment to fix the display of fallback layers with the correct name. Implementing this will enhance the user interface and reduce confusion.

I can assist with implementing this feature if you'd like.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7fce714 and 0dea8e5.

📒 Files selected for processing (6)
  • CHANGELOG.unreleased.md (1 hunks)
  • conf/application.conf (1 hunks)
  • frontend/javascripts/admin/voxelytics/ai_model_list_view.tsx (3 hunks)
  • frontend/javascripts/components/layer_selection.tsx (3 hunks)
  • frontend/javascripts/components/mag_selection.tsx (1 hunks)
  • frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (6 hunks)
🔇 Additional comments (5)
frontend/javascripts/components/layer_selection.tsx (1)

11-11: Enhancement: Added onChange prop to LayerSelection components

The addition of the optional onChange prop increases the flexibility of the LayerSelection and LayerSelectionFormItem components, allowing parent components to respond to selection changes.

Also applies to: 69-69, 90-90

CHANGELOG.unreleased.md (1)

16-16: Changelog updated with new feature

The addition to the changelog accurately reflects the new functionality of selecting magnifications when training AI models.

frontend/javascripts/admin/voxelytics/ai_model_list_view.tsx (2)

Line range hint 112-137: LGTM! The magnification retrieval logic is well-implemented.

The implementation correctly handles both annotation layers and segmentation layers, with proper error handling and clear separation of concerns. The use of getMagInfo ensures consistent magnification information format.


155-155: LGTM! Prop name updated consistently.

The prop name update matches the function rename, maintaining consistency throughout the component.

conf/application.conf (1)

154-155: Verify if enabling these features by default is intended.

Both jobsEnabled and voxelyticsEnabled are set to true in the default configuration. While these features are necessary for AI model training functionality:

  1. The comment above suggests using "yarn enable-jobs" for local development
  2. These features might have infrastructure dependencies that need to be properly configured first

Let's check if there are any related configuration or setup instructions:

frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx Outdated Show resolved Hide resolved
frontend/javascripts/components/mag_selection.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (3)

391-399: Consider debouncing the onChange handler.

The onChange handler triggers state updates and form field changes which could lead to performance issues if the user changes layers rapidly.

+const debouncedSetIntersectingMags = _.debounce(setIntersectingMags, 300);

 onChange={() => {
-  setIntersectingMags(
+  debouncedSetIntersectingMags(
     annotationId,
     dataset,
     form.getFieldValue(["trainingAnnotations", idx, "layerName"]),
     form.getFieldValue(["trainingAnnotations", idx, "imageDataLayer"]),
   );
   form.setFieldValue(["trainingAnnotations", idx, "mag"], undefined);
 }}

410-411: Address TODO comment regarding fallback layer names.

There's a TODO comment about fixing the display of fallback layer names. This should be addressed to improve UX.

Would you like me to help implement the fallback layer name formatting or create a GitHub issue to track this task?


427-434: Consider memoizing magInfo calculation.

The magInfo prop calculation could be memoized to prevent unnecessary recalculations during renders.

+const getMemoizedMagInfo = React.useMemo(() => {
+  if (mags != null) {
+    return mags.find((magInfoPerAnno) => magInfoPerAnno.annotationId === annotationId)?.magInfo;
+  }
+  return initialMagInfo;
+}, [mags, annotationId, initialMagInfo]);

 <MagSelectionFormItem
   name={["trainingAnnotations", idx, "mag"]}
-  magInfo={
-    mags != null
-      ? mags.find((magInfoPerAnno) => magInfoPerAnno.annotationId === annotationId)
-          ?.magInfo
-      : initialMagInfo
-  }
+  magInfo={getMemoizedMagInfo}
 />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0dea8e5 and 3f4bcaf.

📒 Files selected for processing (2)
  • frontend/javascripts/components/mag_selection.tsx (1 hunks)
  • frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/javascripts/components/mag_selection.tsx
🔇 Additional comments (2)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (2)

37-48: LGTM: Clean type imports and new component imports.

The imports are well-organized and the new imports for MagSelectionFormItem and MagInfo are properly added.


180-196: LGTM: Well-implemented intersection logic for magnification lists.

The getIntersectingMagList function correctly handles the intersection of magnifications between data and ground truth layers.

Copy link
Member

@philippotto philippotto left a comment

Choose a reason for hiding this comment

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

sorry, I started reviewing the PR a few days ago and then apparently something else grabbed my attention. I finished the review now and left a few comments.

It's cool that the mag selection seems to work 👍 however, I find the code a bit confusing. I think my main gripe with it is that mags can be null and that it is written only on certain events. In my mind, all information should be available at all times and mags could always be computed on demand (memoized if necessary). I understand that antd forms can be annoying, so maybe it doesn't work how I imagine it, but please let's have a call to discuss this :)

frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx Outdated Show resolved Hide resolved
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx Outdated Show resolved Hide resolved
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (3)

180-196: Consider using more functional programming patterns.

The function could be more concise using functional programming patterns.

-  return groundTruthLayerMags?.filter((groundTruthMag) =>
-    dataLayerMags?.find((mag) => V3.equals(mag, groundTruthMag)),
-  );
+  return groundTruthLayerMags?.filter((groundTruthMag) =>
+    dataLayerMags?.some((mag) => V3.equals(mag, groundTruthMag))
+  );

198-219: Simplify state handling logic.

The state handling in getIntersectingMags could be simplified using immutable patterns.

-    if (mags == null) {
-      return [{ annotationId, magInfo: new MagInfo(intersectingMags) }];
-    } else {
-      return mags.map((mag) =>
-        mag.annotationId === annotationId
-          ? { annotationId, magInfo: new MagInfo(intersectingMags) }
-          : mag,
-      );
-    }
+    const newMagInfo = { annotationId, magInfo: new MagInfo(intersectingMags) };
+    return mags?.map(mag => 
+      mag.annotationId === annotationId ? newMagInfo : mag
+    ) ?? [newMagInfo];

412-413: Address the TODO comment about fallback layer names.

The comment indicates a need to improve the display of fallback layer names.

Would you like me to help implement the fallback layer name formatting or create a GitHub issue to track this task?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4bcaf and 420f648.

📒 Files selected for processing (1)
  • frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (6 hunks)
🔇 Additional comments (4)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (4)

137-139: Add error handling for missing segmentation layer.

The function assumes the segmentation layer will always be found.


161-161: LGTM: Clear and purposeful type definition.

The type effectively combines annotation ID with magnification information.


229-232: Add null check for layer resolutions.

The getMagsForColorLayer function should validate that the layer has resolutions before accessing them.


420-428: LGTM: Well-structured form component integration.

The MagSelectionFormItem integration is clean and handles both initial and updated states correctly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (3)

185-185: Remove console.log statement.

Debug logging should not be present in production code.

-      console.log("getIntersectingMags");

337-339: Extract common layer change handler.

The same layer change handler is duplicated across color layer and ground truth layer selections. Consider extracting it to a shared function.

+const handleLayerChange = (form: FormInstance, idx: number) => {
+  form.setFieldValue(["trainingAnnotations", idx, "mag"], undefined);
+};

 const onChangeLayer = () => {
-  form.setFieldValue(["trainingAnnotations", idx, "mag"], undefined);
+  handleLayerChange(form, idx);
 };

Also applies to: 371-371, 387-388


382-383: Address the TODO comment about fallback layer names.

The TODO indicates that fallback layers need better naming representation in the UI. This could impact user experience as it may be difficult for users to identify the correct layer.

Would you like me to help implement a solution for displaying fallback layer names in a more user-friendly format? I can help create a function that formats the layer names appropriately or open a GitHub issue to track this task.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 420f648 and 3da8f49.

📒 Files selected for processing (1)
  • frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (5 hunks)
🔇 Additional comments (1)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (1)

137-139: ⚠️ Potential issue

Add error handling for missing segmentation layer.

The function assumes the segmentation layer will always be found. Consider adding error handling for cases where the layer might not exist.

 const getMagsForSegmentationLayer = (_annotationId: string, layerName: string) => {
   const segmentationLayer = getSegmentationLayerByHumanReadableName(dataset, tracing, layerName);
+  if (!segmentationLayer) {
+    throw new Error(`Segmentation layer "${layerName}" not found`);
+  }
   return getMagInfo(segmentationLayer.resolutions);
 };

Likely invalid or redundant comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (3)

208-224: Consider memoizing the intersection calculation.

The getIntersectingMagList function performs filtering operations that could benefit from memoization to prevent unnecessary recalculations.

Consider wrapping the function with useMemo:

-const getIntersectingMagList = (
+const getIntersectingMagList = React.useMemo(() => (
   annotationId: string,
   dataset: APIDataset,
   groundTruthLayerName: string,
   imageDataLayerName: string,
 ) => {
   const colorLayers = getColorLayers(dataset);
   const dataLayerMags = getMagsForColorLayer(colorLayers, imageDataLayerName);
   const groundTruthLayerMags = getMagsForSegmentationLayer(
     annotationId,
     groundTruthLayerName,
   ).getMagList();

   return groundTruthLayerMags?.filter((groundTruthMag) =>
     dataLayerMags?.find((mag) => V3.equals(mag, groundTruthMag)),
   );
-};
+}, [dataset, getMagsForSegmentationLayer]);

385-386: Address TODO comment regarding fallback layers.

There's a TODO comment about fixing the display of fallback layer names.

Would you like me to help implement the fallback layer name formatting? I can propose a solution that includes the active layer status in the display name.


394-401: Simplify conditional rendering of magInfo.

The conditional rendering of magInfo can be simplified using nullish coalescing.

Apply this diff:

-                magInfo={
-                  magInfoPerLayer != null && magInfoPerLayer[idx] != null
-                    ? magInfoPerLayer[idx]
-                    : new MagInfo([])
-                }
+                magInfo={magInfoPerLayer?.[idx] ?? new MagInfo([])}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3da8f49 and 88581c6.

📒 Files selected for processing (1)
  • frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (5 hunks)
🔇 Additional comments (4)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (4)

37-49: LGTM: Import statements and type definitions are well-organized.

The new imports for MagSelectionFormItem and MagInfo are properly added, and the API types are correctly imported.


340-342: 🛠️ Refactor suggestion

Extract duplicate onChange handler.

The onChangeLayer handler is duplicated in multiple places. Consider extracting it to a reusable function.

Apply this diff:

+const createLayerChangeHandler = (form: FormInstance, idx: number) => () => {
+  form.setFieldValue(["trainingAnnotations", idx, "mag"], undefined);
+};

-const onChangeLayer = () => {
-  form.setFieldValue(["trainingAnnotations", idx, "mag"], undefined);
-};
+const onChangeLayer = createLayerChangeHandler(form, idx);

Likely invalid or redundant comment.


226-229: ⚠️ Potential issue

Add null check for layer resolutions.

The getMagsForColorLayer function should validate that the layer has resolutions before accessing them.

Apply this diff:

 const getMagsForColorLayer = (colorLayers: APIDataLayer[], layerName: string) => {
   const colorLayer = colorLayers.find((layer) => layer.name === layerName);
-  return colorLayer != null ? getMagInfo(colorLayer.resolutions).getMagList() : null;
+  return colorLayer?.resolutions ? getMagInfo(colorLayer.resolutions).getMagList() : null;
 };

Likely invalid or redundant comment.


137-139: ⚠️ Potential issue

Add error handling for missing segmentation layer.

The function assumes the segmentation layer will always be found. Consider adding error handling for cases where the layer might not exist.

Apply this diff:

 const getMagsForSegmentationLayer = (_annotationId: string, layerName: string) => {
   const segmentationLayer = getSegmentationLayerByHumanReadableName(dataset, tracing, layerName);
+  if (!segmentationLayer) {
+    throw new Error(`Segmentation layer "${layerName}" not found`);
+  }
   return getMagInfo(segmentationLayer.resolutions);
 };

Likely invalid or redundant comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (3)

183-207: Consider extracting the watcher logic into a custom hook.

The watcher logic is complex and could be more maintainable if extracted into a custom hook. This would improve reusability and make the component's logic clearer.

Consider creating a custom hook like this:

function useMagInfoWatcher(form: FormInstance, annotationInfos: AnnotationInfoForAIJob[]) {
  const watcherFn = useCallback(() => {
    const getIntersectingMags = (idx: number, annotationId: string, dataset: APIDataset) => {
      const segmentationLayerName = form.getFieldValue(["trainingAnnotations", idx, "layerName"]);
      const imageDataLayerName = form.getFieldValue(["trainingAnnotations", idx, "imageDataLayer"]);
      if (segmentationLayerName != null && imageDataLayerName != null) {
        return new MagInfo(
          getIntersectingMagList(annotationId, dataset, segmentationLayerName, imageDataLayerName),
        );
      }
      return new MagInfo([]);
    };

    return annotationInfos.map((annotationInfo, idx: number) => {
      const annotation = annotationInfo.annotation;
      const annotationId = "id" in annotation ? annotation.id : annotation.annotationId;
      return getIntersectingMags(idx, annotationId, annotationInfo.dataset);
    });
  }, [form, annotationInfos]);

  return Form.useWatch(watcherFn, form);
}

386-387: Address the TODO comment about fallback layer names.

The comment indicates that fallback layers need proper naming in the UI. This should be addressed to improve user experience.

Would you like me to help implement the fallback layer naming logic or create a GitHub issue to track this task?


341-343: Extract duplicate onChange handler logic.

The same onChange handler logic is duplicated. Consider extracting it into a shared function.

Apply this diff to remove the duplication:

+const createLayerChangeHandler = (form: FormInstance, idx: number) => () => {
+  form.setFieldValue(["trainingAnnotations", idx, "mag"], undefined);
+};

-const onChangeLayer = () => {
-  form.setFieldValue(["trainingAnnotations", idx, "mag"], undefined);
-};

<LayerSelection
  layers={colorLayers}
  getReadableNameForLayer={(layer) => layer.name}
  fixedLayerName={fixedSelectedColorLayer?.name || undefined}
  style={{ width: "100%" }}
-  onChange={onChangeLayer}
+  onChange={createLayerChangeHandler(form, idx)}
/>

<LayerSelectionFormItem
  name={["trainingAnnotations", idx, "layerName"]}
  chooseSegmentationLayer
  layers={segmentationLayers}
  getReadableNameForLayer={(layer) => layer.name}
  fixedLayerName={fixedSelectedSegmentationLayer?.name || undefined}
  label="Ground Truth Layer"
-  onChange={onChangeLayer}
+  onChange={createLayerChangeHandler(form, idx)}
/>

Also applies to: 391-391

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 88581c6 and 0e692b4.

📒 Files selected for processing (2)
  • CHANGELOG.unreleased.md (1 hunks)
  • frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.unreleased.md
🔇 Additional comments (3)
frontend/javascripts/oxalis/view/jobs/train_ai_model.tsx (3)

Line range hint 501-600: LGTM! Comprehensive validation logic.

The validation functions for annotations and bounding boxes are well-implemented with thorough checks and clear error messages.


229-232: ⚠️ Potential issue

Add null check for layer resolutions.

The getMagsForColorLayer function should validate that the layer has resolutions before accessing them.

Apply this diff to add validation:

 const getMagsForColorLayer = (colorLayers: APIDataLayer[], layerName: string) => {
   const colorLayer = colorLayers.find((layer) => layer.name === layerName);
-  return colorLayer != null ? getMagInfo(colorLayer.resolutions).getMagList() : null;
+  return colorLayer?.resolutions ? getMagInfo(colorLayer.resolutions).getMagList() : null;
 };

Likely invalid or redundant comment.


137-139: ⚠️ Potential issue

Add error handling for missing segmentation layer.

The function assumes the segmentation layer will always be found. Consider adding error handling for cases where the layer might not exist.

Apply this diff to add error handling:

 const getMagsForSegmentationLayer = (_annotationId: string, layerName: string) => {
   const segmentationLayer = getSegmentationLayerByHumanReadableName(dataset, tracing, layerName);
+  if (!segmentationLayer) {
+    throw new Error(`Segmentation layer "${layerName}" not found`);
+  }
   return getMagInfo(segmentationLayer.resolutions);
 };

Likely invalid or redundant comment.

@knollengewaechs
Copy link
Contributor Author

I think I addressed all the feedback for now 🤞 From my side an open question that is left is how to handle volume annotation layer names (=tracing ids from what I understand) in the selection. Maybe something like this?
image

…n-readable layer names should be used instead
@knollengewaechs knollengewaechs enabled auto-merge (squash) January 7, 2025 09:57
@knollengewaechs knollengewaechs merged commit 6b36e40 into master Jan 7, 2025
3 checks passed
@knollengewaechs knollengewaechs deleted the multi-anno-trainings-choose-mag branch January 7, 2025 10:03
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