Skip to content

Commit 103a721

Browse files
authored
Merge pull request #111 from daisybio/dev
Update node/edge sizes, add interaction mscor/pval range sliders, update browse form validation
2 parents e12e92f + f1362fb commit 103a721

File tree

8 files changed

+255
-70
lines changed

8 files changed

+255
-70
lines changed

src/app/components/interactions-table/interactions-table.component.html

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,35 @@
1+
<div class="filter-container">
2+
<div class="sliders-row">
3+
<div class="slider-group">
4+
<div class="slider-header">
5+
<label>P-value Range: <span class="value-display">{{ minPValue() | number:'1.2-4' }} - {{ maxPValue() |
6+
number:'1.2-4' }}</span></label>
7+
</div>
8+
<mat-slider [min]="pValueLimits().min" [max]="pValueLimits().max" [step]="pValueLimits().step">
9+
<input [(ngModel)]="minPValue" matSliderStartThumb>
10+
<input [(ngModel)]="maxPValue" matSliderEndThumb>
11+
</mat-slider>
12+
</div>
13+
14+
<div class="slider-group">
15+
<div class="slider-header">
16+
<label>Mscor Range: <span class="value-display">{{ minMscor() | number:'1.2-4' }} - {{ maxMscor() |
17+
number:'1.2-5' }}</span></label>
18+
</div>
19+
<mat-slider [min]="mscorLimits().min" [max]="mscorLimits().max" [step]="mscorLimits().step">
20+
<input [(ngModel)]="minMscor" matSliderStartThumb>
21+
<input [(ngModel)]="maxMscor" matSliderEndThumb>
22+
</mat-slider>
23+
</div>
24+
</div>
25+
</div>
26+
127
<table [dataSource]="dataSource$()" class="mat-elevation-z8" mat-table matSort xmlns="http://www.w3.org/1999/html">
228
<ng-container matColumnDef="name_1">
329
<th *matHeaderCellDef mat-header-cell mat-sort-header>{{ capitalize(level$()) || 'Node' }} 1</th>
430
<td *matCellDef="let interaction" mat-cell>
5-
<button (click)="openDialog(interaction.obj1)" mat-button
6-
matTooltip="Show details about {{interaction.name_1}}" matTooltipPosition="right">
31+
<button (click)="openDialog(interaction.obj1)" mat-button matTooltip="Show details about {{interaction.name_1}}"
32+
matTooltipPosition="right">
733
{{ interaction.name_1 }}
834
</button>
935
</td>
@@ -12,8 +38,8 @@
1238
<ng-container matColumnDef="name_2">
1339
<th *matHeaderCellDef mat-header-cell mat-sort-header>{{ capitalize(level$() || 'Node') }} 2</th>
1440
<td *matCellDef="let interaction" mat-cell>
15-
<button (click)="openDialog(interaction.obj2)" mat-button
16-
matTooltip="Show details about {{interaction.name_2}}" matTooltipPosition="right">
41+
<button (click)="openDialog(interaction.obj2)" mat-button matTooltip="Show details about {{interaction.name_2}}"
42+
matTooltipPosition="right">
1743
{{ interaction.name_2 }}
1844
</button>
1945
</td>
@@ -22,8 +48,8 @@
2248
<ng-container matColumnDef="mirna">
2349
<th *matHeaderCellDef mat-header-cell>miRNAs</th>
2450
<td *matCellDef="let interaction" mat-cell>
25-
<button (click)="openMiRNADialog(interaction.interaction)" mat-button
26-
matTooltip="Show supporting miRNAs" matTooltipPosition="right">
51+
<button (click)="openMiRNADialog(interaction.interaction)" mat-button matTooltip="Show supporting miRNAs"
52+
matTooltipPosition="right">
2753
Show miRNAs
2854
</button>
2955
</td>
@@ -60,4 +86,4 @@
6086
<tr *matHeaderRowDef="columns" mat-header-row></tr>
6187
<tr *matRowDef="let row; columns: columns;" mat-row></tr>
6288
</table>
63-
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" [pageSize]="10" aria-label="Select page of users"></mat-paginator>
89+
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" [pageSize]="10" aria-label="Select page of users"></mat-paginator>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
.filter-container {
2+
padding: 16px;
3+
background: white;
4+
border-radius: 4px;
5+
margin-bottom: 16px;
6+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
7+
8+
.sliders-row {
9+
display: flex;
10+
gap: 32px;
11+
padding: 0 24px;
12+
max-width: 1200px;
13+
margin: 0 auto;
14+
}
15+
16+
.slider-group {
17+
flex: 1;
18+
min-width: 0; // Prevents flex items from overflowing
19+
max-width: 500px; // Limit maximum width of each slider group
20+
21+
.slider-header {
22+
margin-bottom: 8px;
23+
24+
label {
25+
font-weight: 500;
26+
margin: 0;
27+
display: flex;
28+
align-items: center;
29+
gap: 8px;
30+
}
31+
32+
.value-display {
33+
font-weight: normal;
34+
color: rgba(0, 0, 0, 0.6);
35+
}
36+
}
37+
38+
mat-slider {
39+
width: 100%;
40+
}
41+
}
42+
}

src/app/components/interactions-table/interactions-table.component.ts

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ElementRef,
77
inject,
88
input,
9+
model,
910
viewChild,
1011
ViewChild,
1112
} from '@angular/core';
@@ -21,10 +22,12 @@ import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
2122
import { MatSort, MatSortHeader } from '@angular/material/sort';
2223
import { MatButton } from '@angular/material/button';
2324
import { MatTooltip } from '@angular/material/tooltip';
25+
import { MatSliderModule } from '@angular/material/slider';
26+
import { FormsModule } from '@angular/forms';
27+
import { DecimalPipe } from '@angular/common';
2428
import { BrowseService } from '../../services/browse.service';
2529
import { capitalize } from 'lodash';
2630
import { InfoComponent } from '../info/info.component';
27-
import katex from 'katex';
2831
import { ModalsService } from '../modals-service/modals.service';
2932
import { InfoService } from '../../services/info.service';
3033

@@ -38,6 +41,9 @@ import { InfoService } from '../../services/info.service';
3841
MatButton,
3942
MatTooltip,
4043
InfoComponent,
44+
MatSliderModule,
45+
FormsModule,
46+
DecimalPipe,
4147
],
4248
templateUrl: './interactions-table.component.html',
4349
styleUrl: './interactions-table.component.scss',
@@ -54,9 +60,46 @@ export class InteractionsTableComponent implements AfterViewInit {
5460
mscorEquation$ = viewChild<ElementRef<HTMLSpanElement>>('mscorEquation');
5561
infoService = inject(InfoService);
5662
columns = ['name_1', 'name_2', 'mirna', 'correlation', 'mscor', 'padj'];
63+
64+
minPValue = model(0);
65+
maxPValue = model(1);
66+
minMscor = model(0);
67+
maxMscor = model(1);
68+
69+
// Compute data limits
70+
pValueLimits = computed(() => {
71+
const interactions = this.interactions$() || [];
72+
const pValues = interactions.map(i => i.p_value);
73+
return {
74+
min: Math.min(...pValues),
75+
max: Math.max(...pValues),
76+
step: Math.pow(10, Math.floor(Math.log10(Math.min(...pValues)))) / 10 // One decimal place smaller than smallest value
77+
};
78+
});
79+
80+
mscorLimits = computed(() => {
81+
const interactions = this.interactions$() || [];
82+
const mscors = interactions.map(i => i.mscor);
83+
return {
84+
min: Math.min(...mscors),
85+
max: Math.max(...mscors),
86+
step: 0.001 // Fixed small step for mscor
87+
};
88+
});
89+
5790
dataSource$ = computed(() => {
91+
const interactions = this.interactions$() || [];
92+
const filteredInteractions = interactions.filter(interaction => {
93+
const pValue = interaction.p_value;
94+
const mscor = interaction.mscor;
95+
return pValue >= this.minPValue() &&
96+
pValue <= this.maxPValue() &&
97+
mscor >= this.minMscor() &&
98+
mscor <= this.maxMscor();
99+
});
100+
58101
return new MatTableDataSource(
59-
(this.interactions$() || []).map((interaction) => {
102+
filteredInteractions.map((interaction) => {
60103
const names = BrowseService.getInteractionFullNames(interaction);
61104
return {
62105
name_1: names[0],
@@ -83,6 +126,17 @@ export class InteractionsTableComponent implements AfterViewInit {
83126
effect(() => {
84127
this.infoService.renderMscorEquation(this.mscorEquation$()!);
85128
});
129+
130+
// Initialize slider values to data limits
131+
effect(() => {
132+
const pLimits = this.pValueLimits();
133+
const mLimits = this.mscorLimits();
134+
135+
this.minPValue.set(pLimits.min);
136+
this.maxPValue.set(pLimits.max);
137+
this.minMscor.set(mLimits.min);
138+
this.maxMscor.set(mLimits.max);
139+
});
86140
}
87141

88142
ngAfterViewInit(): void {

0 commit comments

Comments
 (0)