Skip to content

Commit

Permalink
Feedback for fixes from external feedback (#55)
Browse files Browse the repository at this point in the history
- changed figure on landing page to be gene symbols not names
- updated some text on the landing page
- updated a few tooltips
- added a button for FAQs page
- added min number of genes to train the model
---------

Co-authored-by: Vincent Rubinetti <[email protected]>
  • Loading branch information
ChristopherMancuso and vincerubinetti authored Dec 6, 2024
1 parent edc214d commit 03329cc
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 77 deletions.
2 changes: 1 addition & 1 deletion frontend/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
VITE_TITLE=GenePlexus
VITE_DESCRIPTION=GenePlexus enables researchers to predict novel genes similar to genes of interest based on their patterns of connectivity in human genome-scale networks.
VITE_DESCRIPTION=GenePlexus enables researchers to predict genes similar to an uploaded geneset of interest based on patterns of connectivity in genome-scale molecular interaction networks, with the ability to translate these findings across species.
VITE_URL=https://geneplexus.net
VITE_OLD_URL=https://geneplexus-old.net
VITE_API=https://us-central1-gap-som-dbmi-geneplx-app-p0n.cloudfunctions.net
Binary file modified frontend/src/assets/highlight-predictions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions frontend/src/components/Alert.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { ComponentProps } from "react";
import clsx from "clsx";
import Mark from "@/components/Mark";
import classes from "./Alert.module.css";

/** static box of certain type with icon and text contents */
const Alert = (props: ComponentProps<typeof Mark>) => {
return <Mark className={classes.alert} {...props}></Mark>;
const Alert = ({ className, ...props }: ComponentProps<typeof Mark>) => {
return <Mark className={clsx(classes.alert, className)} {...props}></Mark>;
};

export default Alert;
3 changes: 2 additions & 1 deletion frontend/src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ type Description =
/** require text and/or tooltip for accessibility */
{ text: string; tooltip?: ReactNode } | { text?: string; tooltip: ReactNode };

type _Link = Pick<ComponentProps<typeof Link>, "to">;
type _Link = Pick<ComponentProps<typeof Link>, "to" | "style">;

type _Button = Pick<
ComponentProps<"button">,
| "type"
| "style"
| "onClick"
| "onDrag"
| "onDragEnter"
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/pages/About.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
FaHourglass,
FaLightbulb,
FaPenNib,
FaQuestion,
FaRegCircleQuestion,
FaScaleBalanced,
FaScroll,
Expand Down Expand Up @@ -86,6 +87,13 @@ const AboutPage = () => {
tooltip="Raw data behind the package and analyses"
flip
/>
<Button
to="https://pygeneplexus.readthedocs.io/en/latest/notes/faqs.html"
text="FAQs"
icon={<FaQuestion />}
tooltip="Detailed help on some frequently asked questions"
flip
/>
</Flex>
</Flex>
</Section>
Expand Down
213 changes: 144 additions & 69 deletions frontend/src/pages/NewAnalysis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,42 @@ const example: Record<Species, string> = {
};

const speciesOptions: SelectOption<Species>[] = [
{ id: "Human", primary: "Human", icon: <FaPerson /> },
{ id: "Mouse", primary: "Mouse", icon: <GiRat /> },
{ id: "Fly", primary: "Fly", icon: <GiFly /> },
{ id: "Zebrafish", primary: "Zebrafish", icon: <FaFish /> },
{ id: "Worm", primary: "Worm", icon: <FaWorm /> },
{ id: "Yeast", primary: "Yeast", icon: <FaBeerMugEmpty /> },
{
id: "Human",
primary: "Human",
secondary: "Homo sapiens",
icon: <FaPerson />,
},
{
id: "Mouse",
primary: "Mouse",
secondary: "Mus musculus",
icon: <GiRat />,
},
{
id: "Fly",
primary: "Fly",
secondary: "Drosophila melanogaster",
icon: <GiFly />,
},
{
id: "Zebrafish",
primary: "Zebrafish",
secondary: "Danio rerio",
icon: <FaFish />,
},
{
id: "Worm",
primary: "Worm",
secondary: "Caenorhabditis elegans",
icon: <FaWorm />,
},
{
id: "Yeast",
primary: "Yeast",
secondary: "Saccharomyces cerevisiae",
icon: <FaBeerMugEmpty />,
},
] as const;

const networkOptions: SelectOption<Network>[] = [
Expand Down Expand Up @@ -106,6 +136,9 @@ const genesetContextOptions: SelectOption<GenesetContext>[] = [
},
];

const geneMin = 5;
const geneMinMessage = `GenePlexus needs at least ${geneMin} valid genes to work properly`;

const NewAnalysisPage = () => {
/** raw text list of input gene ids */
const [genes, setGenes] = useLocalStorage("input-genes", "");
Expand Down Expand Up @@ -196,11 +229,23 @@ const NewAnalysisPage = () => {
const submitAnalysis = () => {
/** check for sufficient inputs */
if (!splitGenes.length) {
window.alert("Please enter some genes first!");
window.alert("Please enter some genes");
scrollTo("#enter-genes");
return;
}

if (splitGenes.length < geneMin) {
window.alert(geneMinMessage);
scrollTo("#enter-genes");
return;
}

if ((checkGenesData?.success || Infinity) < geneMin) {
window.alert(geneMinMessage);
scrollTo("#pre-check-genes");
return;
}

/** send inputs to load analysis page */
navigate("/analysis", {
state: {
Expand Down Expand Up @@ -364,14 +409,15 @@ const NewAnalysisPage = () => {
</div>

<Flex>
<span>{formatNumber(splitGenes.length)} genes</span>

<Button
text="Example"
icon={<FaLightbulb />}
design="hollow"
onClick={() => setGenes(example[speciesTrain])}
tooltip="Try some example genes for this species"
/>

<Flex>
<UploadButton
text="Upload"
Expand All @@ -394,6 +440,10 @@ const NewAnalysisPage = () => {
{filename}
</Flex>
</Flex>

{splitGenes.length > 0 && splitGenes.length < geneMin && (
<Alert type="error">{geneMinMessage}</Alert>
)}
</Section>

<Section>
Expand Down Expand Up @@ -447,6 +497,8 @@ const NewAnalysisPage = () => {
placeholder="Comma, tab, or line-separated list of entrez IDs, symbols, or ensembl gene/protein/transcript IDs"
tooltip="Genes to be used as negative training examples, in addition to those automatically selected by our algorithm."
/>

<span>{formatNumber(splitNegatives.length)} negative genes</span>
</Collapsible>
</Section>

Expand Down Expand Up @@ -475,76 +527,83 @@ const NewAnalysisPage = () => {

{checkGenesStatus === "loading" && (
<Alert type="loading">
Checking {formatNumber(splitGenes.length)} genes
Checking {formatNumber(splitGenes.length + splitNegatives.length)}{" "}
genes
</Alert>
)}
{checkGenesStatus === "error" && (
<Alert type="error">Error checking genes</Alert>
)}

{checkGenesData && (
<Tabs>
<Tab text="Summary" icon={<FaEye />}>
<div className={classes.summary}>
<Mark type="success">
<strong className={classes.success}>
{formatNumber(checkGenesData.success)} genes
</strong>{" "}
converted to Entrez
</Mark>

{!!checkGenesData.error && (
<Mark type="error">
<strong className={classes.error}>
{formatNumber(checkGenesData.error)} genes
<>
<Tabs>
<Tab text="Summary" icon={<FaEye />}>
<div className={classes.summary}>
<Mark type="success">
<strong className={classes.success}>
{formatNumber(checkGenesData.success)} genes
</strong>{" "}
couldn't be converted
converted to Entrez
</Mark>
)}

<span className={classes.divider} />

{checkGenesData.summary.map((row, index) => (
<Mark key={index} icon={<FaDna />}>
<strong>{formatNumber(row.positiveGenes)} genes</strong> in{" "}
{row.network} ({formatNumber(row.totalGenes, true)})
</Mark>
))}
</div>
</Tab>

<Tab text="Detailed" icon={<FaTable />}>
<Table
cols={[
{
key: "input",
name: "Input ID",
},
...(splitNegatives.length
? ([
{
key: "inputType",
name: "Type",
filterType: "enum",
},
] as const)
: []),
{
key: "entrez",
name: "Entrez ID",
render: RenderID,
},
{
key: "inNetwork",
name: "In Network",
render: YesNo,
filterType: "boolean",
},
]}
rows={checkGenesData.table}
/>
</Tab>
</Tabs>
{!!checkGenesData.error && (
<Mark type="error">
<strong className={classes.error}>
{formatNumber(checkGenesData.error)} genes
</strong>{" "}
couldn't be converted
</Mark>
)}

<span className={classes.divider} />

{checkGenesData.summary.map((row, index) => (
<Mark key={index} icon={<FaDna />}>
<strong>{formatNumber(row.positiveGenes)} genes</strong>{" "}
in {row.network} ({formatNumber(row.totalGenes, true)})
</Mark>
))}
</div>
</Tab>

<Tab text="Detailed" icon={<FaTable />}>
<Table
cols={[
{
key: "input",
name: "Input ID",
},
...(splitNegatives.length
? ([
{
key: "inputType",
name: "Type",
filterType: "enum",
},
] as const)
: []),
{
key: "entrez",
name: "Entrez ID",
render: RenderID,
},
{
key: "inNetwork",
name: "In Network",
render: YesNo,
filterType: "boolean",
},
]}
rows={checkGenesData.table}
/>
</Tab>
</Tabs>

{checkGenesData.success < geneMin && (
<Alert type="error">{geneMinMessage}</Alert>
)}
</>
)}
</Section>

Expand All @@ -553,10 +612,19 @@ const NewAnalysisPage = () => {
Submit Analysis
</Heading>

{!checkGenesData &&
splitGenes.length >= geneMin &&
splitGenes.length < geneMin * 2 && (
<Alert type="warning" className="narrow">
You haven't entered many genes and haven't pre-checked them. If
less than {geneMin} end up being valid, the analysis will fail.
</Alert>
)}

<TextBox
className="narrow"
label="Name"
tooltip="(Optional) Give your analysis a name to remember it by"
tooltip="(Optional) A name to help you distinguish this analysis from others. Shown anywhere an analysis summary or details is shown, and used in downloaded file names."
placeholder="analysis"
value={name}
onChange={(value) => setName(value.replaceAll(/[^\w\d-_ ]*/g, ""))}
Expand All @@ -565,6 +633,13 @@ const NewAnalysisPage = () => {
<Button
text="Submit"
icon={<FaPaperPlane />}
style={{
opacity:
splitGenes.length < geneMin ||
(checkGenesData?.success || Infinity) < geneMin
? 0.5
: 1,
}}
onClick={submitAnalysis}
/>
</Section>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/analysis/Predictions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ const Predictions = ({ inputs, results }: Props) => {
key: "knownNovel",
name: "Known/Novel",
tooltip:
"Indicates whether gene was part of input gene list (therefore Known) or not (therefore Novel)",
"Indicates whether gene was part of input gene list (therefore Known) or not (therefore Novel). If cross-species, information is based on one-to-one ortholog.",
filterType: "enum",
},
{
key: "classLabel",
name: "Class Label",
tooltip:
"Whether gene was considered in positive/negative class or not considered at all during training",
"Whether gene was considered in positive/negative class or not considered at all during training. If cross-species, information is based on one-to-one ortholog.",
filterType: "enum",
style: { whiteSpace: "nowrap" },
},
Expand Down
2 changes: 1 addition & 1 deletion functions/convert_ids/convert_ids_deploy/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# An example requirements file. If your function has other dependencies,
# add them below
functions-framework==3.*
geneplexus @ git+https://github.com/krishnanlab/PyGenePlexus@122aa2c
geneplexus @ git+https://github.com/krishnanlab/PyGenePlexus@610ad9a
2 changes: 1 addition & 1 deletion functions/ml/ml_deploy/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# An example requirements file. If your function has other dependencies,
# add them below
functions-framework==3.*
geneplexus @ git+https://github.com/krishnanlab/PyGenePlexus@122aa2c
geneplexus @ git+https://github.com/krishnanlab/PyGenePlexus@610ad9a
flask-compress==1.*

0 comments on commit 03329cc

Please sign in to comment.