diff --git a/apps/platform/src/constants.js b/apps/platform/src/constants.js
index 0d25a56cf..22a27127f 100644
--- a/apps/platform/src/constants.js
+++ b/apps/platform/src/constants.js
@@ -341,7 +341,7 @@ export const variantConsequenceSource = {
},
};
-export const poulationMap = {
+export const populationMap = {
fin: "Finish",
afr: "African",
nfe: "non-Finnish Europeans",
diff --git a/apps/platform/src/pages/CredibleSetPage/Profile.tsx b/apps/platform/src/pages/CredibleSetPage/Profile.tsx
index 41ea78c51..41d35c46d 100644
--- a/apps/platform/src/pages/CredibleSetPage/Profile.tsx
+++ b/apps/platform/src/pages/CredibleSetPage/Profile.tsx
@@ -53,7 +53,7 @@ function Profile({ studyLocusId, variantId, referenceAllele, alternateAllele }:
variables={{ studyLocusId: studyLocusId, variantIds: [variantId] }}
client={client}
>
-
+
diff --git a/apps/platform/src/pages/CredibleSetPage/ProfileHeader.gql b/apps/platform/src/pages/CredibleSetPage/ProfileHeader.gql
index 15d1846f6..c5af1b08f 100644
--- a/apps/platform/src/pages/CredibleSetPage/ProfileHeader.gql
+++ b/apps/platform/src/pages/CredibleSetPage/ProfileHeader.gql
@@ -49,6 +49,8 @@ fragment CredibleSetProfileHeaderFragment on credibleSet {
publicationJournal
pubmedId
nSamples
+ cohorts
+ initialSampleSize
studyType
hasSumstats
analysisFlags
diff --git a/apps/platform/src/pages/CredibleSetPage/ProfileHeader.tsx b/apps/platform/src/pages/CredibleSetPage/ProfileHeader.tsx
index a0132e87b..ad7c568ee 100644
--- a/apps/platform/src/pages/CredibleSetPage/ProfileHeader.tsx
+++ b/apps/platform/src/pages/CredibleSetPage/ProfileHeader.tsx
@@ -10,71 +10,15 @@ import {
ClinvarStars,
LabelChip,
DetailPopover,
+ SummaryStatsTable,
+ DisplaySampleSize,
} from "ui";
import { Box, Typography } from "@mui/material";
import CREDIBLE_SET_PROFILE_HEADER_FRAGMENT from "./ProfileHeader.gql";
-import { getStudyCategory } from "sections/src/utils/getStudyCategory";
import { epmcUrl } from "../../utils/urls";
-import { credsetConfidenceMap, poulationMap } from "../../constants";
-import { v1 } from "uuid";
+import { credsetConfidenceMap, populationMap } from "../../constants";
-type ProfileHeaderProps = {
- variantId: string;
-};
-
-const dicSummary = [
- { id: "n_variants", label: "Total variants", tooltip: "Number of harmonised variants" },
- { id: "n_variants_sig", label: "Significant variants", tooltip: "P-value significant variants" },
- { id: "mean_beta", label: "Mean beta", tooltip: "Mean effect size across all variants" },
- {
- id: "gc_lambda",
- label: "GC lambda",
- tooltip: "Additive Genomic Control (GC) lambda indicating GWAS inflation",
- },
- {
- id: "mean_diff_pz",
- label: "Mean diff P-Z",
- tooltip: "Mean difference between reported and calculated log p-values",
- },
- {
- id: "se_diff_pz",
- label: "SD diff P-Z",
- tooltip: "Standard deviation of the difference between reported and calculated log p-values",
- },
-];
-
-function SummaryStatsTable({ sumstatQCValues }: any) {
- return (
- <>
-
- Harmonised summary statistics
-
-
-
- {dicSummary.map((sumstat: any) => {
- const summStatValue = sumstatQCValues.find(
- (v: any) => v.QCCheckName === sumstat.id
- ).QCCheckValue;
- return (
-
-
-
- {sumstat.label}
-
-
-
- {summStatValue}
-
-
- );
- })}
-
-
- >
- );
-}
-
-function ProfileHeader({ variantId }: ProfileHeaderProps) {
+function ProfileHeader() {
const { loading, error, data } = usePlatformApi();
// TODO: Errors!
@@ -82,7 +26,6 @@ function ProfileHeader({ variantId }: ProfileHeaderProps) {
const credibleSet = data?.credibleSet;
const study = credibleSet?.study;
- const studyCategory = study ? getStudyCategory(study.projectId) : null;
const target = study?.target;
const leadVariant = credibleSet?.locus.rows[0];
const beta = leadVariant?.beta ?? credibleSet?.beta;
@@ -249,7 +192,7 @@ function ProfileHeader({ variantId }: ProfileHeaderProps) {
{study?.studyType.replace(/(qtl|gwas)/gi, match => match.toUpperCase())} Study
- {studyCategory !== "QTL" && (
+ {study?.studyType === "gwas" && (
<>
{study?.traitFromSource}
@@ -276,7 +219,7 @@ function ProfileHeader({ variantId }: ProfileHeaderProps) {
)}
>
)}
- {studyCategory === "QTL" && (
+ {study?.studyType !== "gwas" && (
<>
{target?.id && (
@@ -308,18 +251,9 @@ function ProfileHeader({ variantId }: ProfileHeaderProps) {
)}
- {study?.analysisFlags && (
-
- Analysis
-
- }
- >
- {study?.analysisFlags ? study.analysisFlags : "Not Available"}
-
- )}
+
+ {study?.analysisFlags?.join(", ")}
+
{!study?.hasSumstats
? "Not Available"
@@ -330,21 +264,27 @@ function ProfileHeader({ variantId }: ProfileHeaderProps) {
: "Available"
}
-
- {study?.nSamples.toLocaleString()}
-
-
- {/* LD Ancestries */}
- {study?.ldPopulationStructure?.length > 0 &&
- study.ldPopulationStructure.map(({ ldPopulation, relativeSampleSize }, index) => (
+ {study?.nSamples &&
+
+
+
+ }
+ {study?.ldPopulationStructure?.length > 0 &&
+
+ {study.ldPopulationStructure.map(({ ldPopulation, relativeSampleSize }) => (
))}
-
+
+ }
);
diff --git a/apps/platform/src/pages/StudyPage/Header.tsx b/apps/platform/src/pages/StudyPage/Header.tsx
index 2818075a5..35150ea40 100644
--- a/apps/platform/src/pages/StudyPage/Header.tsx
+++ b/apps/platform/src/pages/StudyPage/Header.tsx
@@ -29,7 +29,7 @@ function Header({
if (diseases?.length) {
traitLinks = (
d.id)}
names={diseases.map(d => d.name)}
diff --git a/apps/platform/src/pages/StudyPage/Profile.tsx b/apps/platform/src/pages/StudyPage/Profile.tsx
index 1e135061f..bb4eddcb3 100644
--- a/apps/platform/src/pages/StudyPage/Profile.tsx
+++ b/apps/platform/src/pages/StudyPage/Profile.tsx
@@ -68,7 +68,7 @@ function Profile({ studyId, studyType, projectId, diseases }: ProfileProps) {
}}
client={client}
>
-
+
{studyType === "gwas" && (
diff --git a/apps/platform/src/pages/StudyPage/StudyProfileHeader.gql b/apps/platform/src/pages/StudyPage/StudyProfileHeader.gql
index 5f83a1d3d..425202661 100644
--- a/apps/platform/src/pages/StudyPage/StudyProfileHeader.gql
+++ b/apps/platform/src/pages/StudyPage/StudyProfileHeader.gql
@@ -1,15 +1,24 @@
fragment StudyProfileHeaderFragment on Gwas {
+ studyType
publicationFirstAuthor
publicationDate
publicationJournal
pubmedId
traitFromSource
+ backgroundTraits {
+ id
+ name
+ }
+ diseases {
+ id
+ name
+ }
+ target {
+ id
+ approvedSymbol
+ }
nSamples
initialSampleSize
- replicationSamples {
- sampleSize
- ancestry
- }
nCases
nControls
cohorts
@@ -17,10 +26,15 @@ fragment StudyProfileHeaderFragment on Gwas {
ldPopulation
relativeSampleSize
}
+ hasSumstats
+ sumstatQCValues {
+ QCCheckName
+ QCCheckValue
+ }
qualityControls
analysisFlags
- discoverySamples {
- sampleSize
- ancestry
+ biosample {
+ biosampleId
+ biosampleName
}
}
diff --git a/apps/platform/src/pages/StudyPage/StudyProfileHeader.tsx b/apps/platform/src/pages/StudyPage/StudyProfileHeader.tsx
index 0f58c0243..877947830 100644
--- a/apps/platform/src/pages/StudyPage/StudyProfileHeader.tsx
+++ b/apps/platform/src/pages/StudyPage/StudyProfileHeader.tsx
@@ -1,136 +1,178 @@
-import { usePlatformApi, Link, Field, ProfileHeader as BaseProfileHeader, Tooltip } from "ui";
-import { Typography, Box } from "@mui/material";
+import { Fragment } from "react";
+import {
+ usePlatformApi,
+ Link,
+ Field,
+ ProfileHeader as BaseProfileHeader,
+ DetailPopover,
+ SummaryStatsTable,
+ LabelChip,
+ DisplaySampleSize,
+} from "ui";
+import { Box } from "@mui/material";
+import { populationMap } from "../../constants";
import STUDY_PROFILE_HEADER_FRAGMENT from "./StudyProfileHeader.gql";
-type samplesType = {
- ancestry: string;
- sampleSize: number;
-}[];
-
-function formatSamples(samples: samplesType) {
- return samples.map(({ ancestry, sampleSize }) => `${ancestry}: ${sampleSize}`).join(", ");
-}
-
-type ProfileHeaderProps = {
- studyCategory: string;
-};
-
-function ProfileHeader({ studyCategory }: ProfileHeaderProps) {
+function ProfileHeader() {
const { loading, error, data } = usePlatformApi();
- // TODO: Errors!
+ // TODO: Errors!
if (error) return null;
const {
+ studyType,
publicationFirstAuthor,
publicationDate,
publicationJournal,
pubmedId,
+ hasSumstats,
+ sumstatQCValues,
nSamples,
initialSampleSize,
- replicationSamples,
traitFromSource,
+ backgroundTraits,
+ diseases,
+ target,
nCases,
nControls,
cohorts,
ldPopulationStructure,
qualityControls,
analysisFlags,
- discoverySamples,
+ biosample,
} = data?.study || {};
return (
- <>
-
- {publicationFirstAuthor}
-
-
- {publicationDate}
-
-
- {publicationJournal}
-
-
-
- {pubmedId}
-
-
-
- {traitFromSource}
-
-
- {nSamples}
+
+
+
+ {studyType?.replace(/(qtl|gwas)/gi, match => match.toUpperCase())}
-
- {studyCategory === "GWAS" ? (
- initialSampleSize
- ) : studyCategory === "FINNGEN" ? (
- discoverySamples?.length ? (
- initialSampleSize ? (
-
- Initial sample size: {initialSampleSize}
-
- }
- showHelpIcon
+ {studyType === "gwas" && (
+ <>
+
+ {traitFromSource}
+
+ {diseases?.length > 0 && (
+
+ {diseases.map(({ id, name }, index) => (
+
+ {index > 0 ? ", " : null}
+ {name}
+
+ ))}
+
+ )}
+ {backgroundTraits?.length > 0 && (
+
+ {backgroundTraits.map(({ id, name }, index) => (
+
+ {index > 0 ? ", " : null}
+ {name}
+
+ ))}
+
+ )}
+ >
+ )}
+ {studyType !== "gwas" && (
+ <>
+ {target?.id && (
+
+ {target.approvedSymbol}
+
+ )}
+ {biosample?.biosampleId && (
+
+
- {formatSamples(discoverySamples)}
-
- ) : (
- formatSamples(discoverySamples)
- )
- ) : null
- ) : null}
-
-
- {studyCategory === "GWAS" &&
- replicationSamples?.length &&
- formatSamples(replicationSamples)}
+ {biosample.biosampleName}
+
+
+ )}
+ >
+ )}
+ {publicationFirstAuthor && (
+
+ {publicationFirstAuthor} et al. {publicationJournal} (
+ {publicationDate?.slice(0, 4)})
+
+ )}
+ {pubmedId &&
+
+
+ {pubmedId}
+
+
+ }
+
+
+
+
+ {!hasSumstats
+ ? "Not Available"
+ : sumstatQCValues
+ ?
+
+
+ : "Available"
+ }
+ {qualityControls?.length > 0 &&
+
+
+
+ {qualityControls.map(warning => (
+ {warning}
+ ))}
+
+
+
+ }
+ {nSamples &&
+
+
+
+ }
- {nCases}
+ {/* do not show anything when value 0 */}
+ {nCases ? nCases?.toLocaleString() : null}
- {nControls}
+ {/* do not show anything when value 0 */}
+ {nCases ? nControls?.toLocaleString() : null}
-
- {((studyCategory === "GWAS" && cohorts?.length) || studyCategory === "FINNGEN") &&
- (ldPopulationStructure?.length ? (
-
-
- LD populations and relative sample sizes
-
- {ldPopulationStructure.map(({ ldPopulation, relativeSampleSize }) => (
-
-
- {ldPopulation}: {relativeSampleSize}
-
-
- ))}
- >
- }
- showHelpIcon
- >
- {studyCategory === "GWAS" ? cohorts.join(", ") : "FinnGen"}
-
- ) : studyCategory === "GWAS" ? (
- cohorts.join(", ")
- ) : (
- "FinnGen"
- ))}
+
+ {analysisFlags?.join(", ")}
-
- {studyCategory === "GWAS" && qualityControls?.length && qualityControls.join(", ")}
-
-
- {studyCategory === "GWAS" && analysisFlags?.length && analysisFlags.join(", ")}
-
- >
+ {ldPopulationStructure?.length > 0 &&
+
+ {ldPopulationStructure.map(({ ldPopulation, relativeSampleSize }) => (
+
+ ))}
+
+ }
+
+
);
}
diff --git a/packages/sections/src/study/SharedTraitStudies/Body.tsx b/packages/sections/src/study/SharedTraitStudies/Body.tsx
index 14796e68c..68ef3d35f 100644
--- a/packages/sections/src/study/SharedTraitStudies/Body.tsx
+++ b/packages/sections/src/study/SharedTraitStudies/Body.tsx
@@ -43,34 +43,6 @@ function getColumns(diseaseIds: string[]) {
id: "traitFromSource",
label: "Reported trait",
},
- {
- id: "author",
- label: "First author",
- renderCell: ({ projectId, publicationFirstAuthor }) =>
- getStudyCategory(projectId) === "FINNGEN" ? "FinnGen" : publicationFirstAuthor || naLabel,
- exportValue: ({ projectId, publicationFirstAuthor }) =>
- getStudyCategory(projectId) === "FINNGEN" ? "FinnGen" : publicationFirstAuthor,
- },
- {
- id: "publicationDate",
- label: "Year",
- renderCell: ({ projectId, publicationDate }) =>
- getStudyCategory(projectId) === "FINNGEN"
- ? "2023"
- : publicationDate
- ? publicationDate.slice(0, 4)
- : naLabel,
- exportValue: ({ projectId, publicationYear }) =>
- getStudyCategory(projectId) === "FINNGEN" ? "2023" : publicationYear,
- },
- {
- id: "publicationJournal",
- label: "Journal",
- renderCell: ({ projectId, publicationJournal }) =>
- getStudyCategory(projectId) === "FINNGEN" ? naLabel : publicationJournal || naLabel,
- exportValue: ({ projectId, publicationJournal }) =>
- getStudyCategory(projectId) === "FINNGEN" ? naLabel : publicationJournal,
- },
{
id: "nSamples",
label: "Sample size",
@@ -113,20 +85,21 @@ function getColumns(diseaseIds: string[]) {
getStudyCategory(projectId) === "FINNGEN"
? "FinnGen"
: cohorts?.length
- ? cohorts.join(", ")
- : null,
+ ? cohorts.join(", ")
+ : null,
},
{
- id: "pubmedId",
- label: "PubMed ID",
- renderCell: ({ projectId, pubmedId }) =>
- getStudyCategory(projectId) === "GWAS" && pubmedId ? (
-
- ) : (
- naLabel
- ),
- exportValue: ({ projectId, pubmedId }) =>
- getStudyCategory(projectId) === "GWAS" && pubmedId ? pubmedId : null,
+ id: "publication",
+ label: "Publication",
+ renderCell: ({ publicationFirstAuthor, publicationDate, pubmedId }) => {
+ if (!publicationFirstAuthor) return naLabel;
+ return
+ },
+ filterValue: ({ publicationYear, publicationFirstAuthor }) =>
+ `${publicationYear} ${publicationFirstAuthor}`,
},
];
}
diff --git a/packages/ui/src/components/DisplaySampleSize.tsx b/packages/ui/src/components/DisplaySampleSize.tsx
new file mode 100644
index 000000000..c991a75c4
--- /dev/null
+++ b/packages/ui/src/components/DisplaySampleSize.tsx
@@ -0,0 +1,32 @@
+import { Typography } from "@mui/material";
+import { Tooltip } from "ui";
+
+type DisplaySampleSizeProps = {
+ nSamples: number;
+ cohorts?: string[];
+ initialSampleSize?: string;
+};
+
+export default function DisplaySampleSize({
+ nSamples,
+ cohorts,
+ initialSampleSize
+}: DisplaySampleSizeProps) {
+
+ const display = <>
+ {nSamples?.toLocaleString()}
+ {cohorts ? ` (cohorts: ${cohorts.join(", ")})` : ""}
+ >;
+
+ if (initialSampleSize) {
+ const title = <>
+ Initial sample size
+ {initialSampleSize}
+ >;
+ return
+ {display}
+ ;
+ }
+
+ return display;
+}
\ No newline at end of file
diff --git a/packages/ui/src/components/SummaryStatsTable.tsx b/packages/ui/src/components/SummaryStatsTable.tsx
new file mode 100644
index 000000000..a548d3ea3
--- /dev/null
+++ b/packages/ui/src/components/SummaryStatsTable.tsx
@@ -0,0 +1,56 @@
+
+import { Typography } from "@mui/material";
+import { v1 } from "uuid";
+import { Tooltip } from "ui";
+
+const dicSummary = [
+ { id: "n_variants", label: "Total variants", tooltip: "Number of harmonised variants" },
+ { id: "n_variants_sig", label: "Significant variants", tooltip: "P-value significant variants" },
+ { id: "mean_beta", label: "Mean beta", tooltip: "Mean effect size across all variants" },
+ {
+ id: "gc_lambda",
+ label: "GC lambda",
+ tooltip: "Additive Genomic Control (GC) lambda indicating GWAS inflation",
+ },
+ {
+ id: "mean_diff_pz",
+ label: "Mean diff P-Z",
+ tooltip: "Mean difference between reported and calculated log p-values",
+ },
+ {
+ id: "se_diff_pz",
+ label: "SD diff P-Z",
+ tooltip: "Standard deviation of the difference between reported and calculated log p-values",
+ },
+];
+
+export default function SummaryStatsTable({ sumstatQCValues }: any) {
+ return (
+ <>
+
+ Harmonised summary statistics
+
+
+
+ {dicSummary.map((sumstat: any) => {
+ const summStatValue = sumstatQCValues.find(
+ (v: any) => v.QCCheckName === sumstat.id
+ ).QCCheckValue;
+ return (
+
+
+
+ {sumstat.label}
+
+
+
+ {summStatValue}
+
+
+ );
+ })}
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/packages/ui/src/index.tsx b/packages/ui/src/index.tsx
index c0e9e419b..b7998bbfc 100644
--- a/packages/ui/src/index.tsx
+++ b/packages/ui/src/index.tsx
@@ -16,6 +16,7 @@ export { default as TooltipStyledLabel } from "./components/TooltipStyledLabel";
export { default as DirectionOfEffectIcon } from "./components/DirectionOfEffectIcon";
export { default as DirectionOfEffectTooltip } from "./components/DirectionOfEffectTooltip";
export { default as DisplayVariantId } from "./components/DisplayVariantId";
+export { default as DisplaySampleSize } from "./components/DisplaySampleSize";
export { default as LabelChip } from "./components/LabelChip";
export { default as BasePage } from "./components/BasePage";
export { default as NewChip } from "./components/NewChip";
@@ -28,6 +29,7 @@ export { default as EllsWrapper } from "./components/EllsWrapper";
export { default as ErrorBoundary } from "./components/ErrorBoundary";
export { default as GlobalSearch } from "./components/GlobalSearch/GlobalSearch";
export { default as DetailPopover } from "./components/DetailPopover";
+export { default as SummaryStatsTable } from "./components/SummaryStatsTable";
export { default as PrivateWrapper } from "./components/PrivateWrapper";
export { default as NavBar } from "./components/NavBar";