Skip to content

Commit

Permalink
Added selectors for aligning search result micro tracks to the micro …
Browse files Browse the repository at this point in the history
…tracks reducer, thus deprecating the alignment service. This work included refactoring the Smith-Waterman and Repeat alignment algorithms. Also, a basic workflow that utilizes the new selectors to dynamically generate micro synteny components in GoldenLayout was put in place to help with test driven development of the reducers.
  • Loading branch information
alancleary committed Aug 16, 2019
1 parent 99efd6e commit 8176052
Show file tree
Hide file tree
Showing 38 changed files with 898 additions and 890 deletions.
13 changes: 13 additions & 0 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"d3": "^5.8.2",
"golden-layout": "^1.5.9",
"jquery": "^3.3.1",
"mnemonist": "^0.30.0",
"rxjs": "^6.4.0",
"split.js": "^1.5.10",
"tippy.js": "^4.0.1",
Expand Down
73 changes: 51 additions & 22 deletions client/src/app/components/gene/gene.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Angular
import { Component, ViewChild } from "@angular/core";
import { AfterViewInit, Component, OnDestroy, ViewChild } from "@angular/core";
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
// app
import { GoldenLayoutDirective } from "../../directives";
import { MicroTracksService } from "../../services";
import { MacroComponent } from "./macro.component";
import { MicroComponent } from "./micro.component";
import { PlotComponent } from "./plot.component";
Expand All @@ -11,10 +14,12 @@ import { PlotComponent } from "./plot.component";
styleUrls: ["./gene.component.scss"],
templateUrl: "./gene.component.html",
})
export class GeneComponent {
export class GeneComponent implements OnDestroy, AfterViewInit {

@ViewChild(GoldenLayoutDirective) goldenLayoutDirective;

private _destroy: Subject<boolean> = new Subject();

layoutComponents = [
{component: MacroComponent, name: "macro"},
{component: MicroComponent, name: "micro"},
Expand All @@ -23,26 +28,50 @@ export class GeneComponent {
layoutConfig = {
content: [{
type: "column",
content: [
{
type: "component",
componentName: "macro",
isClosable: false
},
{
type: "component",
componentName: "micro",
componentState: {
inputs: {key: "value"},
outputs: {
plot: (() => {
this.goldenLayoutDirective.addItem({type: "component", componentName: "plot"});
})
},
},
isClosable: false
}
]
content: []
}]
};

constructor(private _microTracksService: MicroTracksService) { }

// Angular hooks

ngOnDestroy(): void {
this._destroy.next(true);
this._destroy.complete();
}

ngAfterViewInit(): void {
this._microTracksService.clusterIDs
.pipe(takeUntil(this._destroy))
.subscribe((IDs) => {
this._setLayoutConfig(IDs);
});
}

// private

private _setLayoutConfig(clusterIDs): void {
const microConfig = (id) => {
return {
type: "component",
componentName: "micro",
componentState: {
inputs: {cluster: id},
outputs: {
plot: (() => {
this.goldenLayoutDirective.addItem({type: "component", componentName: "plot"});
})
},
},
isClosable: false
};
};
// TODO: remove existing components before adding new ones
clusterIDs.forEach((id) => {
this.goldenLayoutDirective.addItem(microConfig(id));
});
}

// public
}
36 changes: 30 additions & 6 deletions client/src/app/components/gene/micro.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
// Angular + dependencies
import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, Output,
ViewChild } from "@angular/core";
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnDestroy,
Output, ViewChild } from "@angular/core";
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
// app
import { GCV } from "../../../assets/js/gcv";
import { MicroTracksService } from "../../services";

@Component({
selector: "micro",
Expand All @@ -12,7 +16,7 @@ import { GCV } from "../../../assets/js/gcv";
parameters
</div>
<div class="col card-col">
micro viewer
micro viewer: {{cluster}}
</div>
<div class="col-md-auto card-col-right border-left" gcvSidebar #macroLegend="sidebar">
macro legend
Expand All @@ -22,20 +26,40 @@ import { GCV } from "../../../assets/js/gcv";
})
export class MicroComponent implements AfterViewInit, OnDestroy {

@Input() cluster: number;
@Input() colors: any; // D3 color function
@Output() plot = new EventEmitter();

@ViewChild("container") container: ElementRef;

private _destroy: Subject<boolean> = new Subject();

constructor(private _microTracksService: MicroTracksService) { }

// Angular hooks

ngAfterViewInit() {
//const viewer = new GCV.visualization.Micro(this.container.nativeElement);
//this.container.nativeElement.innerHTML = "micro-synteny viewer";
// fetch own data because injected components don't have change detection
this._microTracksService.getCluster(this.cluster)
.pipe(takeUntil(this._destroy))
.subscribe(this._draw);
}

ngOnDestroy() {
//console.log('destroyed');
this._destroy.next(true);
this._destroy.complete();
}

// public

spawnPlot() {
this.plot.emit();
}

// private

_draw(): void {
//const viewer = new GCV.visualization.Micro(this.container.nativeElement);
//this.container.nativeElement.innerHTML = "micro-synteny viewer";
}
}
93 changes: 2 additions & 91 deletions client/src/app/components/multi/multi.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { AppConfig } from "../../app.config";
import { Alert, Family, Gene, Group, MacroTracks, MicroTracks } from "../../models";
import { ClusterMixin, DrawableMixin, PointMixin } from "../../models/mixins";
import { microTracksOperator, multiMacroTracksOperator } from "../../operators";
import { AlignmentService, FilterService, InterAppCommunicationService,
import { FilterService, InterAppCommunicationService,
MacroTracksService, MicroTracksService } from "../../services";
import { AlertComponent } from "../shared/alert.component";

Expand Down Expand Up @@ -79,8 +79,7 @@ export class MultiComponent implements AfterViewInit, OnDestroy, OnInit {
// track which families have been checked
private familyGlyphsSubject = new BehaviorSubject<{[key: string]: string}>({});

constructor(private alignmentService: AlignmentService,
private resolver: ComponentFactoryResolver,
constructor(private resolver: ComponentFactoryResolver,
private filterService: FilterService,
private communicationService: InterAppCommunicationService,
private macroTracksService: MacroTracksService,
Expand Down Expand Up @@ -158,94 +157,6 @@ export class MultiComponent implements AfterViewInit, OnDestroy, OnInit {
return glyphs;
}),
takeUntil(this.destroy));

const glyphedAlignedTracks: Observable<MicroTracks<DrawableMixin, ClusterMixin, DrawableMixin & PointMixin>> = combineLatest(
this.alignmentService.alignedMicroTracks,
this.familyGlyphs)
.pipe(
map(([tracks, glyphs]) => {
return {
// ensure the orphan family is present
families: [...tracks.families, {id: "", name: ""}].map((f) => {
if (glyphs.hasOwnProperty(f.id)) {
const family = Object.create(f);
family.glyph = glyphs[f.id];
return family;
}
return f;
}),
groups: tracks.groups.map((t) => {
const track = Object.create(t);
track.genes = t.genes.map((g) => {
if (glyphs.hasOwnProperty(g.family)) {
const gene = Object.create(g);
gene.glyph = glyphs[g.family];
return gene;
}
return g;
});
return track;
}),
};
}));

this.alignmentService.alignedMicroTracks
.pipe(takeUntil(this.destroy))
.subscribe((tracks) => {
this.hideLeftSlider();
this._setFamilyGlyph(null, null);
});

glyphedAlignedTracks
.pipe(
withLatestFrom(this.microTracksService.routeParams),
takeUntil(this.destroy))
.subscribe(([tracks, route]) => {
this._onAlignedMicroTracks(tracks, route);
});

const filteredMicroTracks =
combineLatest(
glyphedAlignedTracks,
this.filterService.regexpAlgorithm,
this.filterService.orderAlgorithm)
.pipe(microTracksOperator({prefix: (t) => "group " + t.cluster + " - "}));

filteredMicroTracks
.pipe(takeUntil(this.destroy))
.subscribe((tracks) => {
// add gene tooltips
tracks.groups.forEach((group) => {
group.genes = group.genes.map((gene) => {
const g = Object.create(gene);
g.htmlAttributes = {
"data-tippy-content": function (g) {
return `
<div class="media" style="text-align:left;">
<div class="media-body">
<h6 class="mt-0 mb-1"><b>${g.name}</b> (${g.family})</h6>
${g.fmin} - ${g.fmax}
</div>
</div>
`;
}
};
return g;
});
});
this.microTracks = tracks as MicroTracks;
});

// subscribe to macro track data
combineLatest(
this.macroTracksService.multiMacroTracks
.pipe(filter((tracks) => tracks !== undefined)),
filteredMicroTracks)
.pipe(multiMacroTracksOperator())
.pipe(takeUntil(this.destroy))
.subscribe((tracks) => {
this._onMacroTracks(tracks);
});
}

// public
Expand Down
13 changes: 6 additions & 7 deletions client/src/app/components/search/search-params.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { takeUntil } from "rxjs/operators";
import { AppConfig } from "../../app.config";
import { ALIGNMENT_ALGORITHMS } from "../../algorithms";
import { AlignmentParams, BlockParams, QueryParams } from "../../models";
import { AlignmentService, MacroTracksService, MicroTracksService } from "../../services";
import { MacroTracksService, MicroTracksService } from "../../services";

@Component({
selector: "search-params",
Expand Down Expand Up @@ -38,8 +38,7 @@ export class SearchParamsComponent implements OnDestroy, OnInit {
private destroy: Subject<boolean>;

// constructor
constructor(private alignmentService: AlignmentService,
private fb: FormBuilder,
constructor(private fb: FormBuilder,
private macroTracksService: MacroTracksService,
private microTracksService: MicroTracksService) {
this.destroy = new Subject();
Expand All @@ -65,9 +64,9 @@ export class SearchParamsComponent implements OnDestroy, OnInit {
// initialize alignment group and subscribe to store updates
const defaultAlignment = new AlignmentParams();
this.alignmentGroup = this.fb.group(defaultAlignment.formControls());
this.alignmentService.alignmentParams
.pipe(takeUntil(this.destroy))
.subscribe((params) => this._updateGroup(this.alignmentGroup, params));
//this.alignmentService.alignmentParams
// .pipe(takeUntil(this.destroy))
// .subscribe((params) => this._updateGroup(this.alignmentGroup, params));

// submit the updated form
this.blockGroup.markAsDirty();
Expand Down Expand Up @@ -95,7 +94,7 @@ export class SearchParamsComponent implements OnDestroy, OnInit {
});
// submit alignment params
this._submitGroup(this.alignmentGroup, (params) => {
this.alignmentService.updateParams(params);
//this.alignmentService.updateParams(params);
});
} else {
this.invalid.emit();
Expand Down
Loading

0 comments on commit 8176052

Please sign in to comment.