Skip to content

Commit 9b71d55

Browse files
committed
Added # Color tagging Mutation types
1 parent 1acb112 commit 9b71d55

File tree

9 files changed

+439
-63
lines changed

9 files changed

+439
-63
lines changed

app/chitra/chromosome-synteny.tsx

+302-27
Large diffs are not rendered by default.

app/chitra/page.tsx

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import React, { useState, useEffect, useRef } from 'react';
3+
import React, { useState, useEffect, useRef, useCallback } from 'react';
44
import { ChromosomeSynteny } from './chromosome-synteny';
55
import { MultiSelect } from '@/components/ui/multi-select';
66
import { Button } from "@/components/ui/button";
@@ -83,6 +83,7 @@ import { FileUploaderGroup } from "@/components/chromoviz/file-uploader";
8383
import { config } from 'process';
8484
import { TipsCarousel } from "@/components/chromoviz/tips-carousel";
8585
import { useRouter } from 'next/navigation';
86+
import { MutationType } from "@/components/chromoviz/synteny-ribbon";
8687

8788
const parseCSVRow = (d: any): any => {
8889
return {
@@ -337,6 +338,7 @@ export default function ChromoViz() {
337338
const router = useRouter();
338339
const [isAtRoot, setIsAtRoot] = useState(true);
339340
const [isDetailViewOpen, setIsDetailViewOpen] = useState(true);
341+
const [selectedMutationTypes, setSelectedMutationTypes] = useState<Map<string, MutationType>>(new Map());
340342

341343
// Initialize from localStorage
342344
useEffect(() => {
@@ -766,6 +768,18 @@ export default function ChromoViz() {
766768
setIsUsingExample(true);
767769
};
768770

771+
const handleMutationTypeSelect = useCallback((syntenyId: string, mutationType: MutationType) => {
772+
setSelectedMutationTypes(prev => {
773+
const newMap = new Map(prev);
774+
if (mutationType === undefined) {
775+
newMap.delete(syntenyId);
776+
} else {
777+
newMap.set(syntenyId, mutationType);
778+
}
779+
return newMap;
780+
});
781+
}, []);
782+
769783
if (error) {
770784
return (
771785
<div className="flex flex-col items-center justify-center min-h-[50vh] p-4">
@@ -896,6 +910,8 @@ export default function ChromoViz() {
896910
setShowAnnotations={setShowAnnotations}
897911
selectedChromosomes={selectedChromosomes}
898912
showTooltips={showTooltips}
913+
selectedMutationTypes={selectedMutationTypes}
914+
onMutationTypeSelect={handleMutationTypeSelect}
899915
/>
900916
</div>
901917
) : (

components/chromoviz/synteny-ribbon.tsx

+66-9
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ interface SyntenyRibbonProps {
2323
isSelected?: boolean;
2424
zoomBehaviorRef: React.RefObject<d3.ZoomBehavior<any, any>>;
2525
selectedChromosomes: string[];
26+
mutationType?: MutationType;
27+
useCustomColors?: boolean;
2628
}
2729

2830
const SYNTENY_COLORS = {
@@ -54,6 +56,27 @@ const COMPOSITE_STYLES = {
5456
willChange: 'transform, opacity' // Hint to browser about expected changes
5557
} as const;
5658

59+
// Add mutation type color mapping
60+
export const MUTATION_COLORS = {
61+
SYN: '#4ade80', // Green for syntenic
62+
INV: '#f87171', // Red for inversion
63+
TRANS: '#60a5fa', // Blue for translocation
64+
INVTR: '#c084fc', // Purple for inverted translocation
65+
DUP: '#fbbf24', // Yellow for duplication
66+
INVDP: '#f472b6' // Pink for inverted duplication
67+
} as const;
68+
69+
export type MutationType = keyof typeof MUTATION_COLORS;
70+
71+
// Add opacity variants for each mutation type
72+
const MUTATION_COLOR_VARIANTS = Object.entries(MUTATION_COLORS).reduce((acc, [key, color]) => ({
73+
...acc,
74+
[key]: {
75+
DEFAULT: `${color}1a`, // Light version for fill
76+
SOLID: color, // Solid version for stroke
77+
}
78+
}), {} as Record<MutationType, { DEFAULT: string; SOLID: string }>);
79+
5780
export function renderSyntenyRibbon({
5881
link,
5982
sourceSpecies,
@@ -73,6 +96,8 @@ export function renderSyntenyRibbon({
7396
isSelected = false,
7497
zoomBehaviorRef,
7598
selectedChromosomes,
99+
mutationType,
100+
useCustomColors = false,
76101
}: SyntenyRibbonProps) {
77102
// Enhanced filtering logic
78103
const shouldRenderRibbon = () => {
@@ -170,14 +195,30 @@ export function renderSyntenyRibbon({
170195
// Modify transition timing to be more stable
171196
const transition = "all 150ms cubic-bezier(0.4, 0.0, 0.2, 1)";
172197

198+
// Modify the color selection logic
199+
const getRibbonColors = () => {
200+
if (useCustomColors && mutationType) {
201+
return {
202+
fill: MUTATION_COLOR_VARIANTS[mutationType].DEFAULT,
203+
stroke: MUTATION_COLOR_VARIANTS[mutationType].SOLID
204+
};
205+
}
206+
return {
207+
fill: link.query_strand === '+' ? SYNTENY_COLORS.FORWARD : SYNTENY_COLORS.REVERSE,
208+
stroke: link.query_strand === '+' ? SYNTENY_COLORS.BLOCK_FORWARD : SYNTENY_COLORS.BLOCK_REVERSE
209+
};
210+
};
211+
212+
const colors = getRibbonColors();
213+
173214
// Source block
174215
const sourceBlock = blockGroup.append("rect")
175216
.attr("x", x1)
176217
.attr("y", sourceY)
177218
.attr("width", width1)
178219
.attr("height", chromosomeHeight)
179-
.attr("fill", link.query_strand === '+' ? SYNTENY_COLORS.FORWARD : SYNTENY_COLORS.REVERSE)
180-
.attr("stroke", link.query_strand === '+' ? SYNTENY_COLORS.BLOCK_FORWARD : SYNTENY_COLORS.BLOCK_REVERSE)
220+
.attr("fill", colors.fill)
221+
.attr("stroke", colors.stroke)
181222
.attr("stroke-width", 2)
182223
.attr("class", "matching-block source")
183224
.attr("opacity", 0.8);
@@ -188,8 +229,8 @@ export function renderSyntenyRibbon({
188229
.attr("y", targetY)
189230
.attr("width", width2)
190231
.attr("height", chromosomeHeight)
191-
.attr("fill", link.query_strand === '+' ? SYNTENY_COLORS.FORWARD : SYNTENY_COLORS.REVERSE)
192-
.attr("stroke", link.query_strand === '+' ? SYNTENY_COLORS.BLOCK_FORWARD : SYNTENY_COLORS.BLOCK_REVERSE)
232+
.attr("fill", colors.fill)
233+
.attr("stroke", colors.stroke)
193234
.attr("stroke-width", 2)
194235
.attr("class", "matching-block target")
195236
.attr("opacity", 0.8);
@@ -293,7 +334,14 @@ export function renderSyntenyRibbon({
293334

294335
const svg = d3.select(g.node().parentNode);
295336
const zoomBehavior = zoomBehaviorRef.current;
337+
338+
// Store current transform before any changes
296339
const currentTransform = d3.zoomTransform(svg.node());
340+
const currentPosition = {
341+
x: currentTransform.x,
342+
y: currentTransform.y,
343+
k: currentTransform.k
344+
};
297345

298346
const newSelectedState = !isSelected;
299347

@@ -304,14 +352,17 @@ export function renderSyntenyRibbon({
304352
blockGroup.raise();
305353
}
306354

307-
// Preserve transform
355+
// Apply the stored transform to preserve position
308356
if (zoomBehavior) {
309-
svg
310-
.transition()
311-
.duration(0)
312-
.call(zoomBehavior.transform, currentTransform);
357+
requestAnimationFrame(() => {
358+
svg.call(zoomBehavior.transform, d3.zoomIdentity
359+
.translate(currentPosition.x, currentPosition.y)
360+
.scale(currentPosition.k)
361+
);
362+
});
313363
}
314364

365+
// Ensure the group transform is preserved
315366
g.attr("transform", currentTransform.toString());
316367

317368
onSelect(link, newSelectedState);
@@ -349,5 +400,11 @@ export function renderSyntenyRibbon({
349400

350401
[ribbon, sourceBlock, targetBlock].forEach(attachEvents);
351402

403+
// Update gradient colors if using mutation type colors
404+
if (useCustomColors && mutationType) {
405+
gradient.selectAll("stop")
406+
.attr("stop-color", colors.stroke);
407+
}
408+
352409
return blockGroup;
353410
}

components/homepage/hero-section.tsx

+18-17
Original file line numberDiff line numberDiff line change
@@ -87,47 +87,47 @@ export default function HeroSection() {
8787
initial={{ opacity: 0, y: 20 }}
8888
animate={{ opacity: 1, y: 0 }}
8989
transition={{ duration: 0.7, ease: "easeOut" }}
90-
className="w-full space-y-8"
90+
className="w-full space-y-6 sm:space-y-8"
9191
>
9292
<Badge
9393
variant="outline"
94-
className="bg-blue-500/5 text-blue-600 dark:text-blue-400 text-sm font-medium px-6 py-2 rounded-full mx-auto lg:ml-0"
94+
className="bg-blue-500/5 text-blue-600 dark:text-blue-400 text-xs sm:text-sm font-medium px-3 sm:px-6 py-1.5 sm:py-2 rounded-full mx-auto lg:ml-0"
9595
>
96-
<span className="relative flex h-2 w-2 mr-2">
96+
<span className="relative flex h-1.5 sm:h-2 w-1.5 sm:w-2 mr-1.5 sm:mr-2">
9797
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
98-
<span className="relative inline-flex rounded-full h-2 w-2 bg-blue-500"></span>
98+
<span className="relative inline-flex rounded-full h-1.5 sm:h-2 w-1.5 sm:w-2 bg-blue-500"></span>
9999
</span>
100100
Visualize Chromosomal Data Like Never Before
101101
</Badge>
102102

103-
<div className="space-y-4">
104-
<h1 className="text-6xl lg:text-7xl xl:text-8xl font-bold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-gray-900 via-gray-700 to-gray-900 dark:from-white dark:via-gray-300 dark:to-white text-center lg:text-left">
103+
<div className="space-y-3 sm:space-y-4">
104+
<h1 className="text-4xl sm:text-6xl lg:text-7xl xl:text-8xl font-bold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-gray-900 via-gray-700 to-gray-900 dark:from-white dark:via-gray-300 dark:to-white text-center lg:text-left">
105105
CHITRA
106106
</h1>
107107
<div className="relative">
108108
<HyperText
109109
text="Chromosome Interactive Tool for Rearrangement Analysis"
110-
className="text-sm sm:text-base text-muted-foreground font-medium"
110+
className="text-xs sm:text-sm md:text-base text-muted-foreground font-medium"
111111
duration={1000}
112112
/>
113113
</div>
114114
</div>
115115

116-
<p className="text-xl lg:text-2xl text-muted-foreground font-light max-w-xl mx-auto lg:ml-0">
116+
<p className="text-lg sm:text-xl lg:text-2xl text-muted-foreground font-light max-w-xl mx-auto lg:ml-0">
117117
An advanced visualization tool for studying chromosomal rearrangements through interactive synteny block analysis and chromosome breakpoint mapping.
118118
</p>
119119

120-
<div className="flex flex-col sm:flex-row gap-4 pt-6 justify-center sm:justify-center lg:justify-start w-full">
120+
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4 pt-4 sm:pt-6 justify-center sm:justify-center lg:justify-start">
121121
<div className="bg-white/30 dark:bg-black/30 backdrop-blur-sm border border-white/20 dark:border-black/20
122-
rounded-full p-3 sm:p-6 shadow-lg w-full sm:w-auto">
122+
rounded-full p-2 sm:p-3 md:p-6 shadow-lg inline-flex justify-center">
123123
<motion.div
124124
initial={{ opacity: 0, y: 20 }}
125125
animate={{ opacity: 1, y: 0 }}
126126
transition={{ delay: 0.5 }}
127-
className="flex items-center justify-center gap-2 sm:gap-3 w-full"
127+
className="flex items-center justify-center gap-2 sm:gap-3"
128128
>
129-
<Link href="/chitra" className="flex-1 sm:flex-none" onClick={handleGetStarted}>
130-
<div className="relative overflow-hidden rounded-full shadow group p-0.5 w-full sm:w-auto">
129+
<Link href="/chitra" className="inline-flex" onClick={handleGetStarted}>
130+
<div className="relative overflow-hidden rounded-full shadow group p-0.5">
131131
<span className={cn(
132132
"absolute inset-[-1000%] animate-[spin_5s_linear_infinite_reverse]",
133133
"bg-[conic-gradient(from_90deg_at_50%_50%,#4f46e5_0%,#06b6d4_25%,#3b82f6_50%,#4f46e5_75%)] dark:bg-[conic-gradient(from_90deg_at_50%_50%,#1d4ed8_0%,#2563eb_25%,#3b82f6_50%,#60a5fa_75%)]"
@@ -136,12 +136,13 @@ export default function HeroSection() {
136136
variant="outline"
137137
disabled={isLoading}
138138
className={cn(
139-
"h-9 sm:h-12 px-4 sm:px-8 rounded-full font-medium w-full sm:w-auto",
139+
"h-8 sm:h-9 md:h-12 px-4 sm:px-6 md:px-8 rounded-full font-medium",
140140
"bg-white/80 dark:bg-black/80 backdrop-blur-xl",
141141
"text-zinc-800 dark:text-zinc-200",
142142
"border-0 transition-colors duration-300",
143143
"relative z-10",
144-
"text-sm sm:text-base"
144+
"text-xs sm:text-sm md:text-base",
145+
"whitespace-nowrap"
145146
)}
146147
>
147148
{isLoading ? (
@@ -175,13 +176,13 @@ export default function HeroSection() {
175176
<Button
176177
variant="outline"
177178
size="icon"
178-
className="relative h-9 sm:h-12 w-9 sm:w-12 rounded-full backdrop-blur-xl
179+
className="relative h-8 sm:h-9 md:h-12 w-8 sm:w-9 md:w-12 rounded-full backdrop-blur-xl
179180
bg-zinc-50 dark:bg-zinc-900
180181
text-zinc-800 dark:text-zinc-200
181182
border-0"
182183
>
183184
<Github className={cn(
184-
"h-4 w-4 sm:h-5 sm:w-5 transition-all duration-300",
185+
"h-3 w-3 sm:h-4 sm:w-4 md:h-5 md:w-5 transition-all duration-300",
185186
isGithubHovered && "scale-110 text-blue-500 dark:text-blue-400"
186187
)} />
187188
<span className="sr-only">GitHub Repository</span>

content/docs/example-datasets.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ CHITRA includes pre-loaded example datasets to help users explore its functional
1010
2. **Multiple Synteny**
1111
3. **Annotated Genome**
1212

13-
![](https://holocron.so/uploads/1c04fc1d-image4.png)
13+
![](public/media/image4.png)
1414

1515

1616
## Exploring Example Data

content/docs/features.mdx

+30-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ icon: SlidersHorizontalIcon
77

88
The tool is equipped with several interactive features to enhance user experience and make data visualization seamless:
99

10-
![](https://holocron.so/uploads/4bd40204-image5.png)
10+
![](public/media/image5.png)
1111

1212
1. **Zoom Option:**
1313

@@ -48,12 +48,39 @@ The tool is equipped with several interactive features to enhance user experienc
4848

4949
To visualize chromosomal breakpoints in the reference genome, users can explore the example dataset labeled **"Annotated Genome"**. This dataset includes additional information, such as annotations and chromosomal breakpoints, alongside synteny block data.
5050

51-
![](https://holocron.so/uploads/3805af96-image6.png)
51+
![](public/media/image6.png)
5252

5353
Key visualization features:
5454

5555
- **Chromosomal breakpoints** in the reference genome are shown as **red arrows** in the synteny plot
5656
- Breakpoints are highlighted in the **chord map** as **red lines** on the reference genome chord
5757
- These features enable precise identification of structural changes and their genomic locations
5858

59-
You took too much time, bye!
59+
# Color tagging Mutation types
60+
61+
CHITRA provides a color-coding to distinguish between different types of mutations and synteny relationships for the selected ribbons:
62+
63+
![](public/media/image9.png)
64+
65+
1. **Color Tags Feature:**
66+
- Located in the top navigation bar
67+
- Allows users to visually categorize and highlight different mutation types
68+
69+
2. **Available Mutation Types:**
70+
- **SYN (Green):** Syntenic regions
71+
- **INV (Red):** Inversions
72+
- **TRANS (Blue):** Translocations
73+
- **INVTR (Purple):** Inverted translocations
74+
- **DUP (Yellow):** Duplications
75+
76+
3. **How to Use:**
77+
- Click on the "Color Tags" button in the top toolbar
78+
- Select the mutation types you want to highlight
79+
- The corresponding regions in the synteny plot will be colored according to their mutation type
80+
- Multiple mutation types can be selected simultaneously for comparative analysis
81+
82+
4. **Visual Integration:**
83+
- Colors are consistently applied across both the synteny plot and chord map
84+
- Helps in quick identification and analysis of different genomic rearrangements
85+
- Enhances the understanding of complex genomic relationships
86+

content/docs/index.mdx

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Below are the step-by-step instructions, accompanied by pictorial representation
3030

3131
- On the landing page, click the “**Get Started**” button to begin.
3232

33-
![](https://holocron.so/uploads/172fd7b8-image7.png)
33+
![](public/media/image7.png)
3434

3535
#### **Step 2: Uploading Files or Viewing Example Data**
3636

@@ -58,7 +58,7 @@ _Click the_ “**Upload Data**” button. A popup window will appear where you c
5858

5959
> **Note**: All input files should be in CSV format
6060
61-
![](https://holocron.so/uploads/e04190c9-image3.png)
61+
![](public/media/image3.png)
6262

6363
### **2.1.2 Using Example Datasets**
6464

content/docs/visualization.mdx

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ icon: BarChartIcon
88

99
The tool provides an intuitive and user-friendly platform for visualizing genomic data, enabling effective exploration of DNA segments, such as chromosomes, contigs, or scaffolds, across complete genomes. Through interactive features, users can easily identify and analyze synteny blocks (common genomic regions) between species.
1010

11-
![](https://holocron.so/uploads/1fa5c687-image2.png)
11+
![](public/media/image2.png)
1212

1313
## Synteny Visualization
1414

@@ -19,7 +19,7 @@ The tool provides an intuitive and user-friendly platform for visualizing genomi
1919
- The synteny block shared between the two species
2020
- The alignment of the synteny block with the reference genome
2121

22-
![](https://holocron.so/uploads/f9af5c5d-image1.png)
22+
![](public/media/image1.png)
2323

2424

2525
## Interactive Chord Maps
@@ -30,7 +30,7 @@ Users can click on a synteny block to access a detailed chord map that provides
3030
- The size and location of the synteny block in both species
3131
- The orientation of the synteny block (forward or reverse) in the genomes
3232

33-
![](https://holocron.so/uploads/68cb0550-image5.png)
33+
![](public/media/image5.png)
3434

3535

3636
This interactive chord map allows for a deeper understanding of genomic relationships and structural variations between species.

public/media/image9.png

1.03 MB
Loading

0 commit comments

Comments
 (0)