Skip to content

Duplicate Code: Repeated Extraction Patterns in coordinates.ts #119

@github-actions

Description

@github-actions

Analysis of recent commits on main

Assignee: @copilot

Summary

Two structurally duplicated code blocks were found in fidnii/src/utils/coordinates.ts. Each block is copied verbatim into two functions, inflating the file and creating a risk of inconsistent edits.


Duplication Details

Pattern 1 — Scale/Translation Extraction

  • Severity: Low-Medium
  • Occurrences: 2
  • Locations:
    • fidnii/src/utils/coordinates.ts (lines 24–30, inside worldToPixel)
    • fidnii/src/utils/coordinates.ts (lines 56–62, inside pixelToWorld)

Duplicated block (identical in both functions):

const sx = scale.x ?? scale.X ?? 1
const sy = scale.y ?? scale.Y ?? 1
const sz = scale.z ?? scale.Z ?? 1

const tx = translation.x ?? translation.X ?? 0
const ty = translation.y ?? translation.Y ?? 0
const tz = translation.z ?? translation.Z ?? 0

Pattern 2 — Spatial Dimension Index Lookup & Validation

  • Severity: Medium
  • Occurrences: 2
  • Locations:
    • fidnii/src/utils/coordinates.ts (lines 138–154, inside normalizedToWorld)
    • fidnii/src/utils/coordinates.ts (lines 180–196, inside worldToNormalized)

Duplicated block (identical in both functions):

const yIdx = dims.indexOf("y")
const xIdx = dims.indexOf("x")

if (yIdx === -1 || xIdx === -1) {
  const missingAxes = [xIdx === -1 ? "x" : null, yIdx === -1 ? "y" : null]
    .filter((axis): axis is string => axis !== null)
    .join(", ")
  throw new Error(
    `NgffImage is missing required spatial dimension(s): \$\{missingAxes}`,
  )
}

// Look up spatial dimensions by name; default z to 1 for 2D images
const zIdx = dims.indexOf("z")
const dimZ = zIdx !== -1 ? shape[zIdx] : 1
const dimY = shape[yIdx]
const dimX = shape[xIdx]

Impact Analysis

  • Maintainability: Adding support for a new axis key convention (e.g. capitalised Z) in pattern 1 would require edits in two places. Changing the error message or 2D-fallback logic in pattern 2 similarly requires two edits.
  • Bug Risk: Divergence between the two copies could silently produce inconsistent behaviour (e.g. different fallback values or missing axis names in error messages).
  • Code Bloat: ~25 lines of redundant code in a 273-line file.

Refactoring Recommendations

1. Extract getScaleTranslation(ngffImage) helper

function getScaleTranslation(ngffImage: NgffImage): {
  sx: number; sy: number; sz: number
  tx: number; ty: number; tz: number
} {
  const { scale, translation } = ngffImage
  return {
    sx: scale.x ?? scale.X ?? 1,
    sy: scale.y ?? scale.Y ?? 1,
    sz: scale.z ?? scale.Z ?? 1,
    tx: translation.x ?? translation.X ?? 0,
    ty: translation.y ?? translation.Y ?? 0,
    tz: translation.z ?? translation.Z ?? 0,
  }
}

Replace the duplicated blocks in worldToPixel and pixelToWorld with a single call to this helper.

2. Extract getSpatialDimensions(ngffImage) helper

function getSpatialDimensions(ngffImage: NgffImage): {
  dimX: number; dimY: number; dimZ: number
} {
  const { data: { shape }, dims } = ngffImage
  const yIdx = dims.indexOf("y")
  const xIdx = dims.indexOf("x")
  if (yIdx === -1 || xIdx === -1) {
    const missingAxes = [xIdx === -1 ? "x" : null, yIdx === -1 ? "y" : null]
      .filter((axis): axis is string => axis !== null)
      .join(", ")
    throw new Error(
      `NgffImage is missing required spatial dimension(s): \$\{missingAxes}`,
    )
  }
  const zIdx = dims.indexOf("z")
  return {
    dimZ: zIdx !== -1 ? shape[zIdx] : 1,
    dimY: shape[yIdx],
    dimX: shape[xIdx],
  }
}

Replace the duplicated blocks in normalizedToWorld and worldToNormalized with a single call to this helper.


Implementation Checklist

  • Review duplication findings
  • Extract getScaleTranslation helper and update worldToPixel / pixelToWorld
  • Extract getSpatialDimensions helper and update normalizedToWorld / worldToNormalized
  • Verify TypeScript strict-mode compliance (noUnusedLocals, noUnusedParameters)
  • Run bunx tsc --noEmit and bun run check to confirm no regressions
  • Update/run existing Playwright tests to verify no behaviour change

Analysis Metadata

  • Analyzed Files: 14 TypeScript source files in fidnii/src/ and fidnii/src/utils/
  • Detection Method: Serena semantic code analysis + pattern search
  • Analysis Date: 2026-03-26

Generated by Duplicate Code Detector

To install this agentic workflow, run

gh aw add github/gh-aw/.github/workflows/duplicate-code-detector.md@33cd6c7f1fee588654ef19def2e6a4174be66197

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions