Skip to content

Commit 5fbb269

Browse files
committed
fix screening
1 parent 4e7e370 commit 5fbb269

File tree

14 files changed

+2648
-5903
lines changed

14 files changed

+2648
-5903
lines changed

app/tools/ml/layout.tsx

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import TargetContext from "../../../context/TargetContext";
1313
import { MLResultsContext } from "../../../context/MLResultsContext";
1414
import JSME from "../../../components/tools/toolViz/JSMEComp";
1515
import Dropdown from "../../../components/tools/toolViz/DropDown";
16+
import { Button, Group, Input } from "@mantine/core";
1617

1718
type dataChart = {
1819
x: number,
@@ -41,16 +42,36 @@ export default function MLLayout({ children }) {
4142

4243

4344
async function oneOffPred() {
44-
const mol_fp = fpSorter(
45-
localStorage.getItem("fingerprint"),
46-
oneOffSMILES,
47-
rdkit,
48-
parseInt(localStorage.getItem("path")),
49-
parseInt(localStorage.getItem("nBits")),
50-
)
51-
globalThis.one_off_mol_fp = [mol_fp];
52-
await pyodide.runPython(await (await fetch("/pyodide_ml_screen.py")).text());
53-
setOneOffSmilesResult((globalThis.one_off_y).toJs())
45+
const requestId = `fingerprint_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
46+
rdkit.postMessage({
47+
function: 'fingerprint',
48+
id: requestId,
49+
mol_data: [{
50+
"canonical_smiles" : oneOffSMILES
51+
}],
52+
activity_columns: target.activity_columns,
53+
formStuff: {
54+
fingerprint: localStorage.getItem("fingerprint"),
55+
radius: parseInt(localStorage.getItem("path")),
56+
nBits: parseInt(localStorage.getItem("nBits")),
57+
}
58+
});
59+
rdkit.onmessage = async (event) => {
60+
if (event.data.id === requestId) {
61+
let mol_fp = event.data.data[0]["fingerprint"];
62+
pyodide.postMessage({
63+
id: "job-123",
64+
opts: 0,
65+
fp: [mol_fp],
66+
func: "ml-screen"
67+
})
68+
pyodide.onmessage = (event) => {
69+
if (event.data.success == "ok") {
70+
setOneOffSmilesResult(event.data.results[0]);
71+
}
72+
}
73+
}
74+
}
5475
}
5576

5677
return (
@@ -61,18 +82,15 @@ export default function MLLayout({ children }) {
6182
{target.machine_learning.length > 0 && (
6283
<>
6384
&nbsp;
64-
<div style={{ borderColor: "10px solid black", margin: "20px 0", gap: "10px" }}>
85+
<Group>
6586
<h2>Predict the activity of a single molecule</h2>
66-
<input ref={inputRef} style={{ width: "40%" }} className="input" onChange={(e) => setOneOffSmiles(e.target.value)} placeholder="Input Your SMILES string here"></input>
67-
<br />
87+
<Input ref={inputRef} style={{ width: "20%" }} className="input" onChange={(e) => setOneOffSmiles(e.target.value)} placeholder="Input Your SMILES string here"></Input>
6888
<Dropdown buttonText="Draw the molecule">
6989
<JSME width="300px" height="300px" onChange={(smiles) => setOneOffSmiles(smiles)} />
7090
</Dropdown>
71-
<br />
72-
<button className="button" onClick={oneOffPred}>Predict Activity of SMILES</button>
73-
<br />
91+
<Button className="button" onClick={oneOffPred}>Predict Activity of SMILES</Button>
7492
<span>Predicted {target.activity_columns[0]}: {oneOffSMILESResult}</span>
75-
</div>
93+
</Group>
7694

7795
<GroupedBarChart mae={target.machine_learning[0]} r2={target.machine_learning[1]}>
7896
<span>Mean MAE: {round(mean(target.machine_learning[0]), 2)} || Mean R-Squared: {round(mean(target.machine_learning[1]), 2)}</span>

app/tools/screen/cov_score/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useContext, useState } from "react";
44
import { useForm, useFieldArray } from "react-hook-form";
5-
import Table from "../../../../components/ui-comps/PaginatedTables";
5+
import DataTable from "../../../../components/ui-comps/PaginatedTables";
66
import { randomInt } from "mathjs";
77
import { MOEA } from "../../../../components/utils/nsga2";
88
import { coverageNameSpace, coverageSets } from "../../../../components/utils/coverage_score";
@@ -149,7 +149,7 @@ export default function CovScore(){
149149
</div>
150150
<button onClick={handleAddInput} className="button">Add Prior SMILES</button>
151151
</form>
152-
{hof.length > 1 && <Table data={hof} rowsPerPage={5} />}
152+
{hof.length > 1 && <DataTable data={hof} rowsPerPage={5} />}
153153
</div>
154154
)
155155
}

app/tools/screen/layout.tsx

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,46 @@ export default function ScreenLayout({ children }) {
1919
const { pyodide } = useContext(PyodideContext);
2020

2121
async function callofScreenFunction(data) {
22-
console.log(data)
23-
setLoaded(false);
24-
setTimeout(async () => {
25-
const fp_mols = await screenData.map((x) => {
26-
try {
27-
x["fingerprint"] = fpSorter(
28-
localStorage.getItem("fingerprint"),
29-
x[data.smi_column],
30-
rdkit,
31-
parseInt(localStorage.getItem("path")),
32-
parseInt(localStorage.getItem("nBits")),
33-
)
34-
x["id"] = x[data.id_column]
35-
return x
36-
} catch (error) {
37-
console.error("Error processing element:", error);
38-
return null;
39-
}
40-
}).filter((x) => x !== null);
22+
let newScreenData = screenData
23+
newScreenData.forEach(obj => {
24+
console.log(obj[data.smi_column]);
25+
obj["canonical_smiles"] = obj[data.smi_column];
26+
delete obj[data.smi_column];
27+
});
28+
29+
const requestId = `fingerprint_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
30+
rdkit.postMessage({
31+
function: 'fingerprint',
32+
id: requestId,
33+
mol_data: newScreenData,
34+
formStuff: {
35+
fingerprint: localStorage.getItem("fingerprint"),
36+
radius: parseInt(localStorage.getItem("path")),
37+
nBits: parseInt(localStorage.getItem("nBits")),
38+
}
39+
});
4140

42-
globalThis.one_off_mol_fp = fp_mols.map(x => x.fingerprint);
43-
await pyodide.runPython(await (await fetch("/pyodide_ml_screen.py")).text());
44-
let tempVar = (globalThis.one_off_y).toJs();
45-
tempVar = await fp_mols.map((x, i) => {
46-
x["predictions"] = tempVar[i];
47-
return x
48-
});
49-
await setScreenData(tempVar);
50-
setLoaded(true);
51-
}, 500)
41+
rdkit.onmessage = async (event) => {
42+
if (event.data.id === requestId) {
43+
let mol_fp = event.data.data.map(x => x["fingerprint"]);
44+
pyodide.postMessage({
45+
id: "job-123",
46+
opts: 0,
47+
fp: mol_fp,
48+
func: "ml-screen"
49+
})
50+
pyodide.onmessage = async (event) => {
51+
if (event.data.success == "ok") {
52+
let fp_mols = event.data.results;
53+
newScreenData = await newScreenData.map((x, i) => {
54+
x["predictions"] = fp_mols[i];
55+
return x
56+
});
57+
setScreenData(newScreenData);
58+
}
59+
}
60+
}
61+
}
5262
}
5363

5464
if (!loaded) {

app/tools/screen/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useContext } from "react";
44
import Histogram from "../../../components/tools/toolViz/Histogram";
5-
import Table from "../../../components/ui-comps/PaginatedTables";
5+
import DataTable from "../../../components/ui-comps/PaginatedTables";
66
import { ScreenDataContext } from "./layout";
77

88
export default function Screen() {
@@ -32,7 +32,7 @@ export default function Screen() {
3232
Download Predictions in CSV Format
3333
</button>
3434
&nbsp;
35-
<Table data={screenData} rowsPerPage={5} act_column={["predictions"]}/>
35+
<DataTable data={screenData} rowsPerPage={5} act_column={["predictions"]}/>
3636
</>
3737
}
3838
</>

app/tools/toc/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client"
22

33
import { useContext, useEffect, useRef, useState } from "react";
4-
import Table from "../../../components/ui-comps/PaginatedTables";
4+
import DataTable from "../../../components/ui-comps/PaginatedTables";
55
import LigandContext from "../../../context/LigandContext";
66
import { usePapaParse } from 'react-papaparse';
77
import TargetContext from "../../../context/TargetContext";
@@ -70,7 +70,7 @@ export default function TOC() {
7070
<br />
7171
<Button onClick={() => downloadCSV(results)}>Download Ligand Data as CSV</Button>
7272
<br /><br /><br />
73-
<Table data={searchRes} rowsPerPage={30} act_column={target.activity_columns} />
73+
<DataTable data={searchRes} rowsPerPage={30} act_column={target.activity_columns} />
7474
</div>
7575
)
7676
}

components/tools/toolComp/ScaffNetDets.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import TagComponent from "../../ui-comps/Tags";
33
import { subgraph } from "graphology-operators";
44
import ScaffoldNetworkWholeGraph from "./ScaffoldNetworkWholeGraph";
55
import { useDisclosure } from "@mantine/hooks";
6-
import { Button, Card, Grid, Modal } from "@mantine/core";
6+
import { Button, Card, Grid, Group, Modal } from "@mantine/core";
77

88
const GraphComponent: React.FC<any> = ({ graph }) => {
99
const [opened, { open, close }] = useDisclosure(false);
@@ -114,29 +114,29 @@ const GraphComponent: React.FC<any> = ({ graph }) => {
114114
</div>
115115
</Modal>
116116

117-
{/* Pagination buttons */}
118-
<div>
119-
<button className={`tableButton ${currentPage === 1 ? "activeButton" : "inactiveButton"}`} disabled={currentPage === 1} onClick={() => handlePageChange(1)}>
117+
<br />
118+
<Group>
119+
<Button className={`tableButton ${currentPage === 1 ? "activeButton" : "inactiveButton"}`} disabled={currentPage === 1} onClick={() => handlePageChange(1)}>
120120
First Page
121-
</button>
121+
</Button>
122122
{getDisplayedPages().map((pageNumber) => (
123-
<button
123+
<Button
124124
className={`tableButton ${currentPage === pageNumber ? "activeButton" : "inactiveButton"}`}
125125
key={pageNumber}
126126
onClick={() => handlePageChange(pageNumber)}
127127
disabled={pageNumber === currentPage}
128128
>
129129
{pageNumber}
130-
</button>
130+
</Button>
131131
))}
132-
<button
132+
<Button
133133
className={`tableButton ${currentPage === totalPages ? "activeButton" : "inactiveButton"}`}
134134
disabled={currentPage === totalPages}
135135
onClick={() => handlePageChange(totalPages)}
136136
>
137137
Last Page
138-
</button>
139-
</div>
138+
</Button>
139+
</Group>
140140
</div>
141141
);
142142
};

components/tools/toolViz/ScatterPlot.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { useDisclosure } from '@mantine/hooks';
1010
export default function Scatterplot({ data, colorProperty = [], hoverProp = [], xAxisTitle = '', yAxisTitle = '', id = [] }) {
1111
const margin = { top: 10, right: 20, bottom: 80, left: 80 };
1212
const parentRef = useRef<HTMLDivElement | null>(null);
13-
const svgRef = useRef<HTMLDivElement | null>(null);
13+
const svgRef = useRef<SVGSVGElement | null>(null);
1414
const [details, setDetails] = useState(null);
1515
const [opened, { open, close }] = useDisclosure(false);
1616
const [modalDets, setModalDets] = useState<any>(false);
Lines changed: 89 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,97 @@
11
import React, { useState } from "react";
2+
import { Table, Paper, ScrollArea, Text, Group, Badge } from "@mantine/core";
23
import TableFooter from "./TableFooter";
34
import useTable from "../../hooks/useTable";
45
import MoleculeStructure from "../tools/toolComp/MoleculeStructure";
56
import { round } from "mathjs";
67

7-
const Table = ({ data, rowsPerPage, act_column = [] }) => {
8-
const [page, setPage] = useState(1);
9-
const { slice, range } = useTable(data, page, rowsPerPage);
10-
11-
return (
12-
<>
13-
<table className="table">
14-
<thead className="tableRowHeader">
15-
<tr>
16-
<th className="tableHeader">ID</th>
17-
<th className="tableHeader">SMILES</th>
18-
<th className="tableHeader">Representation</th>
19-
{act_column.map((el, i) => (
20-
<th className="tableHeader" key={i}>{el}</th>
21-
))}
22-
</tr>
23-
</thead>
24-
<tbody>
25-
{slice.map((el, i) => (
26-
<tr className="tableRow" key={i}>
27-
<td className="tableCell">{el.id}</td>
28-
<td className="tableCell">{el.canonical_smiles}</td>
29-
<td className="tableCell"><MoleculeStructure structure={el.canonical_smiles} id={i.toString()} /></td>
30-
{act_column.map((pl, j) => (
31-
<td className="tableCell" key={i+j}>{round(el[pl], 2)}</td>
32-
))}
33-
</tr>
34-
))}
35-
</tbody>
36-
</table>
37-
<TableFooter range={range} slice={slice} setPage={setPage} page={page} />
38-
</>
39-
);
8+
const DataTable = ({ data, rowsPerPage, act_column = [] }) => {
9+
const [page, setPage] = useState(1);
10+
const { slice, range } = useTable(data, page, rowsPerPage);
11+
12+
return (
13+
<Paper
14+
shadow="md"
15+
radius="lg"
16+
p="md"
17+
>
18+
<ScrollArea>
19+
<Table
20+
highlightOnHover
21+
striped
22+
withColumnBorders
23+
horizontalSpacing="md"
24+
verticalSpacing="sm"
25+
style={{
26+
fontSize: "0.9rem",
27+
}}
28+
>
29+
<Table.Thead>
30+
<Table.Tr>
31+
<Table.Th>
32+
<Text fw={600}>ID</Text>
33+
</Table.Th>
34+
<Table.Th>
35+
<Text fw={600}>SMILES</Text>
36+
</Table.Th>
37+
<Table.Th>
38+
<Text fw={600}>Structure</Text>
39+
</Table.Th>
40+
{act_column.map((el, i) => (
41+
<Table.Th key={i}>
42+
<Text fw={600}>{el}</Text>
43+
</Table.Th>
44+
))}
45+
</Table.Tr>
46+
</Table.Thead>
47+
48+
<tbody>
49+
{slice.map((el, i) => (
50+
<Table.Tr key={i}>
51+
<Table.Td>
52+
<Badge variant="light" color="blue">
53+
{el.id}
54+
</Badge>
55+
</Table.Td>
56+
57+
<Table.Td style={{ maxWidth: 260 }}>
58+
<Text size="sm" truncate>
59+
{el.canonical_smiles}
60+
</Text>
61+
</Table.Td>
62+
63+
<Table.Td>
64+
<Group justify="center">
65+
<MoleculeStructure
66+
structure={el.canonical_smiles}
67+
id={i.toString()}
68+
/>
69+
</Group>
70+
</Table.Td>
71+
72+
{act_column.map((pl, j) => (
73+
<Table.Td key={`${i}-${j}`}>
74+
<Text ta="right">
75+
{Number.isFinite(el[pl]) ? round(el[pl], 2) : "—"}
76+
</Text>
77+
</Table.Td>
78+
))}
79+
</Table.Tr>
80+
))}
81+
</tbody>
82+
</Table>
83+
</ScrollArea>
84+
85+
<Group justify="center" mt="md">
86+
<TableFooter
87+
range={range}
88+
slice={slice}
89+
setPage={setPage}
90+
page={page}
91+
/>
92+
</Group>
93+
</Paper>
94+
);
4095
};
4196

42-
export default Table;
97+
export default DataTable;

0 commit comments

Comments
 (0)