Skip to content

Commit

Permalink
Add molecule column + renderer for LineUp
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkh committed Jul 8, 2022
1 parent 40d1755 commit 0f4617c
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 0 deletions.
16 changes: 16 additions & 0 deletions dist/lineup/renderer/StructureImageColumn.d.ts

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

1 change: 1 addition & 0 deletions dist/lineup/renderer/StructureImageColumn.d.ts.map

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

38 changes: 38 additions & 0 deletions dist/lineup/renderer/StructureImageColumn.js

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

1 change: 1 addition & 0 deletions dist/lineup/renderer/StructureImageColumn.js.map

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

13 changes: 13 additions & 0 deletions dist/lineup/renderer/StructureImageRenderer.d.ts

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

1 change: 1 addition & 0 deletions dist/lineup/renderer/StructureImageRenderer.d.ts.map

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

72 changes: 72 additions & 0 deletions dist/lineup/renderer/StructureImageRenderer.js

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

1 change: 1 addition & 0 deletions dist/lineup/renderer/StructureImageRenderer.js.map

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

48 changes: 48 additions & 0 deletions src/lineup/renderer/StructureImageColumn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { StringColumn, IDataRow, IStringFilter, Column } from 'lineupjs';
import { isEqual } from 'lodash';

export interface IStructureFilter extends IStringFilter {
filter: string;
valid: Set<string>;
}

export class StructureImageColumn extends StringColumn {
protected structureFilter: IStructureFilter | null = null;

protected align: string | null = null;

filter(row: IDataRow): boolean {
if (!this.isFiltered()) {
return true;
}
return this.structureFilter!.valid.has(this.getLabel(row));
}

isFiltered(): boolean {
return this.structureFilter != null && this.structureFilter.valid?.size > 0;
}

getFilter() {
return this.structureFilter!;
}

setFilter(filter: IStructureFilter | null) {
if (isEqual(filter, this.structureFilter)) {
return;
}

this.fire([StringColumn.EVENT_FILTER_CHANGED, Column.EVENT_DIRTY_VALUES, Column.EVENT_DIRTY], this.structureFilter, (this.structureFilter = filter));
}

getAlign(): string | null {
return this.align;
}

setAlign(structure: string | null): void {
if (isEqual(structure, this.align)) {
return;
}

this.fire([Column.EVENT_DIRTY_VALUES, Column.EVENT_DIRTY], (this.align = structure));
}
}
80 changes: 80 additions & 0 deletions src/lineup/renderer/StructureImageRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { ICellRendererFactory, ERenderMode, ICellRenderer, IDataRow, IRenderContext, IGroupCellRenderer, IOrderedGroup, renderMissingDOM } from 'lineupjs';
import { abortAble } from 'lineupengine';
import { StructureImageColumn } from './StructureImageColumn';
import { AppContext } from '../../app';

const template = '<a target="_blank" rel="noopener" style="background-size: contain; background-position: center; background-repeat: no-repeat;"></a>';

export function getImageURL(structure: string, substructure: string | null = null, align: string | null = null): string {
return `/api/image/?structure=${encodeURIComponent(structure)}${substructure ? `&substructure=${encodeURIComponent(substructure)}` : ''}${
align ? `&align=${encodeURIComponent(align)}` : ''
}`;
}

export function getReducedImages(structures: string[], method: 'single' | 'murcko' | 'mcs' | 'similarity' | 'auto' = 'auto'): Promise<string | null> {
// return fetchText('/api/image/', {
// structures,
// method,
// }).catch(() => null);
return AppContext.getInstance()
.getAPIData('/image', { structures, method })
.catch(() => null);
}

export function svgToImageSrc(svg: string): string {
return `data:image/svg+xml;base64,${btoa(svg)}`;
}

export function svgToCSSBackground(svg: string): string {
return `url('${svgToImageSrc(svg)}')`;
}

export class StructureImageRenderer implements ICellRendererFactory {
readonly title: string = 'Chemical Structure';

canRender(col: StructureImageColumn, mode: ERenderMode): boolean {
return col instanceof StructureImageColumn && (mode === ERenderMode.CELL || mode === ERenderMode.GROUP);
}

create(col: StructureImageColumn): ICellRenderer {
return {
template,
update: (n: HTMLLinkElement, d: IDataRow) => {
if (!renderMissingDOM(n, col, d)) {
if (d.v.images?.[0]) {
n.style.backgroundImage = svgToCSSBackground(d.v.images[0]);
return null;
}
const value = col.getValue(d)!;
// Load aysnc to avoid triggering
return abortAble(
new Promise((resolve) => {
window.setTimeout(() => resolve(value), 500);
}),
).then((image) => {
if (typeof image === 'symbol') {
return;
}
n.style.backgroundImage = `url('${getImageURL(value, col.getFilter()?.filter, col.getAlign())}')`;
n.title = value;
n.href = `https://pubchem.ncbi.nlm.nih.gov/#query=${value}`;
});
}
return null;
},
};
}

createGroup(col: StructureImageColumn, context: IRenderContext): IGroupCellRenderer {
return {
template,
update: (n: HTMLImageElement, group: IOrderedGroup) => {
context.tasks.groupRows(col, group, 'StructureImageRendererGroup', (rows) => {
return abortAble(getReducedImages(Array.from(rows.map((row) => col.getLabel(row))))).then((res: any) => {
n.style.backgroundImage = res ? svgToCSSBackground(res) : '';
});
});
},
};
}
}

0 comments on commit 0f4617c

Please sign in to comment.