Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pdbe/web-components/ligand-env
1 result
Show changes
Commits on Source (2)
# PDB ligand environment component # PDB LigandEnv component
This is a web-component to display ligand structure in 2D along with its interactions. Ligand can be perceived as a set of covalently linked pdb residues (refered to as bound molecule) or a single pdb residue. This depiction can be enriched with a substructure highlight, atom names, and binding site interactions. This is a web-component to display ligand structure in 2D along with its interactions. This depiction can be enriched with substructure highlight, atom names, binding site interactions and aggregated protein-ligand interactions.
## Step after cloning (use local server to see demo pages) ## Installation
```shell ```shell
npm run install npm install
npm run build npm run build
npm run start npm run start
open any of the *.html pages in the demo directory
``` ```
To see demo, copy demo directory to build and open any of the html pages.
## Component modes ## Component modes
* Mode A: Display bound molecule and its interactions * Mode A: Display ligand and its interactions (Using pdb-id, pdb-res-id and pdb-chain-id)
* Mode B: Display ligand and its interactions * Mode B: Display boundmolecule and its interactions (Using pdb-id and bound-molecule-id)
* Mode C: Display ligand (chemical component) only * Mode C: Display ligand only (Using pdb-res-name)
* Mode D: Display ligand and aggregated interactions (Using pdb-res-name and contact-type)
| Mode A | Mode B | Mode C | | Mode A | Mode B | Mode C | Mode D |
|:------------------: | :-------: | :-------: | |:------------------: | :-------: | :-------: | :-------: |
| <img src="https://www.ebi.ac.uk/~lpravda/imgs/1cbs_REA_200_A.png"/>| <img src="https://www.ebi.ac.uk/~lpravda/imgs/3d12_bm1.png"/> | <img src="https://www.ebi.ac.uk/pdbe-srv/pdbechem/image/showNew?code=VIA&size=500"/> | | <img src="dependencies/REA_A_200.png">| <img src="dependencies/3d12_bm1.png"/> | <img src="https://ftp.ebi.ac.uk/pub/databases/msd/pdbechem_v2/ccd/V/VIA/VIA_500.svg"/> | <img src="dependencies/STI_aggregated_interactions.png"> |
| [1cbs REA 200 A](https://www.ebi.ac.uk/pdbe/entry/pdb/1cbs/bound/REA) | 3D12 bm1 (`2xGLC-2xBGC-LXZ-NGA-GL0`)| [wwPDB CCD - VIA](https://pdbe.org/chem/VIA) | [1cbs REA 200 A](https://www.ebi.ac.uk/pdbe/entry/pdb/1cbs/bound/REA) | [3D12 bm1 (`2xGLC-2xBGC-LXZ-NGA-GL0`)](https://www.ebi.ac.uk/pdbe/entry/pdb/3d12/branched/4)| [wwPDB CCD - VIA](https://pdbe.org/chem/VIA) | STI |
## How to use it ## How to use it
The component can be inserted into the pages by two different ways. Either as a `web-component` using html tag, or directly by using javascript as a `plugin`. PDB LigandEnv can be inserted into web pages in two different ways. Either as a `web-component` using html tag, or directly by using javascript as a `plugin`.
Interactions data displayed by the component can come from three different environments `Production`, `Development`, `Internal`. If no environment is specified `Production` is used as default.. Interactions data displayed by the component can come from three different environments `Production`, `Development`, `Internal`. If no environment is specified `Production` is used as default..
...@@ -53,7 +53,7 @@ A few files needs to be imported in the page before the component is attempted t ...@@ -53,7 +53,7 @@ A few files needs to be imported in the page before the component is attempted t
charset="utf-8"></script> charset="utf-8"></script>
<!--PDBe interactions component--> <!--PDBe interactions component-->
<script type="module" src="pdb-ligand-env-component-0.3.0-min.js"></script> <script type="module" src="pdb-ligand-env-component-2.0.0-min.js"></script>
``` ```
#### A) Ligand interactions #### A) Ligand interactions
...@@ -68,16 +68,20 @@ A few files needs to be imported in the page before the component is attempted t ...@@ -68,16 +68,20 @@ A few files needs to be imported in the page before the component is attempted t
<pdb-ligand-env pdb-id="3d12" bound-molecule-id="bm1"></pdb-ligand-env> <pdb-ligand-env pdb-id="3d12" bound-molecule-id="bm1"></pdb-ligand-env>
``` ```
#### C) Ligand/chemical component #### C) Ligand
```html ```html
<pdb-ligand-env pdb-res-name="CLR" zoom-on ></pdb-ligand-env> <pdb-ligand-env pdb-res-name="CLR" zoom-on ></pdb-ligand-env>
``` ```
#### D) Ligand and aggregated interactions
```html
<pdb-ligand-env pdb-res-name="STI", contact-type=["hbond","hydrophobic","vdw"]></pdb-ligand-env>
```
The component contains a number of properties that can be set, in order to change data that are being displayed. First you need to define a component on the page: The component contains a number of properties that can be set, in order to change data that are being displayed. First you need to define a component on the page:
```html ```html
<pdb-ligand-env id='SIA-component'></pdb-ligand-env> <pdb-ligand-env id='SIA-component'></pdb-ligand-env>
``` ```
...@@ -87,14 +91,15 @@ and then inject data you want to display e.g.: ...@@ -87,14 +91,15 @@ and then inject data you want to display e.g.:
let chemUrl = `https://www.ebi.ac.uk/pdbe/static/files/pdbechem_v2/SIA/annotation`; let chemUrl = `https://www.ebi.ac.uk/pdbe/static/files/pdbechem_v2/SIA/annotation`;
let interactionsURL = "https://wwwdev.ebi.ac.uk/pdbe/graph-api/pdb/bound_ligand_interactions/4yy1/A/604"; let interactionsURL = "https://wwwdev.ebi.ac.uk/pdbe/graph-api/pdb/bound_ligand_interactions/4yy1/A/604";
let component = document.getElementById('SIA-component'); let component = document.getElementById('SIA-component');
(async() => {
const depiction = await (await fetch(chemUrl)).json(); const depiction = await (await fetch(chemUrl)).json();
const interactionsData = await (await fetch(interactionsURL)).json(); const interactionsData = await (await fetch(interactionsURL)).json();
const atomsToHighlight = ['C10', 'C11', 'O10']; const atomsToHighlight = ['C10', 'C11', 'O10'];
component.depiction = depiction; component.depiction = depiction;
component.ligandHighlight = atomsToHighlight; component.ligandHighlight = atomsToHighlight;
component.interactions = interactionsData; component.interactions = interactionsData;
})()
``` ```
### Plugin ### Plugin
...@@ -148,6 +153,13 @@ this.display.initLigandInteractions('1cbs', 200, 'A'); ...@@ -148,6 +153,13 @@ this.display.initLigandInteractions('1cbs', 200, 'A');
// to display chemical component with atom names only // to display chemical component with atom names only
this.display.initLigandDisplay('HEM', true); this.display.initLigandDisplay('HEM', true);
// to display aggregated protein-ligand interactions
this.display.initLigandDisplay('STI').then(() => {
this.display.initLigandWeights('STI').then(() => {
this.display.showWeights(["hydrophobic"]);
})
})
```` ````
## Parameters ## Parameters
...@@ -157,7 +169,8 @@ this.display.initLigandDisplay('HEM', true); ...@@ -157,7 +169,8 @@ this.display.initLigandDisplay('HEM', true);
| pdb-id | string | No | PDB id of a protein to retrieve interactions from. `(mode A and B only)` | | pdb-id | string | No | PDB id of a protein to retrieve interactions from. `(mode A and B only)` |
| bound-molecule-id | string | No | PDB bound molecule id `(mode A only)` | | bound-molecule-id | string | No | PDB bound molecule id `(mode A only)` |
| pdb-res-name | string | No | PDB residue name aka: *auth_comp_id* `(mode C only)` | pdb-res-name | string | No | PDB residue name aka: *auth_comp_id* `(mode C only)`
| pdb-res-id | number | No | PDB residue id aka: *auth_seq_id* `(mode B only)` | pdb-res-id | number | No | PDB residue id aka: *auth_seq_id* `(mode B only)` |
| contact-type | string[] | No | protein-ligand contact_type calculated by pdbe-arpeggio `(mode D only)` |
| pdb-chain-id | string | No | PDB residue chain aka: *auth_asym_id* `(mode B only)`| | pdb-chain-id | string | No | PDB residue chain aka: *auth_asym_id* `(mode B only)`|
| substructure | string[] | No | List of atom names to be highlighted on the ligand structure | | substructure | string[] | No | List of atom names to be highlighted on the ligand structure |
| color | string | No | HEX representation of the color highlight. `(Default: #D3D3D3)` | | color | string | No | HEX representation of the color highlight. `(Default: #D3D3D3)` |
......
<!doctype html>
<html lang="en">
<head>
<script src="https://d3js.org/d3.v5.min.js"></script>
<!-- CSS style to be used for scene drawing (required for saving SVGs.) -->
<link rel="stylesheet" href="http://127.0.0.1:8080/pdb-ligand-env-svg.css" />
<!-- UI icons -->
<link rel="stylesheet" href="https://ebi.emblstatic.net/web_guidelines/EBI-Icon-fonts/v1.3/fonts.css" />
<!-- Web component polyfill (only loads what it needs) -->
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/webcomponents-lite.js" charset="utf-8">
</script>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"
charset="utf-8"></script>
<!--PDBe interactions component-->
<script type="module" src="http://127.0.0.1:8080/pdb-ligand-env-component-1.0.0-min.js"></script>
</head>
<body>
<!--Mode A-->
<div style="position: relative; float: left;">
<div style="width: 500px; height: 500px; position: relative">
<pdb-ligand-env pdb-res-name="STI", contact-type="total"></pdb-ligand-env>
</div>
</div>
</body>
</html>
\ No newline at end of file
dependencies/3d12_bm1.png

37.9 KiB

dependencies/REA_A_200.png

47.1 KiB

dependencies/STI_aggregated_interactions.png

32.8 KiB

...@@ -4,6 +4,7 @@ const del = require('del'); ...@@ -4,6 +4,7 @@ const del = require('del');
const concat = require('gulp-concat'); const concat = require('gulp-concat');
const header = require('gulp-header'); const header = require('gulp-header');
const minify = require("gulp-minify"); const minify = require("gulp-minify");
const cp = require('child_process');
const PACKAGE_ROOT_PATH = process.cwd(); const PACKAGE_ROOT_PATH = process.cwd();
const PKG_JSON = require(path.join(PACKAGE_ROOT_PATH, "package.json")); const PKG_JSON = require(path.join(PACKAGE_ROOT_PATH, "package.json"));
...@@ -18,7 +19,7 @@ const banner = ['/**', ...@@ -18,7 +19,7 @@ const banner = ['/**',
].join('\n'); ].join('\n');
const license = ['/**', const license = ['/**',
' * Copyright 2019-2020 Lukas Pravda <lpravda@ebi.ac.uk>', ' * Copyright 2024-2030 Protein Data Bank in Europe <pdbehelp@ebi.ac.uk>',
' * European Bioinformatics Institute (EBI, http://www.ebi.ac.uk/)', ' * European Bioinformatics Institute (EBI, http://www.ebi.ac.uk/)',
' * European Molecular Biology Laboratory (EMBL, http://www.embl.de/)', ' * European Molecular Biology Laboratory (EMBL, http://www.embl.de/)',
' * Licensed under the Apache License, Version 2.0 (the "License");', ' * Licensed under the Apache License, Version 2.0 (the "License");',
...@@ -94,5 +95,11 @@ gulp.task('minifyPlugin', () => { ...@@ -94,5 +95,11 @@ gulp.task('minifyPlugin', () => {
.pipe(gulp.dest('build/')); .pipe(gulp.dest('build/'));
}); });
gulp.task('createDoc', function (cb) {
cp.exec('./node_modules/.bin/jsdoc -c jsdoc.json', function(err, stdout, stderr){
cb(err);
})
});
gulp.task('default', gulp.series('clean', 'copyAppCSS', 'concat', 'concatCSS', gulp.task('default', gulp.series('clean', 'copyAppCSS', 'concat', 'concatCSS',
'copyXML', 'copyIndex', 'copyMapping', 'minifyPlugin')); 'copyXML', 'copyIndex', 'copyMapping', 'minifyPlugin', 'createDoc'));
\ No newline at end of file \ No newline at end of file
{
"tags": {
"allowUnknownTags": true
},
"opts": {
"template": "node_modules/better-docs",
"destination": "build/docs"
},
"plugins": [
"node_modules/better-docs/typescript",
"plugins/markdown"
],
"source": {
"includePattern": "\\.(jsx|js|ts|tsx)$",
"include": ["README.md", "src/component", "src/plugin"]
},
"templates": {
"cleverLinks": false,
"monospaceLinks": false,
"default": {
"outputSourceFiles": true
},
"path": "ink-docstrap",
"theme": "cerulean",
"navType": "vertical",
"linenums": true,
"dateFormat": "MMMM Do YYYY, h:mm:ss a"
}
}
\ No newline at end of file
source diff could not be displayed: it is too large. Options to address this: view the blob.
{ {
"name": "pdb-ligand-env", "name": "pdb-ligand-env",
"version": "1.0.0", "version": "2.0.0",
"description": "", "description": "",
"main": "app.js", "main": "app.js",
"dependencies": { "dependencies": {
"@types/d3": "^5.16.3", "@types/d3": "^5.16.3",
"@types/d3-tip": "^3.5.5", "@types/d3-tip": "^3.5.5",
"@types/ws": "^8.5.4",
"d3": "^5.16.0", "d3": "^5.16.0",
"d3-tip": "^0.9.1", "d3-tip": "^0.9.1",
"d3scription": "^1.0.1", "d3scription": "^1.0.1",
"lit-element": "^2.4.0", "lit-element": "^2.4.0",
"typescript": "^4.0.2" "typescript": "^5.3.3"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.3", "@babel/core": "^7.12.3",
...@@ -18,7 +19,8 @@ ...@@ -18,7 +19,8 @@
"@babel/preset-env": "^7.12.1", "@babel/preset-env": "^7.12.1",
"@babel/runtime": "^7.12.1", "@babel/runtime": "^7.12.1",
"@webcomponents/webcomponentsjs": "^2.5.0", "@webcomponents/webcomponentsjs": "^2.5.0",
"babel-loader": "^8.1.0", "babel-loader": "^9.1.3",
"better-docs": "^2.7.3",
"browser-sync": "^2.26.13", "browser-sync": "^2.26.13",
"camelcase": "^5.0.0", "camelcase": "^5.0.0",
"clean-webpack-plugin": "^1.0.1", "clean-webpack-plugin": "^1.0.1",
...@@ -30,14 +32,16 @@ ...@@ -30,14 +32,16 @@
"gulp-concat": "^2.6.1", "gulp-concat": "^2.6.1",
"gulp-header": "^2.0.9", "gulp-header": "^2.0.9",
"gulp-minify": "^3.1.0", "gulp-minify": "^3.1.0",
"jsdoc": "^4.0.2",
"live-server": "^1.2.1", "live-server": "^1.2.1",
"npm-run-all": "^4.1.3", "npm-run-all": "^4.1.3",
"onchange": "^6.1.1", "onchange": "^6.1.1",
"style-loader": "^0.23.1", "style-loader": "^0.23.1",
"ts-node": "^7.0.1", "ts-node": "^7.0.1",
"url-loader": "^1.1.2", "url-loader": "^1.1.2",
"webpack": "^5.2.0", "webpack": "^5.89.0",
"webpack-cli": "^3.3.12" "webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}, },
"scripts": { "scripts": {
"tscW": "tsc -w", "tscW": "tsc -w",
......
...@@ -3,6 +3,14 @@ import { LitElement } from 'lit-element'; ...@@ -3,6 +3,14 @@ import { LitElement } from 'lit-element';
import "../styles/pdb-ligand-env.css"; import "../styles/pdb-ligand-env.css";
// Extend the LitElement base class // Extend the LitElement base class
/**
* PDB LigandEnv component to display ligand structure in 2D along with its interactions.
* This depiction can be enriched with substructure highlight, atom names, binding site
* interactions and aggregated protein-ligand interactions
* @component
* @example <caption> Basic usage </caption>
* <pdb-ligand-env pdb-id="1cbs" pdb-res-id="200" pdb-chain-id="A" environment="development"></pdb-ligand-env>
*/
class pdbLigandEnv extends LitElement { class pdbLigandEnv extends LitElement {
//Get properties / attribute values //Get properties / attribute values
...@@ -13,6 +21,7 @@ class pdbLigandEnv extends LitElement { ...@@ -13,6 +21,7 @@ class pdbLigandEnv extends LitElement {
entityId: { type: String, attribute: 'entity-id' }, entityId: { type: String, attribute: 'entity-id' },
resName: { type: String, attribute: 'pdb-res-name' }, resName: { type: String, attribute: 'pdb-res-name' },
resId: { type: Number, attribute: 'pdb-res-id' }, resId: { type: Number, attribute: 'pdb-res-id' },
contactType: {type: Array, attribute: 'contact-type', noAccessors: true},
chainId: { type: String, attribute: 'pdb-chain-id' }, chainId: { type: String, attribute: 'pdb-chain-id' },
substructureHighlight: { type: Array, attribute: 'substructure' }, substructureHighlight: { type: Array, attribute: 'substructure' },
substructureColor: { type: String, attribute: 'color' }, substructureColor: { type: String, attribute: 'color' },
...@@ -22,11 +31,27 @@ class pdbLigandEnv extends LitElement { ...@@ -22,11 +31,27 @@ class pdbLigandEnv extends LitElement {
}; };
} }
// Create custom accessors for contactType
set contactType(value) {
let prevCType = this._contactType + "";
this._contactType = value;
if (prevCType.length > 0) {
this.renderLigandEnv();
}
}
get contactType() { return this._contactType; }
constructor() { constructor() {
super(); super();
} }
async connectedCallback() { async connectedCallback() {
this.renderLigandEnv();
}
renderLigandEnv() {
this.innerHTML = "";
this.highlightSubstructure = []; this.highlightSubstructure = [];
let uiParams = new Config.UIParameters(); let uiParams = new Config.UIParameters();
uiParams.zoom = this.zoomOn; uiParams.zoom = this.zoomOn;
...@@ -47,12 +72,22 @@ class pdbLigandEnv extends LitElement { ...@@ -47,12 +72,22 @@ class pdbLigandEnv extends LitElement {
this.display.initLigandInteractions(this.pdbId, this.resId, this.chainId); this.display.initLigandInteractions(this.pdbId, this.resId, this.chainId);
} }
} }
else if (this.resName) { else if (this.resName){
this.display.initLigandDisplay(this.resName, names).then(() => this.display.centerScene()); this.display.initLigandDisplay(this.resName, names).then(() => {
if (this.contactType){
if(this.display.ligandIntxData === undefined){
this.display.initLigandWeights(this.resName).then(() => {
this.display.showWeights(this.contactType);
})
}
else {
this.display.showWeights(this.contactType);
}
}
})
} }
} }
//#region properties //#region properties
set depiction(data) { set depiction(data) {
if (!data) return; if (!data) return;
...@@ -61,6 +96,10 @@ class pdbLigandEnv extends LitElement { ...@@ -61,6 +96,10 @@ class pdbLigandEnv extends LitElement {
this.display.centerScene(); this.display.centerScene();
} }
set atomWeights(contactType) {
this.display.showWeights(contactType);
}
set highlightSubstructure(data) { set highlightSubstructure(data) {
if (!data || !this.display) { if (!data || !this.display) {
console.log(`Argument needs to be a non empty array of strings.`); console.log(`Argument needs to be a non empty array of strings.`);
...@@ -78,12 +117,6 @@ class pdbLigandEnv extends LitElement { ...@@ -78,12 +117,6 @@ class pdbLigandEnv extends LitElement {
this.display.addLigandHighlight(this.substructureHighlight, this.highlightColor); this.display.addLigandHighlight(this.substructureHighlight, this.highlightColor);
} }
set contourData(data) {
if (!data || !this.display || !this.display.depiction !== undefined) return;
this.display.addContours(data);
}
set zoom(data) { set zoom(data) {
if (this.display !== undefined) this.display.toggleZoom(data); if (this.display !== undefined) this.display.toggleZoom(data);
} }
...@@ -104,4 +137,4 @@ class pdbLigandEnv extends LitElement { ...@@ -104,4 +137,4 @@ class pdbLigandEnv extends LitElement {
} }
// Register the new element with the browser. // Register the new element with the browser.
customElements.define('pdb-ligand-env', pdbLigandEnv); customElements.define('pdb-ligand-env', pdbLigandEnv);
\ No newline at end of file
...@@ -7,10 +7,16 @@ namespace Config { ...@@ -7,10 +7,16 @@ namespace Config {
export const interactionShowLabelEvent: string = 'PDB.interactions.showLabel'; export const interactionShowLabelEvent: string = 'PDB.interactions.showLabel';
export const interactionHideLabelEvent: string = 'PDB.interactions.hideLabel'; export const interactionHideLabelEvent: string = 'PDB.interactions.hideLabel';
export const LigandShowAtomEvent: string = 'PDB.ligand.showAtom';
export const LigandHideAtomEvent: string = 'PDB.ligand.hideAtom';
export const molstarClickEvent: string = 'PDB.molstar.click'; export const molstarClickEvent: string = 'PDB.molstar.click';
export const molstarMouseoverEvent: string = 'PDB.molstar.mouseover'; export const molstarMouseoverEvent: string = 'PDB.molstar.mouseover';
export const molstarMouseoutEvent: string = 'PDB.molstar.mouseout'; export const molstarMouseoutEvent: string = 'PDB.molstar.mouseout';
export const ligandHeatmapMouseoverEvent: string = 'PDB.ligHeatmap.mouseover';
export const ligandHeatmapMouseoutEvent: string = 'PDB.ligHeatmap.mouseout';
export const aaTypes = new Map<string, Array<string>>([ export const aaTypes = new Map<string, Array<string>>([
['hydrophobic', new Array<string>('A', 'I', 'L', 'M', 'F', 'W', 'V')], ['hydrophobic', new Array<string>('A', 'I', 'L', 'M', 'F', 'W', 'V')],
['positive', Array<string>('K', 'R', 'O')], ['positive', Array<string>('K', 'R', 'O')],
......
/** /**
* This class contains all the details which are necessary for redrawing * This class contains all the details which are necessary for redrawing
* RDKIt style 2D molecule depiction on a client side as well as some * RDKit style 2D molecule depiction on a client side as well as some
* other logic which should hopefully help with the initial placement of * other logic for initial placement of
* binding partners in the residue-level view. * binding partners in the residue-level view.
* *
* @author Lukas Pravda <lpravda@ebi.ac.uk>
* @class Depiction * @class Depiction
* @param {string} ccdId PDB CCD id. * @param {HTMLElement} parent HTMLElement on which depiction to be displayed.
* @param {Atom[]} atoms List of atoms. * @param {any} root SVG element for the depiction.
* @param {Bond[]} bonds Visual representation of bonds. * @param {any} data Json annotation of ligand SVG
* They do not correlate 1:1 with a number of bonds! **/
* @param {Vector2D} resolution x,y dimension of the image. Needs to be used
* for a scene shift, so it is centered.
*/
class Depiction { class Depiction {
ccdId: string; ccdId: string;
atoms: Atom[]; atoms: Atom[];
bonds: Bond[]; bonds: Bond[];
resolution: Vector2D; resolution: Vector2D;
private parent: HTMLElement;
private root: d3.Selection<SVGGElement, unknown, null, undefined>; private root: d3.Selection<SVGGElement, unknown, null, undefined>;
private structure: d3.Selection<SVGGElement, unknown, null, undefined>;
private contour: d3.Selection<SVGGElement, unknown, null, undefined>;
private highlight: d3.Selection<SVGGElement, unknown, null, undefined>; private highlight: d3.Selection<SVGGElement, unknown, null, undefined>;
public weight: d3.Selection<SVGGElement, unknown, null, undefined>;
private structure: d3.Selection<SVGGElement, unknown, null, undefined>;
constructor(parent: any, data: any) { constructor(parent: HTMLElement, root: any, data: any) {
this.root = parent this.root = root;
this.parent = parent;
this.highlight = this.root.append('g').attr('id', 'highlight'); this.highlight = this.root.append('g').attr('id', 'highlight');
this.weight = this.root.append('g').attr('id', 'weight');
this.structure = this.root.append('g').attr('id', 'structure'); this.structure = this.root.append('g').attr('id', 'structure');
this.contour = this.root.append('g').attr('id', 'contour');
this.ccdId = data.ccd_id; this.ccdId = data.ccd_id;
this.resolution = new Vector2D(data.resolution.x, data.resolution.y); this.resolution = new Vector2D(data.resolution.x, data.resolution.y);
...@@ -53,7 +50,9 @@ class Depiction { ...@@ -53,7 +50,9 @@ class Depiction {
} }
this.bonds.push(bond); this.bonds.push(bond);
}); });
} }
...@@ -62,10 +61,10 @@ class Depiction { ...@@ -62,10 +61,10 @@ class Depiction {
* atom. * atom.
* *
* Present implementation sorts all the partners based on the atom * Present implementation sorts all the partners based on the atom
* degree and then gets the one with the lovest degree and places * degree and then gets the one with the lowest degree and places
* the initial residue position along the vector pointing from it. * the initial residue position along the vector pointing from it.
* *
* @param {string[]} atomNames list of atom names the bound residue * @param {string[]} atomNames array of atom names the bound residue
* has a contact with. * has a contact with.
* @returns {Vector2D} Returns an initial placement of the residue in contact. * @returns {Vector2D} Returns an initial placement of the residue in contact.
* @memberof Depiction * @memberof Depiction
...@@ -89,6 +88,13 @@ class Depiction { ...@@ -89,6 +88,13 @@ class Depiction {
return new Vector2D(x, y); return new Vector2D(x, y);
} }
/**
* Draws ligand structure by appending svg:path
* elements corresponding to bonds and atoms with labels
* @param {boolean} true if atom names need to be displayed
* @memberof Depiction
*/
public draw(atomNames: boolean = false) { public draw(atomNames: boolean = false) {
this.structure.selectAll("*").remove(); this.structure.selectAll("*").remove();
...@@ -99,6 +105,12 @@ class Depiction { ...@@ -99,6 +105,12 @@ class Depiction {
else this.appendLabels(); else this.appendLabels();
} }
/**
* Highlights atoms and bonds connecting them
* @param {string[]} atoms array of atom names to higlight
* @param {string} color color to be used for higlighting
* @memberof Depiction
*/
public highlightSubgraph(atoms: Array<string>, color: string = undefined) { public highlightSubgraph(atoms: Array<string>, color: string = undefined) {
if (!this.atoms || !atoms) return; if (!this.atoms || !atoms) return;
...@@ -125,17 +137,75 @@ class Depiction { ...@@ -125,17 +137,75 @@ class Depiction {
.attr('d', x => `M ${x.bgn.position.x},${x.bgn.position.y} ${x.end.position.x},${x.end.position.y}`) .attr('d', x => `M ${x.bgn.position.x},${x.bgn.position.y} ${x.end.position.x},${x.end.position.y}`)
.attr('style', `fill:none;fill-rule:evenodd;stroke:${color};stroke-width:22px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1`) .attr('style', `fill:none;fill-rule:evenodd;stroke:${color};stroke-width:22px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1`)
} }
/**
* Adds circles around atoms corresponding to the value of
* their weights.The size, color and number of crcles around
* atom indicates the strength of weight. Currently maximum of
* three circles are drawn
* @param {any} weights objects with atom names and value of weight
* @param {string} colorScheme Name of color to be used for circles
* @memberof Depiction
*/
public addCircles(weights: any, colorScheme: string): void {
this.atoms.forEach(x => {
x.value = weights.filter(y => y.atom == x.name).map(z => z.value)[0]
public addContour(data: any) { })
this.contour.selectAll('*').remove(); const data = this.atoms.filter(x => x.value >0);
const intxWeights = weights.map(x => x.value);
const gradient = new Model.Gradient(intxWeights, colorScheme).getScales();
const q1 = d3.quantile(intxWeights, 0.25);
const q3 = d3.quantile(intxWeights, 0.75);
const firstScale = gradient.firstScale;
const secondScale = gradient.secondScale;
const thirdScale = gradient.thirdScale;
this.weight.selectAll()
.data(data)
.enter()
.each(function(x: any){
if(x.value >= q1){
d3.select(this)
.append('circle')
.attr('cx', x.position.x)
.attr('cy', x.position.y)
.attr('r', secondScale.radiusScale(x.value))
.attr('fill', secondScale.colorScale(x.value))
.attr("fill-opacity", "0.5")
if(x.value >= q3){
d3.select(this)
.append('circle')
.attr('cx', x.position.x)
.attr('cy', x.position.y)
.attr('r', thirdScale.radiusScale(x.value))
.attr('fill', thirdScale.colorScale(x.value))
.attr("fill-opacity", "0.5")
}
}
});
this.contour.append('div').text(`'contour data goes here: ${data}`); this.weight.selectAll()
.data(data)
.enter()
.append('circle')
.attr("cx", x => x.position.x)
.attr("cy", x => x.position.y)
.attr("r", x => firstScale.radiusScale(x.value))
.attr("fill", x=> firstScale.colorScale(x.value))
.attr("fill-opacity", "0.5")
.on('mouseenter', (x:Atom) => this.atomMouseEnterEventHandler(x, true))
.on('mouseleave', () => this.atomMouseLeaveEventHandler(true));
} }
/** /**
* Appends to a given selection the visual representation of bonds as svg:path elements. * Appends to a given selection the visual representation of
* * bonds as svg:path elements.
* representation of the bond visuals. * representation of the bond visuals.
* @private
* @memberof Depiction * @memberof Depiction
*/ */
private appendBondVisuals(): void { private appendBondVisuals(): void {
...@@ -149,7 +219,7 @@ class Depiction { ...@@ -149,7 +219,7 @@ class Depiction {
/** /**
* Append atom name labels to the visualization. * Append atom name labels to the visualization.
* * @private
* @memberof Depiction * @memberof Depiction
*/ */
private appendAtomNames() { private appendAtomNames() {
...@@ -167,12 +237,8 @@ class Depiction { ...@@ -167,12 +237,8 @@ class Depiction {
} }
/** /**
* Append depiction labels to the visualization. Because RDKIt places * Append depiction labels to the visualization.
* the labels slightly differently this information needs to be * @private
* consumed too, because we cannot use just atom position directly.
* Also there are all sorts of colorful subscripts and superscripts,
* so it is much easier to use it this way.
*
* @memberof Depiction * @memberof Depiction
*/ */
private appendLabels() { private appendLabels() {
...@@ -183,7 +249,7 @@ class Depiction { ...@@ -183,7 +249,7 @@ class Depiction {
.data(data) .data(data)
.enter() .enter()
.append('g') .append('g')
.attr('filter', 'url(#solid-background)') .attr('filter', 'labels')
.each(function (x: any) { .each(function (x: any) {
for (var i = 0; i < x.labels.length; i++) { for (var i = 0; i < x.labels.length; i++) {
d3.select(this) d3.select(this)
...@@ -196,6 +262,12 @@ class Depiction { ...@@ -196,6 +262,12 @@ class Depiction {
}); });
} }
/**
* Finds the center of an array of atoms
* @param {string} ids atom ids
* @return {Vector2D} coordinates of center
* @memeberof Depiction
*/
public getCenter(ids: string[]): Vector2D { public getCenter(ids: string[]): Vector2D {
let coords = new Array<Vector2D>(); let coords = new Array<Vector2D>();
...@@ -214,7 +286,6 @@ class Depiction { ...@@ -214,7 +286,6 @@ class Depiction {
* *
* *
* @param {Map<string, number>} map * @param {Map<string, number>} map
* @returns
* @memberof Depiction * @memberof Depiction
*/ */
public sortMap(map: Map<string, number>) { public sortMap(map: Map<string, number>) {
...@@ -232,9 +303,81 @@ class Depiction { ...@@ -232,9 +303,81 @@ class Depiction {
return newMap; return newMap;
} }
// #region event handlers
/**
* Mouse enter event handler for circles around atoms
* depicting their weights
* @public
* @param {Atom} atom object
* @param {boolean} propagation if event should be triggered on external components
* @memebrof Depiction
*/
public atomMouseEnterEventHandler(x: Atom, propagation: boolean){
this.fireExternalAtomEvent(x, propagation, Config.LigandShowAtomEvent);
}
/**
* Mouse leave event handler for circlea round atoms
* depicting their weights
* @public
* @param {boolean} propagation if event should be triggered on external components
* @memberof Depiction
*/
public atomMouseLeaveEventHandler(propagation: boolean){
this.fireExternalNullEvent(propagation, Config.LigandHideAtomEvent);
}
// #endregion
// #region fire events
/**
* Dispatches custom event to display atom names and
* corresponding weights on tooltip on mouse enter
* @private
* @param {Atom} atom object
* @param {string} eventName name of event
* @memeberof Depiction
*/
private fireExternalAtomEvent(atom: Atom, propagation:boolean, eventName: string){
const e = new CustomEvent(eventName, {
bubbles: true,
detail: {
tooltip: atom.toTooltip(),
external: propagation
}
});
this.parent.dispatchEvent(e);
}
/**
* Dispatches event to hide tooltip on mouse leave
* @private
* @param {boolean} propagation if event should be triggered on external components
* @param {string} eventName name of event
* @memeberof Depiction
*/
private fireExternalNullEvent(propagation:boolean, eventName: string) {
const e = new CustomEvent(eventName, {
bubbles: true,
detail: {
external: propagation
}
});
this.parent.dispatchEvent(e);
}
// #endregion
} }
/** /**
* Atom from the depiction * Atom from the depiction
* *
...@@ -247,27 +390,37 @@ class Atom { ...@@ -247,27 +390,37 @@ class Atom {
name: string; name: string;
labels: any; labels: any;
position: Vector2D; position: Vector2D;
connectivity: number connectivity: number;
value: number;
constructor(item: any) { constructor(item: any) {
this.name = item.name; this.name = item.name;
this.labels = item.labels; this.labels = item.labels;
this.position = new Vector2D(item.x, item.y); this.position = new Vector2D(item.x, item.y);
this.connectivity = 0; this.connectivity = 0;
this.value = 0;
} }
/** /**
* *
* *
* @param {Atom} other * @param {Atom} other
* @returns true if the atoms are equal * @returns {boolean} true if the atoms are equal
* @memberof Atom * @memberof Atom
*/ */
public equals(other: Atom) { public equals(other: Atom): boolean {
if (!(other instanceof Atom)) return false; if (!(other instanceof Atom)) return false;
return other.name === this.name; return other.name === this.name;
} }
/**
* @return {string} name of atom
* @memberof Atom
*/
public toTooltip(): string {
return `<span>${this.name} | ${this.value}</span>`;
}
} }
/** /**
...@@ -340,7 +493,6 @@ class Vector2D { ...@@ -340,7 +493,6 @@ class Vector2D {
} }
} }
/** /**
* Represents a bond in a 2D depiction. * Represents a bond in a 2D depiction.
* *
...@@ -356,12 +508,6 @@ class Bond { ...@@ -356,12 +508,6 @@ class Bond {
coords: string; coords: string;
style: string; style: string;
/**
*Creates an instance of the bond.
* @param {Atom} a
* @param {Atom} b
* @memberof Bond
*/
constructor(a: Atom, b: Atom, coords: string, style: string) { constructor(a: Atom, b: Atom, coords: string, style: string) {
this.bgn = a; this.bgn = a;
this.end = b; this.end = b;
...@@ -389,7 +535,7 @@ class Bond { ...@@ -389,7 +535,7 @@ class Bond {
* Check whether or not a bond contains the atom. * Check whether or not a bond contains the atom.
* *
* @param {Atom} other The other side of the bond * @param {Atom} other The other side of the bond
* @returns True if the atom is a part of the bond, false otherwise. * @returns {boolean} True if the atom is a part of the bond, false otherwise.
* @memberof Bond * @memberof Bond
*/ */
public containsAtom(other: Atom) { public containsAtom(other: Atom) {
......
/**
* This class contains methods for creating all the visualization
* components of the LigandEnv
*
* @class Visualization
* @param {HTMLElement} element HTMLElement to display the visualization
* @param {Config.UIParameters} uiParameters UI parameter configurations
* @param {string} env environment to fetch data from
*
*/
class Visualization { class Visualization {
// component related // component related
private parent: HTMLElement; private parent: HTMLElement;
...@@ -26,6 +36,7 @@ class Visualization { ...@@ -26,6 +36,7 @@ class Visualization {
private visualsMapper: VisualsMapper; private visualsMapper: VisualsMapper;
private interactionsData: any; private interactionsData: any;
private ligandIntxData: any;
private selectedResidueHash: string; private selectedResidueHash: string;
private nodeDragged: boolean; private nodeDragged: boolean;
...@@ -68,8 +79,11 @@ class Visualization { ...@@ -68,8 +79,11 @@ class Visualization {
if (uiParameters.zoom) this.zoomHandler = this.getZoomHandler(); if (uiParameters.zoom) this.zoomHandler = this.getZoomHandler();
document.addEventListener(Config.ligandHeatmapMouseoverEvent, e => this.ligHeatmapMouseoverEventHandler(e));
document.addEventListener(Config.ligandHeatmapMouseoutEvent, () => this.ligHeatmapMouseoutEventHandler());
document.addEventListener(Config.molstarClickEvent, e => this.molstarClickEventHandler(e)); document.addEventListener(Config.molstarClickEvent, e => this.molstarClickEventHandler(e));
document.addEventListener(Config.molstarMouseoverEvent, e => this.molstarClickEventHandler(e)); document.addEventListener(Config.molstarMouseoverEvent, e => this.molstarClickEventHandler(e));
document.addEventListener(Config.molstarMouseoutEvent, () => this.molstarMouseoutEventHandler()); document.addEventListener(Config.molstarMouseoutEvent, () => this.molstarMouseoutEventHandler());
d3.select(this.parent).on('resize', () => this.resize()); d3.select(this.parent).on('resize', () => this.resize());
...@@ -95,7 +109,7 @@ class Visualization { ...@@ -95,7 +109,7 @@ class Visualization {
private molstarClickEventHandler(e: any) { private molstarClickEventHandler(e: any) {
if (this.fullScreen) return; if (this.fullScreen) return;
let hash = `${e.eventData.auth_asym_id}${e.eventData.auth_seq_id}${e.eventData.ins_code}`; let hash = `${e.eventData.auth_asym_id}${e.eventData.auth_seq_id}${e.eventData.ins_code}`;
this.nodes?.each((node: Model.InteractionNode, index: number, group: any) => { this.nodes?.each((node: Model.InteractionNode, index: number, group: any) => {
this.nodeDim(node, index, group); this.nodeDim(node, index, group);
...@@ -109,6 +123,22 @@ class Visualization { ...@@ -109,6 +123,22 @@ class Visualization {
} }
private ligHeatmapMouseoverEventHandler(e: any) {
if (this.depiction === undefined) return;
const atomName = e.detail.name; // CustomEvent
const atom = this.depiction.atoms.filter(x => x.value >0 && x.name === atomName);
if (atom.length > 0) {
this.depiction.atomMouseEnterEventHandler(atom[0], true);
} else {
this.depiction.atomMouseLeaveEventHandler(false);
}
}
private ligHeatmapMouseoutEventHandler() {
if (this.depiction === undefined) return;
this.depiction.atomMouseLeaveEventHandler(true);
}
/** /**
* Handles mouse leave molstar event. Removes interaction node highlight * Handles mouse leave molstar event. Removes interaction node highlight
...@@ -260,7 +290,7 @@ class Visualization { ...@@ -260,7 +290,7 @@ class Visualization {
* PDBeChem process. * PDBeChem process.
* *
* @param {string} ligandId * @param {string} ligandId
* @returns * @param {boolean} withNames true for displaying atom names
* @memberof Visualization * @memberof Visualization
*/ */
public async initLigandDisplay(ligandId: string, withNames: boolean = false) { public async initLigandDisplay(ligandId: string, withNames: boolean = false) {
...@@ -272,19 +302,50 @@ class Visualization { ...@@ -272,19 +302,50 @@ class Visualization {
.then(() => this.centerScene()); .then(() => this.centerScene());
} }
/**
* Download aggregated protein-ligand interactions data.
*
* @param {string} ligandId
* @memberof Visualization
*/
public async initLigandWeights(ligandId: string){
const weightUrl = `https://raw.githubusercontent.com/roshkjr/Learning-sources/main/${ligandId}_atom_residue_intx.json`
return d3.json(weightUrl)
.then((d: any) => this.ligandIntxData = d);
}
/** /**
* Add depiction to the canvas from external resource. * Add depiction to the canvas from external resource.
* *
* @param {*} depiction Content of annotation.json file generated by * @param {any} depiction Content of annotation.json file generated by
* the PDBeChem process. * the PDBeChem process.
* @param {boolean} withNames true for displaying atom names
* @memberof Visualization * @memberof Visualization
*/ */
public addDepiction(depiction: any, withNames: boolean) { public addDepiction(depiction: any, withNames: boolean) {
this.depiction = new Depiction(this.depictionRoot, depiction); this.depiction = new Depiction(this.parent, this.depictionRoot, depiction);
this.depiction.draw(withNames); this.depiction.draw(withNames);
} }
/**
* Adds circles around atoms higlighting the weights of atoms.
*
* @param {string} contactType
* @memberof Visualization
*/
public showWeights(contactType: string[]){
if ((this.depiction === undefined) || (this.ligandIntxData) === undefined) return;
const atomPropensity= new Model.LigandIntx(this.ligandIntxData, contactType).getAtomIntxPropensity();
const colorScheme = "Greens";
this.depiction.addCircles(atomPropensity, colorScheme);
if(this.zoomHandler !== undefined){
this.zoomHandler(this.svg, d3.zoomIdentity)
};
}
/** /**
* Show depiction with/without atom names * Show depiction with/without atom names
...@@ -312,26 +373,16 @@ class Visualization { ...@@ -312,26 +373,16 @@ class Visualization {
* @memberof Visualization * @memberof Visualization
*/ */
public addLigandHighlight(highlight: string[], color: string = undefined) { public addLigandHighlight(highlight: string[], color: string = undefined) {
if (!this.depiction) return;
this.depiction.highlightSubgraph(highlight, color); this.depiction.highlightSubgraph(highlight, color);
} }
/**
* Add contours to the ligand structure. The previous contours are
* going to be removed.
*
* @param {*} data
* @memberof Visualization
*/
public addContours(data: any) {
this.depiction.addContour(data);
}
/** /**
* Add ligand interactions to the canvas * Add ligand interactions to the canvas
* *
* @param {*} data Data content of the API end point * @param {*} data Data content of the API end point
* /pdb/bound_ligand_interactions * /pdb/bound_ligand_interactions
* @param {boolean} true if atom names to be displayed
* @memberof Visualization * @memberof Visualization
*/ */
public addLigandInteractions(data: any, withNames: boolean = false) { public addLigandInteractions(data: any, withNames: boolean = false) {
...@@ -356,7 +407,7 @@ class Visualization { ...@@ -356,7 +407,7 @@ class Visualization {
/** /**
* Add bound molecule interactions to the canvas. * Add bound molecule interactions to the canvas.
* *
* @param {*} data Data content of the API end point * @param {any} data Data content of the API end point
* /pdb/bound_molecule_interactions * /pdb/bound_molecule_interactions
* @param {string} bmId Bound molecule id * @param {string} bmId Bound molecule id
* @memberof Visualization * @memberof Visualization
...@@ -376,6 +427,7 @@ class Visualization { ...@@ -376,6 +427,7 @@ class Visualization {
// #region menu functions // #region menu functions
/** /**
* Export scene into an SVG components. It relies on the availability * Export scene into an SVG components. It relies on the availability
* of the external CSS for SVG styling. Otherwise it does not work. * of the external CSS for SVG styling. Otherwise it does not work.
...@@ -611,6 +663,7 @@ class Visualization { ...@@ -611,6 +663,7 @@ class Visualization {
this.parent.dispatchEvent(e); this.parent.dispatchEvent(e);
} }
// #endregion fire events // #endregion fire events
...@@ -668,7 +721,6 @@ class Visualization { ...@@ -668,7 +721,6 @@ class Visualization {
* @param {Model.InteractionNode} n Interaction node user clicked to * @param {Model.InteractionNode} n Interaction node user clicked to
* @param {number} i index o the interaction node * @param {number} i index o the interaction node
* @param {*} g group of interaction nodes * @param {*} g group of interaction nodes
* @returns
* @memberof Visualization * @memberof Visualization
*/ */
private selectLigand(n: Model.InteractionNode, i: number, g: any) { private selectLigand(n: Model.InteractionNode, i: number, g: any) {
...@@ -783,7 +835,7 @@ class Visualization { ...@@ -783,7 +835,7 @@ class Visualization {
/** /**
* Setup display of interactions for bound molecule. * Setup display of interactions for bound molecule.
* * This includes: setup of links, nodes, simulation and subscribing to relevant events. * This includes: setup of links, nodes, simulation and subscribing to relevant events.
* No depiction is required for this step. * No depiction is required for this step.
* *
* @private * @private
......
...@@ -59,6 +59,8 @@ namespace Model { ...@@ -59,6 +59,8 @@ namespace Model {
/** /**
* Data model representing a single residue, which is a part of the * Data model representing a single residue, which is a part of the
* bound molecule. This residue is unique in the entire binding site. * bound molecule. This residue is unique in the entire binding site.
* @param {any} data
* @param {boolean} isLigand true if the residue is a ligand
*/ */
export class Residue { export class Residue {
id: string id: string
...@@ -496,4 +498,114 @@ namespace Model { ...@@ -496,4 +498,114 @@ namespace Model {
} }
} }
export class LigandIntx{
data: any;
contactTypes: string[];
filteredData: any;
constructor(data: any, contactTypes:string[]){
this.data = data;
this.contactTypes = contactTypes;
this.filteredData = this.getFilteredData();
}
private getAtomResidueObj(x: string[]){
return {
"atom": x[0],
"AA": x[1],
"count": x[2]
}
}
private getFilteredData(){
const filteredData = new Array();
for (const contactType in this.data){
if (this.contactTypes.includes(contactType)){
filteredData.push(...this.data[contactType].map(this.getAtomResidueObj));
}
}
return filteredData
}
public getAtomIntxPropensity(){
const atomCount = new Array();
this.filteredData.reduce(function(acc, currentValue){
if(!acc[currentValue.atom]){
acc[currentValue.atom] = {"atom": currentValue.atom, "count": 0};
atomCount.push(acc[currentValue.atom]);
}
acc[currentValue.atom].count += currentValue.count;
return acc
},{});
const totalIntx = atomCount.reduce(function(acc, currentValue){
acc += currentValue.count;
return acc;
}, 0)
const atomPropensity = atomCount.map((x) =>
({"atom": x.atom,
"value": (x.count/totalIntx).toFixed(2)
})
);
return atomPropensity
}
}
/**
* Data model representing scale of a circles
* Stores scale for radius and color
*/
export class Scale{
radiusScale: any;
colorScale: any;
constructor(radiusScale:any, colorScale:any){
this.radiusScale = radiusScale;
this.colorScale = colorScale;
}
}
/**
* Gradient object with three
* level scales for circles to highlight
* @param {any} weight
* @param {string} colorScheme color to be used for generating gradient
*/
export class Gradient {
weight: any;
colorScheme: string;
constructor(weight: any, colorScheme:string){
this.weight = weight;
this.colorScheme = colorScheme;
}
/**
* Generates three level scales for the
* Gradient object
*/
public getScales(){
const color = d3[`scheme${this.colorScheme}`][9];
const weightMax = Number(d3.max(this.weight));
const gradient = {firstScale: new Scale(d3.scaleLinear([0, weightMax], [20, 30]),
d3.scaleLinear([0,weightMax], ["#FFFFFF", color[4]])),
secondScale: new Scale(d3.scaleLinear([0,weightMax], [10, 20]),
d3.scaleLinear([0, weightMax], [color[5], color[7]])),
thirdScale: new Scale(d3.scaleLinear([0, weightMax], [2, 10]),
d3.scaleLinear([0, weightMax], [color[8], color[9]]))
};
return gradient
}
}
} }
\ No newline at end of file
...@@ -45,7 +45,7 @@ class ResidueProvider { ...@@ -45,7 +45,7 @@ class ResidueProvider {
* Get single letter abbreviation of the ligand. * Get single letter abbreviation of the ligand.
* *
* @param {string} name Name of the chemical compound * @param {string} name Name of the chemical compound
* @returns Single letter abbreviation of the ligand * @returns {string} Single letter abbreviation of the ligand
* @memberof ResidueProvider * @memberof ResidueProvider
*/ */
public getAminoAcidAbbreviation(name: string): string { public getAminoAcidAbbreviation(name: string): string {
...@@ -57,7 +57,6 @@ class ResidueProvider { ...@@ -57,7 +57,6 @@ class ResidueProvider {
* Fetch single letter abbreviations from API if they are not present * Fetch single letter abbreviations from API if they are not present
* *
* @param {string} n * @param {string} n
* @returns
* @memberof ResidueProvider * @memberof ResidueProvider
*/ */
public downloadAnnotation(r: Model.Residue): void { public downloadAnnotation(r: Model.Residue): void {
......
...@@ -128,7 +128,6 @@ namespace Resources { ...@@ -128,7 +128,6 @@ namespace Resources {
* @param {string} chainId * @param {string} chainId
* @param {number} resId * @param {number} resId
* @param {Model.Environment} env * @param {Model.Environment} env
* @returns
*/ */
export function ligandInteractionsAPI(pdbId: string, chainId: string, resId: number, env: Model.Environment) { export function ligandInteractionsAPI(pdbId: string, chainId: string, resId: number, env: Model.Environment) {
let url = ''; let url = '';
......
...@@ -114,6 +114,9 @@ let helpBonds = ` ...@@ -114,6 +114,9 @@ let helpBonds = `
// #endregion help // #endregion help
/**
* @class UI
*/
class UI { class UI {
...@@ -143,7 +146,6 @@ class UI { ...@@ -143,7 +146,6 @@ class UI {
* *
* @param {Config.UIParameters} p Object with annotation which * @param {Config.UIParameters} p Object with annotation which
* UI elements should be created. * UI elements should be created.
* @returns
* @memberof UI * @memberof UI
*/ */
public register(p: Config.UIParameters) { public register(p: Config.UIParameters) {
...@@ -263,6 +265,8 @@ class UI { ...@@ -263,6 +265,8 @@ class UI {
this.parent.addEventListener(Config.interactionClickEvent, e => this.nodeMouseEnterEventHandler(e)); this.parent.addEventListener(Config.interactionClickEvent, e => this.nodeMouseEnterEventHandler(e));
this.parent.addEventListener(Config.interactionMouseoverEvent, e => this.nodeMouseEnterEventHandler(e)); this.parent.addEventListener(Config.interactionMouseoverEvent, e => this.nodeMouseEnterEventHandler(e));
this.parent.addEventListener(Config.interactionMouseoutEvent, () => this.nodeMouseLeaveEventHandler()); this.parent.addEventListener(Config.interactionMouseoutEvent, () => this.nodeMouseLeaveEventHandler());
this.parent.addEventListener(Config.LigandShowAtomEvent, e => this.nodeMouseEnterEventHandler(e));
this.parent.addEventListener(Config.LigandHideAtomEvent, () => this.nodeMouseLeaveEventHandler());
} }
if (this.residueLabel !== undefined) { if (this.residueLabel !== undefined) {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
"declaration": true, "declaration": true,
"module": "none", "module": "none",
"moduleResolution": "node", "moduleResolution": "node",
"out": "build/pdb-ligand-env-plugin.js" "outFile": "build/pdb-ligand-env-plugin.js"
}, },
"include": ["src/plugin/**/*", ], "include": ["src/plugin/**/*", ],
"exclude": [ "exclude": [
......