Skip to content

Commit

Permalink
Merge pull request #76 from privrja/devel
Browse files Browse the repository at this point in the history
Version 1.0.2
  • Loading branch information
privrja committed Jun 16, 2021
2 parents 2656633 + 48dd16d commit b471e4e
Show file tree
Hide file tree
Showing 21 changed files with 769 additions and 400 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This repo use npm to manage many action.
To install dependencies run ```npm install```
To run development server use ```npm start```
To run tests use ```npm test```
And to build package use ```npom build```
And to build package use ```npm build```

### CORS

Expand Down
719 changes: 393 additions & 326 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
{
"name": "thesis-frontend-react",
"version": "0.1.0",
"version": "1.0.2",
"private": true,
"dependencies": {
"@babel/core": "^7.14.3",
"@babel/core": "^7.14.5",
"@fortawesome/fontawesome-svg-core": "^1.2.35",
"@fortawesome/free-brands-svg-icons": "^5.15.3",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "latest",
"@testing-library/jest-dom": "^5.12.0",
"@testing-library/jest-dom": "^5.13.0",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^13.1.9",
"@types/file-saver": "^2.0.1",
"@types/jest": "^26.0.23",
"@types/node": "^15.3.1",
"@types/react": "^17.0.6",
"@types/react-dom": "^17.0.5",
"@types/node": "^15.12.2",
"@types/react": "^17.0.11",
"@types/react-dom": "^17.0.7",
"@types/react-fontawesome": "^1.6.4",
"@types/react-helmet": "^6.1.1",
"@types/react-router-dom": "^5.1.5",
"@types/react-select": "^4.0.15",
"async-mutex": "^0.3.1",
"async-parallel": "^1.2.3",
"file-saver": "^2.0.5",
"formik": "^2.2.7",
"formik": "^2.2.9",
"html-react-parser": "latest",
"jsme-editor": "^0.8.2",
"jsme-react": "0.0.9",
Expand All @@ -34,9 +34,9 @@
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.3",
"react-select": "^4.3.1",
"sass": "^1.33.0",
"sass": "^1.34.1",
"smiles-drawer": "github:privrja/smilesDrawer#2.1.6",
"typescript": "^4.2.4"
"typescript": "^4.3.2"
},
"scripts": {
"predeploy": "npm run build",
Expand Down
2 changes: 1 addition & 1 deletion src/component/ModificationComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class ModificationComponent extends React.Component<Props, State> {
<h3>Sequence - {this.props.blockLength} blocks</h3>
<label htmlFor="sel-sequence-type">Type</label>
<SelectInput id='sel-sequence-type' name='sel-sequence-type'
options={SequenceEnumHelper.getOptions()} onChange={this.updateModifications}/>
options={SequenceEnumHelper.getOptions()} onChange={this.updateModifications} selected={SequenceEnumHelper.getValue(this.props.sequenceType ?? '').toString()}/>
<label htmlFor="txt-sequence">Sequence</label>
<TextInput id="txt-sequence" name="sequence" size={60} value={this.state.sequence}/>
<div className={styles.padding}>
Expand Down
2 changes: 2 additions & 0 deletions src/enum/SearchEnum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export class SearchEnumHelper {
static getOptionsBySource(source: ServerEnum) {
switch (source) {
case ServerEnum.PUBCHEM:
case ServerEnum.COCONUT:
return [
new SelectOption(SearchEnum.NAME.toString(), this.getName(SearchEnum.NAME)),
new SelectOption(SearchEnum.SMILES.toString(), this.getName(SearchEnum.SMILES)),
Expand All @@ -88,6 +89,7 @@ export class SearchEnumHelper {
case ServerEnum.CHEBI:
case ServerEnum.CHEMSPIDER:
case ServerEnum.MASS_SPEC_BLOCKS:
case ServerEnum.NP_ATLAS:
default:
return this.getOptions();
}
Expand Down
37 changes: 33 additions & 4 deletions src/enum/ServerEnum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import ChemSpiderFinder from "../finder/ChemSpiderFinder";
import MassSpecBlocksFinder from "../finder/MassSpecBlocksFinder";
import {SELECTED_CONTAINER, TOKEN} from "../constant/ApiConstants";
import ChebiFinder from "../finder/ChebiFinder";
import CoconutFinder from "../finder/CoconutFinder";
import NPAtlasFinder from "../finder/NPAtlasFinder";

export enum ServerEnum {
PUBCHEM, CHEMSPIDER, NORINE, PDB, CHEBI, MASS_SPEC_BLOCKS, DOI, SIDEROPHORE_BASE, LIPID_MAPS
PUBCHEM, CHEMSPIDER, NORINE, PDB, CHEBI, MASS_SPEC_BLOCKS, DOI, SIDEROPHORE_BASE, LIPID_MAPS, COCONUT, NP_ATLAS
}

export class ServerEnumHelper {
Expand All @@ -24,7 +26,9 @@ export class ServerEnumHelper {
new SelectOption(ServerEnum.MASS_SPEC_BLOCKS.toString(), this.getName(ServerEnum.MASS_SPEC_BLOCKS) + (containerName ? (' - ' + containerName) : '')),
new SelectOption(ServerEnum.DOI.toString(), this.getName(ServerEnum.DOI)),
new SelectOption(ServerEnum.SIDEROPHORE_BASE.toString(), this.getName(ServerEnum.SIDEROPHORE_BASE)),
new SelectOption(ServerEnum.LIPID_MAPS.toString(), this.getName(ServerEnum.LIPID_MAPS))
new SelectOption(ServerEnum.LIPID_MAPS.toString(), this.getName(ServerEnum.LIPID_MAPS)),
new SelectOption(ServerEnum.COCONUT.toString(), this.getName(ServerEnum.COCONUT)),
new SelectOption(ServerEnum.NP_ATLAS.toString(), this.getName(ServerEnum.NP_ATLAS))
];
}

Expand All @@ -35,6 +39,8 @@ export class ServerEnumHelper {
new SelectOption(ServerEnum.NORINE.toString(), this.getName(ServerEnum.NORINE)),
new SelectOption(ServerEnum.PDB.toString(), this.getName(ServerEnum.PDB)),
new SelectOption(ServerEnum.CHEBI.toString(), this.getName(ServerEnum.CHEBI)),
new SelectOption(ServerEnum.COCONUT.toString(), this.getName(ServerEnum.COCONUT)),
new SelectOption(ServerEnum.NP_ATLAS.toString(), this.getName(ServerEnum.NP_ATLAS)),
new SelectOption(ServerEnum.MASS_SPEC_BLOCKS.toString(), this.getName(ServerEnum.MASS_SPEC_BLOCKS) + (containerName ? (' - ' + containerName) : ''))
];
}
Expand All @@ -60,6 +66,11 @@ export class ServerEnumHelper {
if (container) {
return new MassSpecBlocksFinder(Number(container), token ?? undefined);
}
break;
case ServerEnum.COCONUT:
return new CoconutFinder();
case ServerEnum.NP_ATLAS:
return new NPAtlasFinder();
}
return new PubChemFinder();
}
Expand All @@ -85,6 +96,10 @@ export class ServerEnumHelper {
return 'Siderophore Base';
case ServerEnum.LIPID_MAPS:
return 'Lipid Maps';
case ServerEnum.COCONUT:
return 'COCONUT';
case ServerEnum.NP_ATLAS:
return 'NPAtlas';
}
}

Expand All @@ -107,6 +122,10 @@ export class ServerEnumHelper {
return "http://bertrandsamuel.free.fr/siderophore_base/siderophore.php?id=" + identifier;
case ServerEnum.LIPID_MAPS:
return "https://www.lipidmaps.org/data/LMSDRecord.php?LMID=" + identifier;
case ServerEnum.COCONUT:
return "https://coconut.naturalproducts.net/compound/coconut_id/" + identifier;
case ServerEnum.NP_ATLAS:
return "https://www.npatlas.org/explore/compounds/" + identifier;
}
}

Expand All @@ -115,7 +134,13 @@ export class ServerEnumHelper {
identifier = "0";
}
if (identifier.toUpperCase().includes('CHEBI:')) {
return identifier;
return identifier.toUpperCase();
}
if (identifier.toUpperCase().includes('CNP')) {
return identifier.toUpperCase();
}
if (identifier.toUpperCase().includes('NPA')) {
return identifier.toUpperCase();
}
switch (database) {
default:
Expand All @@ -129,13 +154,17 @@ export class ServerEnumHelper {
case ServerEnum.PDB:
return 'PDB: ' + identifier;
case ServerEnum.CHEBI:
return 'ChEBI:' + identifier;
return 'CHEBI:' + identifier;
case ServerEnum.MASS_SPEC_BLOCKS:
return 'MSB: ' + identifier;
case ServerEnum.DOI:
return 'DOI: ' + identifier;
case ServerEnum.SIDEROPHORE_BASE:
return 'SB: ' + identifier;
case ServerEnum.COCONUT:
return 'CNP' + '0'.repeat(7 - identifier.length) + identifier;
case ServerEnum.NP_ATLAS:
return 'NPA' + '0'.repeat(6 - identifier.length) + identifier;
}
}

Expand Down
103 changes: 103 additions & 0 deletions src/finder/CoconutFinder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import IFinder from "./IFinder";
import SingleStructure from "./SingleStructure";
import Sleep from "../helper/Sleep";
import {ServerEnum} from "../enum/ServerEnum";
import ComputeHelper from "../helper/ComputeHelper";

const ENDPOINT_URI = "https://guarded-atoll-36331.herokuapp.com/https://coconut.naturalproducts.net/api/search/";

interface Molecule {
coconut_id: string;
name: string;
unique_smiles: string;
molecular_formula: string;
}

class CoconutFinder implements IFinder {

async simpleFind(parameter: string, query: string = 'simple?query=') {
if (parameter === '') {
return Sleep.noSleepPromise();
}
if (query.includes('simple?query')) {
query += parameter;
}
return fetch(ENDPOINT_URI + query).then(async response => {
if (response.status === 200) {
let json = await response.json().catch(() => []);
if (json.naturalProducts.length > 0) {
return json.naturalProducts.map((molecule: Molecule) => {
let mass = 0;
try {
mass = ComputeHelper.computeMass(ComputeHelper.removeUnnecessaryCharactersFromFormula(molecule.molecular_formula ?? ''));
} catch (e) {
}
return new SingleStructure(
molecule.coconut_id,
ServerEnum.COCONUT,
molecule.name,
molecule.unique_smiles,
molecule.molecular_formula,
mass
)
});
}
}
return [];
}).catch(() => []);
}

findByFormula(formula: string): Promise<SingleStructure[]> {
return this.simpleFind(formula);
}

async findByIdentifier(id: string): Promise<SingleStructure[]> {
if (id === '') {
return Sleep.noSleepPromise();
}
return fetch(ENDPOINT_URI + 'simple?query=' + id).then(async response => {
if (response.status === 200) {
let json = await response.json().catch(() => []);
if (json.naturalProducts.length > 0) {
let mass = 0;
try {
mass = ComputeHelper.computeMass(ComputeHelper.removeUnnecessaryCharactersFromFormula(json.naturalProducts[0].molecular_formula ?? ''));
} catch (e) {
}
return [new SingleStructure(
json.naturalProducts[0].coconut_id,
ServerEnum.COCONUT,
json.naturalProducts[0].name,
json.naturalProducts[0].unique_smiles,
json.naturalProducts[0].molecular_formula,
mass
)];
} else {
return [];
}
} else {
return [];
}
}).catch(() => []);
}

findByIdentifiers(ids: string[]): Promise<SingleStructure[]> {
return Sleep.noSleepPromise();
}

findByMass(mass: number): Promise<SingleStructure[]> {
return Sleep.noSleepPromise();
}

findByName(name: string): Promise<SingleStructure[]> {
return this.simpleFind(name);
}

findBySmiles(smiles: string): Promise<SingleStructure[]> {
return this.simpleFind(smiles, 'exact-structure?type=inchi&max-hits=100&smiles=' + smiles);
}


}

export default CoconutFinder;
90 changes: 90 additions & 0 deletions src/finder/NPAtlasFinder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import IFinder from "./IFinder";
import SingleStructure from "./SingleStructure";
import Sleep from "../helper/Sleep";
import {ServerEnum} from "../enum/ServerEnum";
import ComputeHelper from "../helper/ComputeHelper";

const ENDPOINT_URI = "https://guarded-atoll-36331.herokuapp.com/https://www.npatlas.org/api/v1/";

interface Molecule {
npaid: string;
original_name: string;
smiles: string;
mol_formula: string;
}

const BASIC_SEARCH = 'compounds/basicSearch?';
const PARAMS = '&threshold=0&origin_type=all&rank=all&skip=0&limit=100';

class NPAtlasFinder implements IFinder {

basicSearch(endpoint: string, method: string, oneResult: boolean = false): Promise<SingleStructure[]> {
return fetch(endpoint, {method: method}).then(async response => {
if (response.status === 200) {
let json = await response.json().catch(() => []);
if (oneResult) {
let mass = 0;
try {
mass = ComputeHelper.computeMass(ComputeHelper.removeUnnecessaryCharactersFromFormula(json.mol_formula ?? ''));
} catch (e) {
}
return [new SingleStructure(json.npaid, ServerEnum.NP_ATLAS, json.original_name, json.smiles, json.mol_formula, mass)];
} else {
if (json.length > 0) {
return json.map((molecule: Molecule) => {
let mass = 0;
try {
mass = ComputeHelper.computeMass(ComputeHelper.removeUnnecessaryCharactersFromFormula(molecule.mol_formula ?? ''));
} catch (e) {
}
return new SingleStructure(molecule.npaid, ServerEnum.NP_ATLAS, molecule.original_name, molecule.smiles, molecule.mol_formula, mass);
});
}
}
}
return [];
}).catch(() => []);
}

findByFormula(formula: string): Promise<SingleStructure[]> {
if (formula === '') {
return Sleep.noSleepPromise();
}
return this.basicSearch(ENDPOINT_URI + BASIC_SEARCH + 'formula=' + formula + PARAMS, 'POST');
}

async findByIdentifier(id: string): Promise<SingleStructure[]> {
if (id === '') {
return Sleep.noSleepPromise();
}
return this.basicSearch(ENDPOINT_URI + 'compound/' + id, 'GET', true);
}

findByIdentifiers(ids: string[]): Promise<SingleStructure[]> {
return Sleep.noSleepPromise();
}

findByMass(mass: number): Promise<SingleStructure[]> {
if (mass === 0) {
return Sleep.noSleepPromise();
}
return this.basicSearch(ENDPOINT_URI + 'compounds/massSearch?mass=' + mass + '&type=exact_mass&range=100&skip=0&limit=100', 'POST');
}

findByName(name: string): Promise<SingleStructure[]> {
if (name === '') {
return Sleep.noSleepPromise();
}
return this.basicSearch(ENDPOINT_URI + BASIC_SEARCH + 'name=' + name + PARAMS, 'POST');
}

findBySmiles(smiles: string): Promise<SingleStructure[]> {
if (smiles === '') {
return Sleep.noSleepPromise();
}
return this.basicSearch(ENDPOINT_URI + BASIC_SEARCH + 'smiles=' + smiles + '&method=sub' + PARAMS, 'POST');
}

}

export default NPAtlasFinder;
4 changes: 4 additions & 0 deletions src/helper/ComputeHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ export const H2 = 'H2';

class ComputeHelper {

public static removeUnnecessaryCharactersFromFormula(formula: string) {
return formula.replaceAll(/[[\]+\-*/\\?.,;{}:"'|<>~!@#$%^&()]/g, '');
}

public static computeMass(formula: string) {
let mass = 0;
let map = this.formulaMap(formula);
Expand Down
Loading

0 comments on commit b471e4e

Please sign in to comment.