From 89eeb200fef572c18b1294b1ae5c9d6dc2727054 Mon Sep 17 00:00:00 2001 From: Shashank Budhanuru Ramaraju Date: Thu, 17 Aug 2023 16:00:44 +0100 Subject: [PATCH] review comments fixes --- .../glyphs/CanonicalGeneGlyph.ts | 127 ++++++++++-------- .../glyphs/ImplicitExonGeneGlyph.ts | 58 +------- 2 files changed, 74 insertions(+), 111 deletions(-) diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/CanonicalGeneGlyph.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/CanonicalGeneGlyph.ts index e71f569e6..236c7a89a 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/CanonicalGeneGlyph.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/CanonicalGeneGlyph.ts @@ -52,6 +52,15 @@ interface CDSFeatures { } export class CanonicalGeneGlyph extends Glyph { + /** + * Returns features as rows (Array of all child features and the parent feature at the end). + * ex: + * [ [ UTR/CDS/exon, UTR/CDS/exon, . . . , UTR/CDS/exon, mRNA/transcript ], + * [ UTR/CDS/exon, UTR/CDS/exon, . . . , UTR/CDS/exon, mRNA/transcript ] ] + * + * @param feature - Parent feature (ex: gene) + * @returns returns features for selected row + */ featuresForRow(feature: AnnotationFeatureI): AnnotationFeature[][] { const cdsFeatures: CDSFeatures[] = [] feature.children?.forEach((child: AnnotationFeatureI) => { @@ -89,6 +98,9 @@ export class CanonicalGeneGlyph extends Glyph { }) } }) + childFeatures.push({ + annotationFeature: f.parent, + }) features.push(childFeatures) }) @@ -253,85 +265,75 @@ export class CanonicalGeneGlyph extends Glyph { currentCDS += 1 }) }) + } - // hightlight selected row - if (apolloSelectedFeature) { - const featuresForRow: AnnotationFeature[][] = this.featuresForRow(feature) - let featureEntry: AnnotationFeatureI | undefined - let featureRow: number | undefined - - let i = 0 - for (const row of featuresForRow) { - for (const f of row) { - if (apolloSelectedFeature._id === f.annotationFeature._id) { - featureEntry = f.parent - featureRow = i - } - } - if (featureEntry) { - break - } - i++ - } + drawHover(stateModel: LinearApolloDisplay, ctx: CanvasRenderingContext2D) { + const { apolloHover } = stateModel + if (!apolloHover) { + return + } + const { feature } = apolloHover + if (!feature) { + return + } - if (featureEntry === undefined || featureRow === undefined) { - return - } - const widthPx = featureEntry.length / bpPerPx - const offsetPx = (featureEntry.start - feature.min) / bpPerPx - const startPx = reversed ? xOffset - widthPx : xOffset + offsetPx - const top = (row + featureRow) * rowHeight - ctx.fillStyle = theme?.palette.action.selected ?? 'rgba(0,0,0,08)' - ctx.fillRect(startPx, top, widthPx, rowHeight) + if ( + feature.discontinuousLocations && + feature.discontinuousLocations.length > 0 + ) { + feature.discontinuousLocations.forEach( + (dl: { end: number; start: number }) => { + this.drawShadeForFeature( + stateModel, + ctx, + dl.start, + dl.end, + dl.end - dl.start, + ) + }, + ) + } else { + this.drawShadeForFeature( + stateModel, + ctx, + feature.start, + feature.end, + feature.length, + ) } } - drawHover(stateModel: LinearApolloDisplay, ctx: CanvasRenderingContext2D) { - const { - apolloHover, - apolloRowHeight, - featureLayouts, - lgv, - displayedRegions, - theme, - } = stateModel + drawShadeForFeature( + stateModel: LinearApolloDisplay, + ctx: CanvasRenderingContext2D, + start: number, + end: number, + length: number, + ) { + const { apolloRowHeight, lgv, displayedRegions, theme, apolloHover } = + stateModel if (!apolloHover) { return } - const { feature, mousePosition } = apolloHover - if (!(feature && mousePosition)) { + const { mousePosition } = apolloHover + if (!mousePosition) { return } const { bpPerPx, bpToPx, offsetPx } = lgv const rowHeight = apolloRowHeight const { regionNumber, y } = mousePosition const rowNumber = Math.floor(y / rowHeight) - const layout = featureLayouts[regionNumber] - const row = layout.get(rowNumber) - let featureEntry: AnnotationFeatureI | undefined - row?.forEach(([, featureObj]) => { - featureObj.children?.forEach((f: AnnotationFeatureI) => { - f.children?.forEach((cf: AnnotationFeatureI) => { - if (feature?._id === cf._id) { - featureEntry = f - } - }) - }) - }) - if (!featureEntry) { - return - } const displayedRegion = displayedRegions[regionNumber] const { refName, reversed } = displayedRegion const startPx = (bpToPx({ refName, - coord: reversed ? featureEntry.end : featureEntry.start, + coord: reversed ? end : start, regionNumber, })?.offsetPx ?? 0) - offsetPx const top = rowNumber * rowHeight - const widthPx = featureEntry.length / bpPerPx + const widthPx = length / bpPerPx ctx.fillStyle = theme?.palette.action.focus ?? 'rgba(0,0,0,0.04)' ctx.fillRect(startPx, top, widthPx, rowHeight) } @@ -361,16 +363,25 @@ export class CanonicalGeneGlyph extends Glyph { f.end !== undefined && f.phase !== undefined ) { - if (bp >= f.start && bp <= f.end) { + if (bp >= f.start && bp <= f.end && f.parent) { featureFromLayout = f.annotationFeature } } else { - if (bp >= f.annotationFeature.start && bp <= f.annotationFeature.end) { + if ( + bp >= f.annotationFeature.start && + bp <= f.annotationFeature.end && + f.parent + ) { featureFromLayout = f.annotationFeature } } } + if (!featureFromLayout) { + featureFromLayout = + featuresForRow[featuresForRow.length - 1].annotationFeature + } + return featureFromLayout } } diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/ImplicitExonGeneGlyph.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/ImplicitExonGeneGlyph.ts index 98f7228ac..196c06237 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/ImplicitExonGeneGlyph.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/ImplicitExonGeneGlyph.ts @@ -46,6 +46,7 @@ export class ImplicitExonGeneGlyph extends Glyph { child.children?.forEach((annotationFeature: AnnotationFeatureI) => { childFeatures.push(annotationFeature) }) + childFeatures.push(child) features.push(childFeatures) }) return features @@ -156,43 +157,11 @@ export class ImplicitExonGeneGlyph extends Glyph { }) currentMRNA += 1 }) - - // hightlight selected row - if (apolloSelectedFeature) { - let featureEntry: AnnotationFeatureI | undefined - let featureRow: number | undefined - let idx = 0 - feature.children?.forEach((f: AnnotationFeatureI) => { - f.children?.forEach((cf: AnnotationFeatureI) => { - if (cf._id === apolloSelectedFeature?._id) { - featureEntry = f - featureRow = idx - } - }) - idx++ - }) - - if (featureEntry === undefined || featureRow === undefined) { - return - } - const widthPx = featureEntry.length / bpPerPx - const offsetPx = (featureEntry.start - feature.min) / bpPerPx - const startPx = reversed ? xOffset - widthPx : xOffset + offsetPx - const top = (row + featureRow) * rowHeight - ctx.fillStyle = theme?.palette.action.selected ?? 'rgba(0,0,0,08)' - ctx.fillRect(startPx, top, widthPx, rowHeight) - } } drawHover(stateModel: LinearApolloDisplay, ctx: CanvasRenderingContext2D) { - const { - apolloHover, - apolloRowHeight, - featureLayouts, - lgv, - displayedRegions, - theme, - } = stateModel + const { apolloHover, apolloRowHeight, lgv, displayedRegions, theme } = + stateModel if (!apolloHover) { return } @@ -204,33 +173,16 @@ export class ImplicitExonGeneGlyph extends Glyph { const { bpPerPx, bpToPx, offsetPx } = lgv const rowHeight = apolloRowHeight const rowNumber = Math.floor(y / rowHeight) - const layout = featureLayouts[regionNumber] - const row = layout.get(rowNumber) - - let featureEntry: AnnotationFeatureI | undefined - row?.forEach(([, featureObj]) => { - featureObj.children?.forEach((f: AnnotationFeatureI) => { - f.children?.forEach((cf: AnnotationFeatureI) => { - if (feature?._id === cf._id) { - featureEntry = f - } - }) - }) - }) - - if (!featureEntry) { - return - } const displayedRegion = displayedRegions[regionNumber] const { refName, reversed } = displayedRegion const startPx = (bpToPx({ refName, - coord: reversed ? featureEntry.end : featureEntry.start, + coord: reversed ? feature.end : feature.start, regionNumber, })?.offsetPx ?? 0) - offsetPx const top = rowNumber * rowHeight - const widthPx = featureEntry.length / bpPerPx + const widthPx = feature.length / bpPerPx ctx.fillStyle = theme?.palette.action.focus ?? 'rgba(0,0,0,0.04)' ctx.fillRect(startPx, top, widthPx, rowHeight) }