Skip to content
Snippets Groups Projects
Commit ffeb391c authored by Lukas Pravda's avatar Lukas Pravda
Browse files

Merge branch 'dev'

parents 1265a35d 6b6a5fca
No related branches found
No related tags found
No related merge requests found
Pipeline #105124 passed with stages
in 1 minute and 18 seconds
.vscode .vscode
.DS_Store
.mypy_cache .mypy_cache
node_modules node_modules
......
...@@ -12,4 +12,5 @@ pages: ...@@ -12,4 +12,5 @@ pages:
paths: paths:
- public - public
only: only:
- dev
- master - master
...@@ -40,6 +40,9 @@ A few files needs to be imported in the page before the component is attempted t ...@@ -40,6 +40,9 @@ A few files needs to be imported in the page before the component is attempted t
<!-- CSS style to be used for scene drawing (required for saving SVGs.) --> <!-- CSS style to be used for scene drawing (required for saving SVGs.) -->
<link rel="stylesheet" href="pdb-ligand-env-svg.css" /> <link rel="stylesheet" href="pdb-ligand-env-svg.css" />
<!-- CSS style to be used for the component UI -->
<link rel="stylesheet" href="pdb-ligand-env.css" />
<!-- UI icons --> <!-- UI icons -->
<link rel="stylesheet" href="https://ebi.emblstatic.net/web_guidelines/EBI-Icon-fonts/v1.3/fonts.css" /> <link rel="stylesheet" href="https://ebi.emblstatic.net/web_guidelines/EBI-Icon-fonts/v1.3/fonts.css" />
...@@ -49,7 +52,7 @@ A few files needs to be imported in the page before the component is attempted t ...@@ -49,7 +52,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.2.0-min.js"></script> <script type="module" src="pdb-ligand-env-component-0.3.0-min.js"></script>
``` ```
#### A) Ligand interactions #### A) Ligand interactions
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js" <script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"
charset="utf-8"></script> charset="utf-8"></script>
<!--PDBe interactions component--> <!--PDBe interactions component-->
<script type="module" src="pdb-ligand-env-component-0.2.0-min.js"></script> <script type="module" src="pdb-ligand-env-component-0.3.0-min.js"></script>
</head> </head>
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
<!-- MOL* --> <!-- MOL* -->
<link rel="stylesheet" type="text/css" <link rel="stylesheet" type="text/css"
href="https://wwwdev.ebi.ac.uk/pdbe/pdb-component-library/v1.0/css/molstar-light-0.0.1.css"> href="https://www.ebi.ac.uk/pdbe/pdb-component-library/css/pdbe-molstar-1.1.0.css">
<script src="https://wwwdev.ebi.ac.uk/pdbe/pdb-component-library/v1.0/js/molstar-0.0.1.js"></script> <script src="https://www.ebi.ac.uk/pdbe/pdb-component-library/js/pdbe-molstar-plugin-1.1.0.js"></script>
<!-- Web component polyfill (only loads what it needs) --> <!-- Web component polyfill (only loads what it needs) -->
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/webcomponents-lite.js" charset="utf-8"> <script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/webcomponents-lite.js" charset="utf-8">
...@@ -18,17 +18,17 @@ ...@@ -18,17 +18,17 @@
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js" <script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"
charset="utf-8"></script> charset="utf-8"></script>
<script type="module" src="pdb-ligand-env-component-0.2.0-min.js"></script> <script type="module" src="pdb-ligand-env-component-0.3.0-min.js"></script>
<script> <script>
var renderBmInteractions = function (id, bmId) { var renderBmInteractions = function (id, bmId) {
var int = var int =
`<pdb-ligand-env style="border: 1px solid black" pdb-id="${id}" bound-molecule-id="${bmId}"></pdb-ligand-env>` `<pdb-ligand-env style="border: 1px solid black" pdb-id="${id}" bound-molecule-id="${bmId}" environment="dev"></pdb-ligand-env>`
document.getElementById('rt').innerHTML = int; document.getElementById('rt').innerHTML = int;
}; };
var renderLigandInteractions = function (id, chain, resId) { var renderLigandInteractions = function (id, chain, resId) {
var int = var int =
`<pdb-ligand-env style="border: 1px solid black" pdb-id="${id}" pdb-chain-id="${chain}" pdb-res-id="${resId}" zoom-on></pdb-ligand-env>` `<pdb-ligand-env style="border: 1px solid black" pdb-id="${id}" pdb-chain-id="${chain}" pdb-res-id="${resId}" zoom-on environment="dev"></pdb-ligand-env>`
document.getElementById('rt').innerHTML = int; document.getElementById('rt').innerHTML = int;
}; };
...@@ -42,9 +42,9 @@ ...@@ -42,9 +42,9 @@
if (result.bmid === undefined) { if (result.bmid === undefined) {
result['query'] = result['query'] =
`https://wwwdev.ebi.ac.uk/pdbe/coordinates/${result.pdbid}/ligandInteraction?&authAsymId=$${result.chain}&authSeqNumber=${result.resid}&radius=5&dataSource=hydrogens` `https://www.ebi.ac.uk/pdbe/model-server/v1/${result.pdbid}/residueInteraction?auth_asym_id=${result.chain}&auth_seq_id=${result.resid}&radius=5&data_source=pdb-h`
} else { } else {
result['query'] = `https://wwwdev.ebi.ac.uk/pdbe/coordinates/${result.pdbid}?dataSource=hydrogens` result['query'] = `https://www.ebi.ac.uk/pdbe/model-server/v1/${result.pdbid}/full?data_source=pdb-h`
} }
if (result.chain !== undefined) result.chain = result.chain.toUpperCase(); if (result.chain !== undefined) result.chain = result.chain.toUpperCase();
...@@ -64,9 +64,9 @@ ...@@ -64,9 +64,9 @@
} else { } else {
params = { params = {
pdbid: '1cbs', pdbid: '1cbs',
chain: 'A', chain: 'A_1',
resid: 200, resid: 200,
query: "https://wwwdev.ebi.ac.uk/pdbe/coordinates/1cbs/ligandInteraction?&authAsymId=$A&authSeqNumber=$200&radius=5&dataSource=hydrogens" query: "https://www.ebi.ac.uk/pdbe/model-server/v1/1cbs/residueInteraction?auth_asym_id=A_1&auth_seq_id=200&radius=5&data_source=pdb-h"
}; };
} }
...@@ -78,32 +78,27 @@ ...@@ -78,32 +78,27 @@
var initParams = { var initParams = {
moleculeId: params.pdbid, moleculeId: params.pdbid,
pdbeUrl: 'https://wwwdev.ebi.ac.uk/pdbe/', pdbeUrl: 'https://www.ebi.ac.uk/pdbe/',
loadMaps: true, loadMaps: false,
validationAnnotation: true, bgColor: {
domainAnnotation: true, r: 255,
g: 250,
b: 250
},
lowPrecisionCoords: true, lowPrecisionCoords: true,
isExpanded: false, isExpanded: false,
hideControls: true, hideControls: true,
showLogs: false, showLogs: false,
subscribeEvents: true, subscribeEvents: true,
showPDBeLogo: false, showPDBeLogo: false,
assemblyId: 'preferred', //'deposited' subscribeEvents: true,
// selectInteraction: false,
ligandView: { ligandView: {
auth_asym_Id: params.chain,
auth_seq_id: params.resid, auth_seq_id: params.resid,
auth_asym_id: params.chain,
hydrogens: true hydrogens: true
},
backgroundColour: '0xFFFFFF',
//customColorList: [0xff0000, 0x0000ff],
//representationStyle: representationStyle//,
customData: {
url: `https://wwwdev.ebi.ac.uk/pdbe/coordinates/${params.pdbid}/ligandInteraction?&authAsymId=${params.chain}&authSeqNumber=${params.resid}&radius=5&dataSource=hydrogens`,
format: 'cif'
} }
} }
var pdbeMolstar = new MolStarPdbeWrapper(); var pdbeMolstar = new PDBeMolstarPlugin();
pdbeMolstar.render(document.getElementById('3dViewer'), initParams); pdbeMolstar.render(document.getElementById('3dViewer'), initParams);
}); });
}()); }());
......
This diff is collapsed.
{ {
"name": "pdb-ligand-env", "name": "pdb-ligand-env",
"version": "0.2.0", "version": "0.3.0",
"description": "", "description": "",
"main": "app.js", "main": "app.js",
"dependencies": { "dependencies": {
"@types/d3": "^5.0.1", "@types/d3": "^5.16.3",
"@types/d3-tip": "^3.5.5", "@types/d3-tip": "^3.5.5",
"d3": "^5.15.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.2.1", "lit-element": "^2.4.0",
"typescript": "^3.7.4" "typescript": "^4.0.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.8.3", "@babel/core": "^7.12.3",
"@babel/plugin-transform-runtime": "^7.8.3", "@babel/plugin-transform-runtime": "^7.12.1",
"@babel/preset-env": "^7.8.3", "@babel/preset-env": "^7.12.1",
"@babel/runtime": "^7.8.3", "@babel/runtime": "^7.12.1",
"@webcomponents/webcomponentsjs": "^2.4.1", "@webcomponents/webcomponentsjs": "^2.5.0",
"babel-loader": "^8.0.5", "babel-loader": "^8.1.0",
"browser-sync": "^2.26.7", "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",
"css-loader": "^2.1.0", "css-loader": "^2.1.0",
...@@ -32,12 +32,12 @@ ...@@ -32,12 +32,12 @@
"gulp-minify": "^3.1.0", "gulp-minify": "^3.1.0",
"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.0", "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": "^4.41.5", "webpack": "^5.2.0",
"webpack-cli": "^3.3.10" "webpack-cli": "^3.3.12"
}, },
"scripts": { "scripts": {
"tscW": "tsc -w", "tscW": "tsc -w",
......
...@@ -38,10 +38,19 @@ class Depiction { ...@@ -38,10 +38,19 @@ class Depiction {
this.atoms = data.atoms.map(x => new Atom(x)); this.atoms = data.atoms.map(x => new Atom(x));
this.bonds = new Array<Bond>(); this.bonds = new Array<Bond>();
let bds = new Set<string>();
data.bonds.forEach(x => { data.bonds.forEach(x => {
var atomA = this.atoms.find(e => e.name == x.bgn); let atomA = this.atoms.find(e => e.name == x.bgn);
var atomB = this.atoms.find(e => e.name == x.end); let atomB = this.atoms.find(e => e.name == x.end);
var bond = new Bond(atomA, atomB, x.coords, x.style); let bond = new Bond(atomA, atomB, x.coords, x.style);
let bondFlag = [atomA.name, atomB.name].sort().join("_");
if (!bds.has(bondFlag)) {
bds.add(bondFlag);
atomA.connectivity++;
atomB.connectivity++;
}
this.bonds.push(bond); this.bonds.push(bond);
}); });
...@@ -67,16 +76,9 @@ class Depiction { ...@@ -67,16 +76,9 @@ class Depiction {
} }
// ideally we want to find an atom which is part just a single bond to get nice initial position. // ideally we want to find an atom which is part just a single bond to get nice initial position.
// If there is no such atom any will do // If there is no such atom any will do
let searchStruct = new Map<string, number>();
this.bonds.forEach(x => {
searchStruct.set(x.bgn.name, searchStruct.get(x.bgn.name) === undefined ? 1 : searchStruct.get(x.bgn.name) + 1);
searchStruct.set(x.end.name, searchStruct.get(x.end.name) === undefined ? 1 : searchStruct.get(x.end.name) + 1);
});
searchStruct = this.sortMap(searchStruct); // ascending order so we hit those with less partners sooner.
let thisAtomName = [...searchStruct.keys()].find(x => atomNames.findIndex(y => y === x) !== -1) let atoms = this.atoms.filter(x => atomNames.includes(x.name)).sort((x, y) => x.connectivity - y.connectivity);
let thisAtom = this.atoms.find(x => x.name === thisAtomName); let thisAtom = atoms[0];
let bond = this.bonds.find(x => x.containsAtom(thisAtom)); let bond = this.bonds.find(x => x.containsAtom(thisAtom));
let otherAtom = bond.getOtherAtom(thisAtom); let otherAtom = bond.getOtherAtom(thisAtom);
...@@ -88,10 +90,9 @@ class Depiction { ...@@ -88,10 +90,9 @@ class Depiction {
return new Vector2D(x, y); return new Vector2D(x, y);
} }
public draw(withClarityNodes: boolean = false) { public draw() {
this.structure.selectAll("*").remove(); this.structure.selectAll("*").remove();
if (withClarityNodes) this.appendClarityNodes();
this.appendBondVisuals(); this.appendBondVisuals();
this.appendTexts(); this.appendTexts();
} }
...@@ -154,16 +155,24 @@ class Depiction { ...@@ -154,16 +155,24 @@ class Depiction {
* @memberof Depiction * @memberof Depiction
*/ */
private appendTexts(): void { private appendTexts(): void {
let data = this.atoms
.filter(x => x.labels.length > 0)
?.map(x => x.labels)
?.reduce((a, b) => a.concat(b));
this.structure.selectAll() this.structure.selectAll()
.data(this.atoms.filter(x => Object.keys(x.labels).length !== 0).map(x => x.labels).reduce((a, b) => a.concat(b))) .data(data)
.enter() .enter()
.append('text') .append('text')
.attr('filter', "url(#solid-background)")
.attr('style', (x: any) => x.style) .attr('style', (x: any) => x.style)
.attr('x', (x: any) => x.x) .attr('x', (x: any) => x.x)
.attr('y', (x: any) => x.y) .attr('y', (x: any) => x.y)
.attr('dominant-baseline', (x: any) => x['dominant-baseline']) .attr('dominant-baseline', (x: any) => x['dominant-baseline'])
.attr('text-anchor', (x: any) => x['text-anchor']) .attr('text-anchor', (x: any) => x['text-anchor'])
.each(function (x: any) { .each(function (x: any) {
for (var i = 0; i < x.tspans.length; i++) { for (var i = 0; i < x.tspans.length; i++) {
d3.select(this) d3.select(this)
.append('tspan') .append('tspan')
...@@ -173,23 +182,6 @@ class Depiction { ...@@ -173,23 +182,6 @@ class Depiction {
}); });
} }
/**
* Add small white circle on the background of atoms with label
* just to make the interaction lines pretty.
*
* @memberof Depiction
*/
private appendClarityNodes(): void {
this.structure.selectAll()
.data(this.atoms.filter(x => Object.keys(x.labels).length != 0))
.enter().append('circle')
.classed('pdb-lig-env-svg-shadow-node', true)
.attr('cx', (x: any) => x.position.x)
.attr('cy', (x: any) => x.position.y)
.attr('r', 15);
}
public getCenter(ids: string[]): Vector2D { public getCenter(ids: string[]): Vector2D {
let coords = new Array<Vector2D>(); let coords = new Array<Vector2D>();
...@@ -241,10 +233,13 @@ class Atom { ...@@ -241,10 +233,13 @@ class Atom {
name: string; name: string;
labels: any; labels: any;
position: Vector2D; position: Vector2D;
connectivity: 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;
} }
/** /**
...@@ -347,7 +342,6 @@ class Bond { ...@@ -347,7 +342,6 @@ class Bond {
coords: string; coords: string;
style: string; style: string;
/** /**
*Creates an instance of the bond. *Creates an instance of the bond.
* @param {Atom} a * @param {Atom} a
...@@ -358,7 +352,7 @@ class Bond { ...@@ -358,7 +352,7 @@ class Bond {
this.bgn = a; this.bgn = a;
this.end = b; this.end = b;
this.coords = coords; this.coords = coords;
this.style = style.replace("stroke-width:2px", "stroke-width:4px");; this.style = style.replace("stroke-width:2px", "stroke-width:4px");
} }
......
This diff is collapsed.
...@@ -15,14 +15,14 @@ namespace Model { ...@@ -15,14 +15,14 @@ namespace Model {
GroupGroup GroupGroup
} }
/** /**
* What environment should be used * What environment should be used
* *
* @export * @export
* @enum {number} * @enum {number}
*/ */
export enum Environment { export enum Environment {
Production, Production,
Development, Development,
Internal Internal
...@@ -149,7 +149,18 @@ namespace Model { ...@@ -149,7 +149,18 @@ namespace Model {
} }
public toString(): string { public toString(): string {
return `${this.residue.chemCompId} ${this.residue.chainId} ${this.residue.authorResidueNumber}${this.residue.authorInsertionCode}`; let r = this.residue;
let splitted = r.chainId.split('_');
let chainStr = splitted[0];
let symString = "";
if (splitted.length > 1) {
symString = splitted[1] !== "1"? `[${splitted[1]}]` : "";
}
let str = `${r.chemCompId} | ${chainStr}${symString} | ${r.authorResidueNumber}${r.authorInsertionCode}`;
return str;
} }
public toTooltip(): string { public toTooltip(): string {
...@@ -157,23 +168,49 @@ namespace Model { ...@@ -157,23 +168,49 @@ namespace Model {
} }
} }
export interface Link { export abstract class Link {
source: InteractionNode; public source: InteractionNode;
target: InteractionNode; public target: InteractionNode;
constructor(source: InteractionNode, target: InteractionNode) {
this.source = source;
this.target = target;
}
public containsBothNodes(a: InteractionNode, b: InteractionNode): boolean {
let condA = this.source.equals(a) && this.target.equals(b);
let condB = this.source.equals(b) && this.target.equals(a);
return condA || condB;
}
public containsNode(node: InteractionNode) {
return this.source.equals(node) || this.target.equals(node);
}
getLinkClass(): string; public containsResidue(n: Residue): boolean {
hasClash(): boolean; return (this.target.residue.equals(n) || this.source.residue.equals(n));
toTooltip(): string; }
public getOtherNode(node: InteractionNode) {
return this.source.equals(node) ? this.target : this.source;
}
abstract getLinkClass(): string;
abstract hasClash(): boolean;
abstract toTooltip(): string;
} }
export class ResidueResidueLink implements Link { export class ResidueResidueLink extends Link {
target: InteractionNode; target: InteractionNode;
source: InteractionNode source: InteractionNode
interactions: Map<InteractionType, Array<string>>; interactions: Map<InteractionType, Array<string>>;
constructor(source: InteractionNode, target: InteractionNode, interactions: any) { constructor(source: InteractionNode, target: InteractionNode, interactions: any) {
this.source = source; super(source, target);
this.target = target;
this.interactions = new Map<InteractionType, Array<string>>(); this.interactions = new Map<InteractionType, Array<string>>();
Object.keys(interactions).forEach(x => { Object.keys(interactions).forEach(x => {
...@@ -182,14 +219,6 @@ namespace Model { ...@@ -182,14 +219,6 @@ namespace Model {
}); });
} }
/**
* Checks if the link contains a given node.
*/
public containsNode(n: InteractionNode): boolean {
return this.target.equals(n) || this.source.equals(n);
}
public hasClash(): boolean { public hasClash(): boolean {
this.interactions.forEach(x => { this.interactions.forEach(x => {
if (x.includes('clash')) { if (x.includes('clash')) {
...@@ -199,17 +228,6 @@ namespace Model { ...@@ -199,17 +228,6 @@ namespace Model {
return false; return false;
} }
/**
* Shorthand to check if the link contains particular underlying
* residue.
*/
public containsResidue(n: Residue): boolean {
return (this.target.residue.equals(n) || this.source.residue.equals(n));
}
public isBoundMoleculeLink(): boolean { public isBoundMoleculeLink(): boolean {
return this.source.residue.isLigand && this.target.residue.isLigand && this.interactions.get(InteractionType.AtomAtom).includes('covalent'); return this.source.residue.isLigand && this.target.residue.isLigand && this.interactions.get(InteractionType.AtomAtom).includes('covalent');
} }
...@@ -245,30 +263,20 @@ namespace Model { ...@@ -245,30 +263,20 @@ namespace Model {
} }
export class LigandResidueLink implements Link { export class LigandResidueLink extends Link {
source: InteractionNode;
target: InteractionNode;
interaction: Array<Interaction>; interaction: Array<Interaction>;
constructor(begin: InteractionNode, end: InteractionNode, beginAtoms: string[], endAtoms: string[], constructor(begin: InteractionNode, end: InteractionNode, beginAtoms: string[], endAtoms: string[],
interactionType: string, interactionDetails: string[], distance: number) { interactionType: string, interactionDetails: string[], distance: number) {
this.source = begin; super(begin, end);
this.target = end;
this.interaction = new Array<Interaction>(); this.interaction = new Array<Interaction>();
this.interaction.push( this.interaction.push(
new Interaction(beginAtoms, endAtoms, InteractionTypeUtil.parse(interactionType.replace('-', '_')), interactionDetails, distance) new Interaction(beginAtoms, endAtoms, InteractionTypeUtil.parse(interactionType.replace('-', '_')), interactionDetails, distance)
); );
} }
public containsBothNodes(a: InteractionNode, b: InteractionNode): boolean {
let condA = this.source.equals(a) && this.target.equals(b);
let condB = this.source.equals(b) && this.target.equals(a);
return condA || condB;
}
public addInteraction(beginAtoms: string[], endAtoms: string[], interactionType: string, interactionDetails: string[], distance: number): void { public addInteraction(beginAtoms: string[], endAtoms: string[], interactionType: string, interactionDetails: string[], distance: number): void {
this.interaction.push( this.interaction.push(
new Interaction(beginAtoms, endAtoms, InteractionTypeUtil.parse(interactionType.replace('-', '_')), interactionDetails, distance) new Interaction(beginAtoms, endAtoms, InteractionTypeUtil.parse(interactionType.replace('-', '_')), interactionDetails, distance)
...@@ -293,10 +301,6 @@ namespace Model { ...@@ -293,10 +301,6 @@ namespace Model {
return 'other'; return 'other';
} }
public containsInteractionNode(node: InteractionNode) {
return this.source.equals(node) || this.target.equals(node);
}
public hasClash(): boolean { public hasClash(): boolean {
this.interaction.forEach(x => { this.interaction.forEach(x => {
x.interactionsClases.forEach(y => { x.interactionsClases.forEach(y => {
...@@ -371,6 +375,19 @@ namespace Model { ...@@ -371,6 +375,19 @@ namespace Model {
this.links.push(link); this.links.push(link);
}); });
let searchableNodes = Array.from(this.tmpNodesSet);
data.composition.connections.forEach(pair => {
let bgn = searchableNodes.find(x => x.residue.id === pair[0]);
let end = searchableNodes.find(x => x.residue.id === pair[1]);
let result = this.links.find(x => x.containsBothNodes(bgn, end));
if (result === undefined) {
let link = new ResidueResidueLink(bgn, end, { 'atom_atom': ['covalent'] });
this.links.push(link);
}
});
this.interactionNodes = Array.from(this.tmpNodesSet.values()); this.interactionNodes = Array.from(this.tmpNodesSet.values());
return this; return this;
...@@ -424,7 +441,7 @@ namespace Model { ...@@ -424,7 +441,7 @@ namespace Model {
return; // we do not want to show 'self interactions' return; // we do not want to show 'self interactions'
} }
let tmpLink = tmpLinks.find(x => (<LigandResidueLink>x).containsBothNodes(bgnNode, endNode)) as LigandResidueLink; let tmpLink = tmpLinks.find(x => x.containsBothNodes(bgnNode, endNode));
if (tmpLink !== undefined) { if (tmpLink !== undefined) {
tmpLink.addInteraction(x.ligand_atoms, x.end.atom_names, x.interaction_type, x.interaction_details, x.distance); tmpLink.addInteraction(x.ligand_atoms, x.end.atom_names, x.interaction_type, x.interaction_details, x.distance);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
class ResidueProvider { class ResidueProvider {
private static instance: ResidueProvider; private static instance: ResidueProvider;
private environment: Model.Environment;
private mapping: Map<string, string>; private mapping: Map<string, string>;
public downloadPromises: Array<Promise<any>>; public downloadPromises: Array<Promise<any>>;
...@@ -14,7 +15,8 @@ class ResidueProvider { ...@@ -14,7 +15,8 @@ class ResidueProvider {
* construction calls with the `new` operator. * construction calls with the `new` operator.
* @memberof ResidueProvider * @memberof ResidueProvider
*/ */
private constructor() { private constructor(env: Model.Environment) {
this.environment = env;
this.mapping = new Map<string, string>(Config.aaAbreviations); this.mapping = new Map<string, string>(Config.aaAbreviations);
this.downloadPromises = new Array<Promise<any>>(); this.downloadPromises = new Array<Promise<any>>();
} }
...@@ -30,9 +32,9 @@ class ResidueProvider { ...@@ -30,9 +32,9 @@ class ResidueProvider {
* @returns {ResidueProvider} * @returns {ResidueProvider}
* @memberof ResidueProvider * @memberof ResidueProvider
*/ */
public static getInstance(): ResidueProvider { public static getInstance(env: Model.Environment = Model.Environment.Production): ResidueProvider {
if (!ResidueProvider.instance) { if (!ResidueProvider.instance) {
ResidueProvider.instance = new ResidueProvider(); ResidueProvider.instance = new ResidueProvider(env);
} }
return ResidueProvider.instance; return ResidueProvider.instance;
...@@ -61,7 +63,7 @@ class ResidueProvider { ...@@ -61,7 +63,7 @@ class ResidueProvider {
public downloadAnnotation(r: Model.Residue): void { public downloadAnnotation(r: Model.Residue): void {
if (this.mapping.has(r.chemCompId) || r.isLigand) return; if (this.mapping.has(r.chemCompId) || r.isLigand) return;
let url = Resources.residueTypeAPI(r.chemCompId); let url = Resources.residueTypeAPI(r.chemCompId, this.environment);
let res = d3.json(url).then(x => { let res = d3.json(url).then(x => {
let code = x[r.chemCompId][0].one_letter_code; let code = x[r.chemCompId][0].one_letter_code;
this.mapping.set(r.chemCompId, code); this.mapping.set(r.chemCompId, code);
......
namespace Resources { namespace Resources {
export const productionAPI: string = 'https://www.ebi.ac.uk/pdbe/graph-api'; export const productionAPI: string = 'https://www.ebi.ac.uk/pdbe';
export const devAPI: string = 'https://wwwdev.ebi.ac.uk/pdbe/graph-api'; export const devAPI: string = 'https://wwwdev.ebi.ac.uk/pdbe';
export const intAPI: string = 'https://wwwint.ebi.ac.uk/pdbe/graph-api'; export const intAPI: string = 'https://wwwint.ebi.ac.uk/pdbe';
// export const glycanSymbols: string = 'https://pdbe.gitdocs.ebi.ac.uk/web-components/ligand-env/pdb-snfg-visuals.xml'; export const boundMoleculeURL: string = 'graph-api/pdb/bound_molecule_interactions';
// export const glycanMapping: string = 'https://pdbe.gitdocs.ebi.ac.uk/web-components/ligand-env/het_mapping.json'; export const carbohydrateURL: string = 'graph-api/pdb/carbohydrate_polymer_interactions';
// export const componentSvgCss: string = 'https://pdbe.gitdocs.ebi.ac.uk/web-components/ligand-env/pdb-ligand-env-svg.css'; export const boundLigandURL: string = 'graph-api/pdb/bound_ligand_interactions';
export const compoundSummaryURL: string = 'api/pdb/compound/summary';
export const componentLibraryURL: string = 'pdb-component-library/data/ligand-env';
export const staticFilesURL: string = 'static/files/pdbechem_v2';
export const glycanSymbols: string = 'https://www.ebi.ac.uk/pdbe/pdb-component-library/data/ligand-env/pdb-snfg-visuals.xml'; export function glycanSymbolsAPI(env: Model.Environment) {
export const glycanMapping: string = 'https://www.ebi.ac.uk/pdbe/pdb-component-library/data/het_mapping.json'; let url = '';
export const componentSvgCss: string = 'https://www.ebi.ac.uk/pdbe/pdb-component-library/data/pdb-ligand-env-svg.css'; switch (env) {
case Model.Environment.Internal:
case Model.Environment.Development: {
url = `${devAPI}/${componentLibraryURL}/pdb-snfg-visuals.xml`;
break;
}
default: {
url = `${productionAPI}/${componentLibraryURL}/pdb-snfg-visuals.xml`;
break;
}
}
return url;
}
export const residueTypeURL: string = "https://www.ebi.ac.uk/pdbe/api/pdb/compound/summary/";
export function ligandAnnotationAPI(ligandName: string, env: Model.Environment): string { export function hetMappingAPI(env: Model.Environment) {
let url = ''; let url = '';
switch (env) { switch (env) {
case Model.Environment.Production: { case Model.Environment.Internal:
url = `https://www.ebi.ac.uk/pdbe/static/files/pdbechem_v2/${ligandName}/annotation`; case Model.Environment.Development: {
break; url = `${devAPI}/${componentLibraryURL}/het_mapping.json`;
break;
} }
case Model.Environment.Development: default: {
url = `${productionAPI}/${componentLibraryURL}/het_mapping.json`;
break;
}
}
return url;
}
export function ligEnvCSSAPI(env: Model.Environment) {
let url = '';
switch (env) {
case Model.Environment.Internal: case Model.Environment.Internal:
url = `https://wwwdev.ebi.ac.uk/pdbe/static/files/pdbechem_v2/${ligandName}/annotation`; case Model.Environment.Development: {
url = `${devAPI}/pdb-component-library/css/pdb-ligand-env-svg.css`;
break;
}
default: {
url = `${productionAPI}/pdb-component-library/css/pdb-ligand-env-svg.css`;
break;
}
} }
return url; return url;
} }
export function boundMoleculeAPI(pdbId: string, bmId: string, env: Model.Environment): string {
export function ligandAnnotationAPI(ligandName: string, env: Model.Environment): string {
let url = ''; let url = '';
switch (env) { switch (env) {
case Model.Environment.Production: { case Model.Environment.Production: {
url = `${productionAPI}/pdb/bound_molecule_interactions/${pdbId}/${bmId}`; url = `${productionAPI}/${staticFilesURL}/${ligandName}/annotation`;
break; break;
} }
case Model.Environment.Development:
case Model.Environment.Internal:
url = `${devAPI}/${staticFilesURL}/${ligandName}/annotation`;
}
return url;
}
export function boundMoleculeAPI(pdbId: string, bmId: string, env: Model.Environment): string {
let url = '';
switch (env) {
case Model.Environment.Development: { case Model.Environment.Development: {
url = `${devAPI}/pdb/bound_molecule_interactions/${pdbId}/${bmId}`; url = `${devAPI}/${boundMoleculeURL}/${pdbId}/${bmId}`;
break; break;
} }
case Model.Environment.Internal: { case Model.Environment.Internal: {
url = `${intAPI}/pdb/bound_molecule_interactions/${pdbId}/${bmId}`; url = `${intAPI}/${boundMoleculeURL}/${pdbId}/${bmId}`;
break; break;
} }
default:
url = `${productionAPI}/${boundMoleculeURL}/${pdbId}/${bmId}`;
break;
} }
return url; return url;
} }
export function carbohydratePolymerAPI(pdbId: string, bmId: string, entityId: string, env: Model.Environment): string { export function carbohydratePolymerAPI(pdbId: string, bmId: string, entityId: string, env: Model.Environment): string {
let url = ''; let url = '';
switch (env) { switch (env) {
case Model.Environment.Production: {
url = `${productionAPI}/pdb/carbohydrate_polymer_interactions/${pdbId}/${bmId}/${entityId}`;
break;
}
case Model.Environment.Development: { case Model.Environment.Development: {
url = `${devAPI}/pdb/carbohydrate_polymer_interactions/${pdbId}/${bmId}/${entityId}`; url = `${devAPI}/${carbohydrateURL}/${pdbId}/${bmId}/${entityId}`;
break; break;
} }
case Model.Environment.Internal: { case Model.Environment.Internal: {
url = `${intAPI}/pdb/carbohydrate_polymer_interactions/${pdbId}/${bmId}/${entityId}`; url = `${intAPI}/${carbohydrateURL}/${pdbId}/${bmId}/${entityId}`;
break; break;
} }
default:
url = `${productionAPI}/${carbohydrateURL}/${pdbId}/${bmId}/${entityId}`;
break;
} }
return url; return url;
} }
/**
* Retrieve ligand interactions URL given the environment
*
* @export
* @param {string} pdbId
* @param {string} chainId
* @param {number} resId
* @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 = '';
switch (env) { switch (env) {
case Model.Environment.Production: {
url = `${productionAPI}/pdb/bound_ligand_interactions/${pdbId}/${chainId}/${resId}`;
break;
}
case Model.Environment.Development: { case Model.Environment.Development: {
url = `${devAPI}/pdb/bound_ligand_interactions/${pdbId}/${chainId}/${resId}`; url = `${devAPI}/${boundLigandURL}/${pdbId}/${chainId}/${resId}`;
break; break;
} }
case Model.Environment.Internal: { case Model.Environment.Internal: {
url = `${intAPI}/pdb/bound_ligand_interactions/${pdbId}/${chainId}/${resId}`; url = `${intAPI}/${boundLigandURL}/${pdbId}/${chainId}/${resId}`;
break; break;
} }
default:
url = `${productionAPI}/${boundLigandURL}/${pdbId}/${chainId}/${resId}`;
break;
} }
return url; return url;
} }
export function residueTypeAPI(chemCompId: string): string { /**
return `${residueTypeURL}${chemCompId}`; * Return residue type URL API
*
* @export
* @param {string} chemCompId
* @param {Model.Environment} env
* @returns {string}
*/
export function residueTypeAPI(chemCompId: string, env: Model.Environment): string {
let url = '';
switch (env) {
case Model.Environment.Development: {
url = `${devAPI}/${compoundSummaryURL}/${chemCompId}`;
break;
}
case Model.Environment.Internal: {
url = `${intAPI}/${compoundSummaryURL}/${chemCompId}`;
break;
}
default:
url = `${productionAPI}/${compoundSummaryURL}/${chemCompId}`;
break;
}
return url;
} }
} }
...@@ -64,11 +64,11 @@ let helpBonds = ` ...@@ -64,11 +64,11 @@ let helpBonds = `
<table class='pdb-lig-env-help-table' style="border-bottom: 0.5px solid black; padding-bottom: 10px;"> <table class='pdb-lig-env-help-table' style="border-bottom: 0.5px solid black; padding-bottom: 10px;">
<tr> <tr>
<td> <td>
<hr style="border: 0 none; border-top: 5px solid #AD4379; background: none; height: 0;" /> <hr style="border: 0 none; border-top: 5px dashed #AD4379; background: none; height: 0;" />
</td> </td>
<td>aromatic</td> <td>aromatic</td>
<td> <td>
<hr style="border: 0 none; border-top: 5px solid #FF5050; background: none; height: 0;" /> <hr style="border: 0 none; border-top: 5px dashed #FF5050; background: none; height: 0;" />
</td> </td>
<td>clashes</td> <td>clashes</td>
</tr> </tr>
...@@ -78,7 +78,7 @@ let helpBonds = ` ...@@ -78,7 +78,7 @@ let helpBonds = `
</td> </td>
<td>covalent</td> <td>covalent</td>
<td> <td>
<hr style="border: 0 none; border-top: 5px solid #3F26BF; background: none; height: 0;" /> <hr style="border: 0 none; border-top: 5px dashed #3F26BF; background: none; height: 0;" />
</td> </td>
<td>electrostatic</td> <td>electrostatic</td>
...@@ -94,7 +94,7 @@ let helpBonds = ` ...@@ -94,7 +94,7 @@ let helpBonds = `
<tr> <tr>
<td> <td>
<hr style="border: 0 none; border-top: 5px solid #9B7653; background: none; height: 0;" /> <hr style="border: 0 none; border-top: 5px dashed #9B7653; background: none; height: 0;" />
</td> </td>
<td>vdw</td> <td>vdw</td>
</tr> </tr>
......
...@@ -6,22 +6,25 @@ ...@@ -6,22 +6,25 @@
* *
* @class VisualsMapper * @class VisualsMapper
*/ */
class VisualsMapper { class VisualsMapper {
public glycanImages: Map<string, SVGElement>; public glycanImages: Map<string, SVGElement>;
public glycanMapping: Map<string, string>; public glycanMapping: Map<string, string>;
public graphicsPromise: Promise<void>; public graphicsPromise: Promise<void>;
public mappingPromise: Promise<void>; public mappingPromise: Promise<void>;
constructor() { constructor(env: Model.Environment) {
this.glycanMapping = new Map<string, string>(); this.glycanMapping = new Map<string, string>();
this.glycanImages = new Map<string, SVGElement>(); this.glycanImages = new Map<string, SVGElement>();
this.graphicsPromise = this.parseSymbols(Resources.glycanSymbols); let symbolsUrl = Resources.glycanSymbolsAPI(env);
this.mappingPromise = this.parseGlycanMapping(Resources.glycanMapping); let mappingUrl = Resources.hetMappingAPI(env);
this.graphicsPromise = this.parseSymbols(symbolsUrl);
this.mappingPromise = this.parseGlycanMapping(mappingUrl);
} }
/** /**
* Gets proper glycan in the SVG format based on teh glycan class. * Gets proper glycan in the SVG format based on teh glycan class.
* *
...@@ -49,7 +52,7 @@ class VisualsMapper { ...@@ -49,7 +52,7 @@ class VisualsMapper {
let parsedImages: any = x.documentElement.getElementsByTagName('glycans')[0].getElementsByTagName('g'); let parsedImages: any = x.documentElement.getElementsByTagName('glycans')[0].getElementsByTagName('g');
for (let img of parsedImages) { for (let img of parsedImages) {
this.glycanImages.set(img.getAttribute('name'), img.outerHTML); this.glycanImages.set(img.getAttribute('name'), img.outerHTML);
} }
}); });
} }
......
.pdb-lig-env-svg-shadow-node {
stroke-width: 0;
fill: white;
}
.pdb-lig-env-svg-shadow-bond { .pdb-lig-env-svg-shadow-bond {
stroke-width: 15px; stroke-width: 10px;
stroke: transparent; stroke: transparent;
} }
...@@ -29,16 +25,19 @@ ...@@ -29,16 +25,19 @@
.pdb-lig-env-svg-bond-stacking { .pdb-lig-env-svg-bond-stacking {
stroke-width: 2px; stroke-width: 2px;
stroke-dasharray: 10 10;
stroke: green; stroke: green;
} }
.pdb-lig-env-svg-bond-atom-pi { .pdb-lig-env-svg-bond-atom-pi {
stroke-width: 2px; stroke-width: 2px;
stroke-dasharray: 10 10;
stroke: #2E8B57; stroke: #2E8B57;
} }
.pdb-lig-env-svg-bond-amide { .pdb-lig-env-svg-bond-amide {
stroke-width: 2px; stroke-width: 2px;
stroke-dasharray: 10 10;
stroke: green; stroke: green;
} }
...@@ -65,16 +64,18 @@ ...@@ -65,16 +64,18 @@
.pdb-lig-env-svg-bond-clashes { .pdb-lig-env-svg-bond-clashes {
stroke-width: 2px; stroke-width: 2px;
stroke-dasharray: 10 10;
stroke: #FF5050; stroke: #FF5050;
} }
.pdb-lig-env-svg-bond-covalent { .pdb-lig-env-svg-bond-covalent {
stroke-width: 2px; stroke-width: 3px;
stroke: black; stroke: black;
} }
.pdb-lig-env-svg-bond-other { .pdb-lig-env-svg-bond-other {
stroke-width: 1px; stroke-width: 1px;
stroke-dasharray: 10 10;
stroke: black; stroke: black;
} }
...@@ -88,7 +89,7 @@ ...@@ -88,7 +89,7 @@
.pdb-lig-env-svg-node text { .pdb-lig-env-svg-node text {
cursor: inherit; cursor: inherit;
font-family: sans-serif; font-family: 'Exo 2', sans-serif;
stroke: black !important; stroke: black !important;
fill: black !important; fill: black !important;
} }
...@@ -96,13 +97,13 @@ ...@@ -96,13 +97,13 @@
.pdb-lig-env-svg-node text tspan:first-child { .pdb-lig-env-svg-node text tspan:first-child {
cursor: inherit; cursor: inherit;
font-weight: 100; font-weight: 100;
font-size: 1em; font-size: 1.3em;
} }
.pdb-lig-env-svg-node text tspan:nth-child(2) { .pdb-lig-env-svg-node text tspan:nth-child(2) {
cursor: inherit; cursor: inherit;
font-weight: lighter; font-weight: lighter;
font-size: 0.75em; font-size: 1.3em;
} }
.pdb-lig-env-svg-ligand-res { .pdb-lig-env-svg-ligand-res {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
height: auto; height: auto;
padding: 10px; padding: 10px;
font: 12px sans-serif; font: 12px sans-serif;
background: #ccd4e0; background: #e9e6e0;
overflow: auto; overflow: auto;
opacity: 0.8; opacity: 0.8;
word-wrap: normal; word-wrap: normal;
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
} }
.pdb-lig-env-menu-panel { .pdb-lig-env-menu-panel {
background: #ccd4e0; background: #e9e6e0;
opacity: 0.9; opacity: 0.9;
float: right; float: right;
height: 30px; height: 30px;
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
} }
.pdb-lig-env-menu-panel>i:hover { .pdb-lig-env-menu-panel>i:hover {
color: #637ca0; color: #ae5d04;
} }
.pdb-lig-env-toolbar-container { .pdb-lig-env-toolbar-container {
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment