Skip to content

Commit

Permalink
add q-score for ligand validation
Browse files Browse the repository at this point in the history
  • Loading branch information
Filomeno Sanchez committed Nov 11, 2024
1 parent f6ba809 commit f594095
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 6 deletions.
2 changes: 1 addition & 1 deletion baby-gru/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "moorhen",
"version": "0.10.2",
"version": "0.10.3",
"private": false,
"main": "moorhen.js",
"types": "./types/main.d.ts",
Expand Down
31 changes: 27 additions & 4 deletions baby-gru/src/components/card/MoorhenLigandCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import { useEffect, useRef, useState } from "react";
import { CenterFocusStrongOutlined, HelpOutlined, RadioButtonCheckedOutlined, RadioButtonUncheckedOutlined } from "@mui/icons-material";
import parse from 'html-react-parser'
import { convertViewtoPx, guid } from "../../utils/utils";
import { Popover, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
import { LinearProgress, Popover, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
import { libcootApi } from "../../types/libcoot";

export const MoorhenLigandCard = (props: {
ligand: moorhen.LigandInfo;
molecule: moorhen.Molecule;
validationStyles?: moorhen.RepresentationStyles[]
validationStyles?: moorhen.RepresentationStyles[];
calculateQScore?: boolean;
}) => {

const validationLabels = {
Expand All @@ -24,16 +26,18 @@ export const MoorhenLigandCard = (props: {

const [showState, setShowState] = useState<{ [key: string]: boolean }>({})
const [showInfoTable, setShowInfoTable] = useState<boolean>(false)
const [qScore, setQScore] = useState<number | null>(null)

const isDark = useSelector((state: moorhen.State) => state.sceneSettings.isDark)
const height = useSelector((state: moorhen.State) => state.sceneSettings.height)
const width = useSelector((state: moorhen.State) => state.sceneSettings.width)
const activeMap = useSelector((state: moorhen.State) => state.generalStates.activeMap)

const defaultValidationStyles = [
'contact_dots', 'chemical_features', 'ligand_environment', 'ligand_validation'
]

const { ligand, molecule, validationStyles } = { validationStyles: defaultValidationStyles, ...props }
const { ligand, molecule, validationStyles, calculateQScore } = { validationStyles: defaultValidationStyles, calculateQScore: false, ...props }

useEffect(() => {
const changedState = { ...showState }
Expand All @@ -46,6 +50,16 @@ export const MoorhenLigandCard = (props: {
}
}, [])

useEffect(() => {
const getQScore = async () => {
if (activeMap && calculateQScore) {
const qScoreResponse = await molecule.calculateQscore(activeMap, ligand.cid)
setQScore(qScoreResponse?.[0]?.value)
}
}
getQScore()
}, [])

const getToggleButton = (style: string, label: string) => {
return <ToggleButton
key={`${style}-${molecule.molNo}-${ligand.cid}`}
Expand Down Expand Up @@ -114,7 +128,16 @@ export const MoorhenLigandCard = (props: {
</Table>
</TableContainer>
</Popover>}
{ligand.svg ? parse(ligand.svg) : <span>{ligand.cid}</span>}
<Stack direction="vertical" gap={1}>
{ligand.svg ? parse(ligand.svg) : <span>{ligand.cid}</span>}
{(calculateQScore && activeMap) ?
<div style={{ display: "flex", justifyContent: "center" }}>
{
qScore ? <span>Q-Score: {qScore.toFixed(2)}</span> : <LinearProgress variant="indeterminate" style={{ width: "50%" }}/>
}
</div>
: null}
</Stack>
</Col>
<Col className='col-3' style={{margin: '0', padding:'0', justifyContent: 'right', display:'flex'}}>
<Stack direction='vertical' gap={1} style={{display: 'flex', justifyContent: 'center'}}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const MoorhenLigandValidation = (props: moorhen.CollectedProps) => {
}

return ligandInfo.map((ligand, index) => {
return <MoorhenLigandCard key={`${ligand.cid}-${selectedModel}`} ligand={ligand} molecule={selectedMolecule}/>
return <MoorhenLigandCard key={`${ligand.cid}-${selectedModel}`} ligand={ligand} molecule={selectedMolecule} calculateQScore={true}/>
})
}

Expand Down
1 change: 1 addition & 0 deletions baby-gru/src/types/moorhen.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ export namespace moorhen {
getLigandSVG(resName: string, useCache?: boolean): Promise<string>;
isValidSelection(cid: string): Promise<boolean>;
fetchHeaderInfo(useCache?: boolean): Promise<libcootApi.headerInfoJS>;
calculateQscore(activeMap: Map, cid?: string): Promise<libcootApi.ValidationInformationJS[]>;
type: string;
adaptativeBondsEnabled: boolean;
cachedLigandSVGs: {[key: string]: string};
Expand Down
40 changes: 40 additions & 0 deletions baby-gru/src/utils/MoorhenMolecule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2471,4 +2471,44 @@ export class MoorhenMolecule implements moorhen.Molecule {

return headerInfo.data.result.result
}

/**
* Calculate the Q-Score for a CID
* @param {string} cid - The CID selection used to calcualte the qscore
* @param {moorhen.Map} activeMap - The map instance used in the refinement
*/
async calculateQscore(activeMap: moorhen.Map, cid?: string) {
if (!cid) {
const result = await this.commandCentre.current.cootCommand({
command: 'get_q_score',
commandArgs: [ this.molNo, activeMap.molNo ],
returnType: 'validation_data',
}, false) as moorhen.WorkerResponse<libcootApi.ValidationInformationJS[]>
return result.data.result.result
} else {
//Here we copy the ligand into a separate fragment and calculate the q-score.
// Newer versions can do this directly with molecules_container.get_q_score_for_cid
const copyMoleculeResponse = await this.commandCentre.current.cootCommand({
returnType: "status",
command: "copy_fragment_using_cid",
commandArgs: [this.molNo, cid],
}, true) as moorhen.WorkerResponse<number>
const qScoreResponse = await this.commandCentre.current.cootCommand({
command: 'get_q_score',
commandArgs: [copyMoleculeResponse.data.result.result, activeMap.molNo],
returnType: "validation_data"
}, false) as moorhen.WorkerResponse<libcootApi.ValidationInformationJS[]>
await this.commandCentre.current.cootCommand({
returnType: 'status',
commandArgs: [copyMoleculeResponse.data.result.result],
command: "close_molecule"
}, false) as moorhen.WorkerResponse<number>
await this.commandCentre.current.cootCommand({
returnType: 'status',
commandArgs: [ ],
command: "end_delete_closed_molecules"
}, false) as moorhen.WorkerResponse<number>
return qScoreResponse.data.result.result
}
}
}

0 comments on commit f594095

Please sign in to comment.