diff --git a/package.json b/package.json index 326eb2a2..10147964 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "classnames": "^2.2.6", "env-cmd": "^10.1.0", "file-saver": "^2.0.5", - "fs": "0.0.1-security", + "fs": "^0.0.1-security", "json2csv": "^5.0.6", "leaflet": "^1.7.1", "lodash": "^4.17.21", diff --git a/src/modules/service-pages/ontomapsComponents.js b/src/components/OntomapsComponents.js similarity index 97% rename from src/modules/service-pages/ontomapsComponents.js rename to src/components/OntomapsComponents.js index 22b55119..203c98b7 100644 --- a/src/modules/service-pages/ontomapsComponents.js +++ b/src/components/OntomapsComponents.js @@ -1,4 +1,4 @@ -import { ontologymapsUrl, useProgenetixApi } from "../../hooks/api" +import { ontologymapsUrl, useProgenetixApi } from "../hooks/api" import Link from "next/link" export function CodeGroups({ codeGroups, ontomapsUrl }) { diff --git a/src/components/SearchPage.js b/src/components/SearchPage.js new file mode 100644 index 00000000..39fe77f3 --- /dev/null +++ b/src/components/SearchPage.js @@ -0,0 +1,20 @@ +import React from "react" +import { Layout } from "./Layout" +import BiosamplesSearchPanel from "./searchForm/BiosamplesSearchPanel" +import parametersConfig from "../config/beaconSearchParameters.yaml" +import beaconQueryTypes from "../config/beaconQueryTypes.yaml" +import requestTypeExamples from "../config/beaconSearchExamples.yaml" + +export default function Page({ cytoBands }) { + return ( + + + + ) +} diff --git a/src/components/searchForm/BiosamplesSearchForm.js b/src/components/searchForm/BiosamplesSearchForm.js index 1319e8fe..e0d72d20 100644 --- a/src/components/searchForm/BiosamplesSearchForm.js +++ b/src/components/searchForm/BiosamplesSearchForm.js @@ -223,6 +223,13 @@ export function BeaconSearchForm({ /> )}
+
-
@@ -264,31 +272,50 @@ export function BeaconSearchForm({ {...parameters.referenceName} {...selectProps} /> - +
+ @@ -23,6 +29,15 @@ export default function ChromosomePreview({ watch, cytoBands }) { width={width} /> )} + {shouldDisplayMate && ( + + )}
) } diff --git a/src/components/searchResults/BiosamplesResults.js b/src/components/searchResults/BiosamplesResults.js index b44ae53e..5a45c0b0 100644 --- a/src/components/searchResults/BiosamplesResults.js +++ b/src/components/searchResults/BiosamplesResults.js @@ -84,6 +84,24 @@ function QuerySummary({ query }) { {query.end} )} + {query.mateName && ( +
  • + Adjacent Chro: + {query.mateName} +
  • + )} + {query.mateStart && ( +
  • + Adj. Start: + {query.mateStart} +
  • + )} + {query.mateEnd && ( +
  • + Adj. End: + {query.mateEnd} +
  • + )} {query.variantType && (
  • Type: diff --git a/src/components/searchResults/DatasetResultBox.js b/src/components/searchResults/DatasetResultBox.js index fff17d3b..cd645e4b 100644 --- a/src/components/searchResults/DatasetResultBox.js +++ b/src/components/searchResults/DatasetResultBox.js @@ -2,6 +2,7 @@ import React, { useRef, useState } from "react" import { // MAX_HISTO_SAMPLES, // SITE_DEFAULTS, + getVisualizationLink, replaceWithProxy, useProgenetixApi, useExtendedSWR @@ -17,7 +18,6 @@ import BiosamplesStatsDataTable from "./BiosamplesStatsDataTable" import { WithData } from "../Loader" import { openJsonInNewTab } from "../../utils/files" // import dynamic from "next/dynamic" -import { getVisualizationLink } from "../../modules/service-pages/dataVisualizationPage" const HANDOVER_IDS = { histoplot: "histoplot", diff --git a/src/config/DIPG_searchExamples.yaml b/src/config/DIPG_searchExamples.yaml deleted file mode 100644 index 20435c91..00000000 --- a/src/config/DIPG_searchExamples.yaml +++ /dev/null @@ -1,63 +0,0 @@ ---- -- label: "SNV Example" - note: "Example for specific EIF4A1 mutation" - description: | - This example shows a core Beacon query, against a specific - mutation in the EIF4A1 gene, in the DIPG childhood brain tumor dataset. - parameters: - referenceName: - defaultValue: "refseq:NC_000017.11" - start: - defaultValue: 7577121 - alternateBases: - defaultValue: "A" - referenceBases: - defaultValue: "G" -- label: "SNV Range Example" - note: "Example for EIF4A1 transcript region matches (precise variants)" - description: > - As in the standard SNV query, this example shows a Beacon query against mutations in the EIF4A1 gene in the DIPG childhood brain tumor dataset. However, this range + wildcard query will return any variant with alternate bases (indicated through "N"). - Since parameters will be interpreted using an "AND" paradigm, either Alternate Bases OR Variant Type should be specified. The exact variants which were being found can be retrieved through the variant handover [H—>O] link. - parameters: - referenceName: - defaultValue: "refseq:NC_000017.11" - start: - defaultValue: 7572826 - end: - defaultValue: 7579005 - variantType: - defaultValue: "" - alternateBases: - defaultValue: "" - referenceBases: - defaultValue: "" -- label: "CDKN2A Deletion Example" - note: "Example for focal CDKN2A deletion matches." - description: | - This example shows the query for CNV deletion variants overlapping the CDKN2A gene's coding region with at least a single base, but limited to "highly focal" hits (here i.e. <= ~1Mbp in size) in Glioblastoma samples. The query can be modified e.g. through changing the position parameters or diagnosis. - parameters: - referenceName: - defaultValue: "refseq:NC_000009.12" - start: - defaultValue: "21500001-21975098" - end: - defaultValue: "21967753-22500000" - variantType: - defaultValue: "EFO:0030067" - bioontology: - defaultValue: ["NCIT:C3058"] -- label: "MYC Duplication" - note: "Example for focal MYC Duplications." - description: | - The example parameters will select samples with a continuous, focal duplication of the complete MYC coding region. The serarch will be limited to neoplastic samples (EFO:0009656). - parameters: - referenceName: - defaultValue: "refseq:NC_000008.11" - start: - defaultValue: "124000000-127736593" - end: - defaultValue: "127740957-130000000" - variantType: - defaultValue: "EFO:0030070" - materialtype: - defaultValue: "EFO:0009656" diff --git a/src/config/DIPG_searchParameters.yaml b/src/config/DIPG_searchParameters.yaml deleted file mode 100644 index 08d64bda..00000000 --- a/src/config/DIPG_searchParameters.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -note: "" -label: "" -description: "" -parameters: - datasetIds: - defaultValue: ["progenetix"] - isHidden: true - cohorts: - defaultValue: ["pgx:cohort-DIPG"] - isHidden: true - end: - isHidden: true - variantType: - isHidden: true diff --git a/src/config/TCGA_searchExamples.yaml b/src/config/TCGA_searchExamples.yaml deleted file mode 100644 index 13a33d7f..00000000 --- a/src/config/TCGA_searchExamples.yaml +++ /dev/null @@ -1,37 +0,0 @@ ---- -- label: "CDKN2A Deletion Example" - note: "Example for focal CDKN2A deletion matches." - description: | - This example shows the query for CNV deletion variants overlapping the - CDKN2A gene's coding region with at least a single base, but limited - to "highly focal" hits (here i.e. <= ~1Mbp in size) in Glioblastoma samples. The query can be modified e.g. through changing the position parameters or diagnosis. - parameters: - referenceName: - defaultValue: "refseq:NC_000009.12" - start: - defaultValue: "21500001-21975098" - end: - defaultValue: "21967753-22500000" - variantType: - defaultValue: "EFO:0030067" - allTermsFilters: - defaultValue: ["NCIT:C3058", "pgx:cohort-TCGA"] - isHidden: false -- label: "MYC Duplication" - note: "Example for focal MYC Duplications." - description: | - The example parameters will select samples with a continuous, focal duplication of the complete MYC coding region. The serarch will be limited to neoplastic samples (EFO:0009656). - parameters: - referenceName: - defaultValue: "refseq:NC_000008.11" - start: - defaultValue: "124000000-127736593" - end: - defaultValue: "127740957-130000000" - variantType: - defaultValue: "EFO:0030070" - materialtype: - defaultValue: "EFO:0009656" - allTermsFilters: - defaultValue: ["pgx:cohort-TCGA"] - isHidden: false diff --git a/src/config/TCGA_searchParameters.yaml b/src/config/TCGA_searchParameters.yaml deleted file mode 100644 index c44735d2..00000000 --- a/src/config/TCGA_searchParameters.yaml +++ /dev/null @@ -1,31 +0,0 @@ ---- -note: "" -label: "" -description: "" -parameters: - datasetIds: - defaultValue: ["progenetix"] - isHidden: false - referenceName: - placeholder: "9" - start: - placeholder: "19000001-21975098" - end: - placeholder: "21967753-24000000" - variantType: - placeholder: "EFO:0030067" - alternateBases: - placeholder: "" - isHidden: true - referenceBases: - placeholder: "" - isHidden: true - accessid: - isHidden: true - sex: - placeholder: "" - materialtype: - placeholder: "EFO:0009656" #"EFO:0009656" - allTermsFilters: - defaultValue: ["pgx:cohort-TCGA"] - isHidden: false diff --git a/src/config/arraymap_searchExamples.yaml b/src/config/arraymap_searchExamples.yaml deleted file mode 100644 index a8c2a323..00000000 --- a/src/config/arraymap_searchExamples.yaml +++ /dev/null @@ -1,75 +0,0 @@ ---- -- label: "CDKN2A Deletion Example" - note: "Example for focal CDKN2A deletion matches." - description: | - This example shows the query for CNV deletion variants overlapping the - CDKN2A gene's coding region with at least a single base, but limited - to "highly focal" hits (here i.e. <= ~1Mbp in size). The query can be modified e.g. through changing the position parameters or diagnosis. - parameters: - referenceName: - defaultValue: "refseq:NC_000009.12" - start: - defaultValue: "21500001-21975098" - end: - defaultValue: "21967753-22500000" - variantType: - defaultValue: "EFO:0030067" - allTermsFilters: - defaultValue: ["NCIT:C3058", "pgx:cohort-arraymap"] - isHidden: false -- label: "MYC Duplication" - note: "Example for focal MYC Duplications." - description: | - The example parameters will select samples with a continuous, focal duplication - of the complete MYC coding region. The serarch will be limited to "pgx:icdom-80463" - (i.e. ICD-O 3 8046/3, Non-small cell carcinoma). - parameters: - referenceName: - defaultValue: "refseq:NC_000008.11" - start: - defaultValue: "124000000-127736593" - end: - defaultValue: "127740957-130000000" - variantType: - defaultValue: "EFO:0030070" - allTermsFilters: - defaultValue: ["pgx:icdom-80463", "pgx:cohort-arraymap"] - isHidden: false -- label: "TP53 Del. in Cell Lines" - note: "Example for TP53 deletion" - description: >- - Query example for an "any overlap", focal deletion in TP53 where the - search will be limited to cell lines, searched with limit to the "EFO:0030035" - material code. - parameters: - referenceName: - defaultValue: "refseq:NC_000017.11" - start: - defaultValue: "5000000-7676592" - end: - defaultValue: "7669608-10000000" - variantType: - defaultValue: "EFO:0030067" - allTermsFilters: - defaultValue: ["EFO:0030035", "pgx:cohort-arraymap"] - isHidden: false -- label: "K-562 Cell Line" - note: "Instances of K-562 and daughter cell lines, searched by Cellosaurus id" - description: | - The query retrieves all instances of K-562 and derived cell lines - using the "cellosaurus:CVCL_0004" identifier. This is an example for a - pure "non-variant" query. - parameters: - referenceName: - defaultValue: "" - start: - defaultValue: "" - end: - defaultValue: "" - variantType: - defaultValue: "" - referenceid: - defaultValue: ["cellosaurus:CVCL_0004"] - allTermsFilters: - defaultValue: ["pgx:cohort-arraymap"] - isHidden: false diff --git a/src/config/arraymap_searchParameters.yaml b/src/config/arraymap_searchParameters.yaml deleted file mode 100644 index 03f1630d..00000000 --- a/src/config/arraymap_searchParameters.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -note: "" -label: "" -description: "" -parameters: - datasetIds: - defaultValue: ["progenetix"] - isHidden: true - allTermsFilters: - defaultValue: ["pgx:cohort-arraymap"] - isHidden: false diff --git a/src/config/beaconSearchExamples.yaml b/src/config/beaconSearchExamples.yaml index 132c71d1..3dc96131 100644 --- a/src/config/beaconSearchExamples.yaml +++ b/src/config/beaconSearchExamples.yaml @@ -186,3 +186,37 @@ isHidden: true referenceBases: isHidden: true + +- label: "Fusion Example" + note: | + This is an experimental example for a fusion query (by positions). + http://progenetix.org/beacon/g_variants/?referenceName=8&mateName=12&start=45100000&end=47300000&mateStart=26200000&mateEnd=35600000&variantType=SO:0000806 + description: | + This is an experimental example for a fusion query (by positions). + parameters: + datasetIds: + isHidden: false + defaultValue: ["progenetix"] + variantType: + isHidden: false + defaultValue: SO:0000806 + allTermsFilters: + isHidden: false + referenceName: + isHidden: false + defaultValue: refseq:NC_000008.11 + mateName: + isHidden: false + defaultValue: refseq:NC_000012.12 + start: + isHidden: false + defaultValue: 45100000 + end: + isHidden: false + defaultValue: 47300000 + mateStart: + isHidden: false + defaultValue: 26200000 + mateEnd: + isHidden: false + defaultValue: 35600000 diff --git a/src/config/carriocordo2021heterogeneity_searchExamples.yaml b/src/config/carriocordo2021heterogeneity_searchExamples.yaml deleted file mode 100644 index fa0e9336..00000000 --- a/src/config/carriocordo2021heterogeneity_searchExamples.yaml +++ /dev/null @@ -1,33 +0,0 @@ ---- -- label: "CDKN2A Deletion Example" - note: "Example for focal CDKN2A deletion matches." - description: | - This example shows the query for CNV deletion variants overlapping the - CDKN2A gene's coding region with at least a single base, but limited - to "highly focal" hits (here i.e. <= ~1Mbp in size) in Glioblastoma samples. The query can be modified e.g. through changing the position parameters or diagnosis. - parameters: - referenceName: - defaultValue: "refseq:NC_000009.12" - start: - defaultValue: "21500001-21975098" - end: - defaultValue: "21967753-22500000" - variantType: - defaultValue: "EFO:0030067" - bioontology: - defaultValue: ["NCIT:C3058"] -- label: "MYC Duplication" - note: "Example for focal MYC Duplications." - description: | - The example parameters will select samples with a continuous, focal duplication of the complete MYC coding region. The serarch will be limited to neoplastic samples (EFO:0009656). - parameters: - referenceName: - defaultValue: "refseq:NC_000008.11" - start: - defaultValue: "124000000-127736593" - end: - defaultValue: "127740957-130000000" - variantType: - defaultValue: "EFO:0030070" - materialtype: - defaultValue: "EFO:0009656" diff --git a/src/config/carriocordo2021heterogeneity_searchParameters.yaml b/src/config/carriocordo2021heterogeneity_searchParameters.yaml deleted file mode 100644 index b43908ba..00000000 --- a/src/config/carriocordo2021heterogeneity_searchParameters.yaml +++ /dev/null @@ -1,31 +0,0 @@ ---- -note: "" -label: "" -description: "" -parameters: - datasetIds: - defaultValue: ["progenetix"] - isHidden: true - cohorts: - defaultValue: ["pgx:cohort-carriocordo2021heterogeneity"] - isHidden: true - referenceName: - placeholder: "9" - start: - placeholder: "19000001-21975098" - end: - placeholder: "21967753-24000000" - variantType: - placeholder: "EFO:0030067" - alternateBases: - placeholder: "" - isHidden: true - referenceBases: - placeholder: "" - isHidden: true - accessid: - isHidden: true - sex: - placeholder: "" - materialtype: - placeholder: "EFO:0009656" #"EFO:0009656" diff --git a/src/hooks/api.js b/src/hooks/api.js index 8492291d..d711dff4 100644 --- a/src/hooks/api.js +++ b/src/hooks/api.js @@ -222,6 +222,11 @@ export function useDataVisualization(queryData) { ) } +export function getVisualizationLink(datasetIds, accessId, fileId, skip, limit, count) { + return `/service-collection/dataVisualization?datasetIds=${datasetIds}&accessid=${accessId}&fileId=${fileId}&sampleCount=${count}&skip=${skip}&limit=${limit}` +} + + export function buildDataVisualizationParameters(queryData) { return new URLSearchParams( flattenParams([...Object.entries(queryData)]).filter(([, v]) => !!v) diff --git a/src/modules/data-pages/DIPG_dataPage.js b/src/modules/data-pages/DIPG_dataPage.js deleted file mode 100644 index 6c7b2709..00000000 --- a/src/modules/data-pages/DIPG_dataPage.js +++ /dev/null @@ -1,49 +0,0 @@ -import React from "react" -import { Layout } from "../../components/Layout" -import parametersConfig from "../../config/beaconSearchParameters.yaml" -import beaconQueryTypes from "../../config/beaconQueryTypes.yaml" -// import beaconQueryTypes from "../../config/DIPGqueryTypes.yaml" -import requestTypeExamples from "../../config/DIPG_searchExamples.yaml" - -import { ExternalLink } from "../../components/helpersShared/linkHelpers" - - -import BiosamplesSearchPanel from "../../components/searchForm/BiosamplesSearchPanel" -import Panel from "../../components/Panel" -// import Link from "next/link" - -export default function DIPG_dataPage({ cytoBands }) { - const imgHere = { - float: "right", - width: "160px", - border: "0px", - margin: "-90px -20px 0px 0px" - } - - return ( - - -
    - - This portal allows the exploration of genomic variants in aggressive - childhood gliomas, enabled by the data originally collected for{" "} - - . -
    -
    - -
    - ) -} diff --git a/src/modules/data-pages/NCIT_SubsetsPage.js b/src/modules/data-pages/NCIT_SubsetsPage.js deleted file mode 100644 index 505d992c..00000000 --- a/src/modules/data-pages/NCIT_SubsetsPage.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from "react" -import { Layout } from "../../components/Layout" -import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" - -export default function NCIT_SubsetsPage() { - return ( - -
    -

    - The cancer samples in Progenetix are mapped to several classification - systems. For each of the classes, aggregated date is available by - clicking the code. Additionally, a selection of the corresponding - samples can be initiated by clicking the sample number or selecting - one or more classes through the checkboxes. -

    -

    - Sample selection follows a hierarchical system in which samples - matching the child terms of a selected class are included in the - response. -

    -
    - -
    - ) -} diff --git a/src/modules/data-pages/NCITclinical_SubsetsPage.js b/src/modules/data-pages/NCITclinical_SubsetsPage.js deleted file mode 100644 index f575d82a..00000000 --- a/src/modules/data-pages/NCITclinical_SubsetsPage.js +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import { Layout } from "../../components/Layout" -import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" - -export default function NCITclinical_SubsetsPage() { - return ( - -
    -

    - Where available cancer samples in Progenetix are mapped to with their - standard clinical and histological parameters such as TNM classification - or histological grade. -

    -

    - For each of the classes, aggregated date is available by - clicking the code. Additionally, a selection of the corresponding - samples can be initiated by clicking the sample number or selecting - one or more classes through the checkboxes. Sample selection follows - a hierarchical system in which samples - matching the child terms of a selected class are included in the - response. -

    -
    - - - -
    - ) -} diff --git a/src/modules/data-pages/TCGAcancers_dataPage.js b/src/modules/data-pages/TCGAcancers_dataPage.js deleted file mode 100644 index c480bea8..00000000 --- a/src/modules/data-pages/TCGAcancers_dataPage.js +++ /dev/null @@ -1,50 +0,0 @@ -import React from "react" -import { Layout } from "../../components/Layout" -import { SubsetLoader } from "../../components/SubsetLoader" -import Panel from "../../components/Panel" -import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" - -const datasetIds = "progenetix" -const subsetId = "pgx:cohort-TCGAcancers" - -export default function arraymap_dataPage() { - return ( - - - - - - - - - - - - ) -} - -function ThisSubset() { - return ( - <> -
    - This page represents the TCGA subset of the Progenetix - collection, based on 22142 samples (tumor and reeferences) from The - Cancer Genome Atlas project. The results are based upon data generated - by the TCGA Research Network. Disease-specific subsets of TCGA data (aka. projects) can be - accessed below. - -
    - - ) -} diff --git a/src/modules/data-pages/arraymap_dataPage.js b/src/modules/data-pages/arraymap_dataPage.js deleted file mode 100644 index ac00fea6..00000000 --- a/src/modules/data-pages/arraymap_dataPage.js +++ /dev/null @@ -1,43 +0,0 @@ -import React from "react" -import { Layout } from "../../components/Layout" -import { SubsetLoader } from "../../components/SubsetLoader" -import Panel from "../../components/Panel" - -const datasetIds = "progenetix" -const subsetId = "pgx:cohort-arraymap" - -export default function arraymap_dataPage() { - return ( - - - - - - - - - ) -} - -function ThisSubset() { - return ( - <> -
    - The arrayMap data represents a subset of the Progenetix collection for - which the probe-specific array has been used for data generation. For - these samples, individual array probe plots will be accessible through - the sample details pages. - -
    - - ) -} diff --git a/src/modules/data-pages/cbioportal_SubsetsPage.js b/src/modules/data-pages/cbioportal_SubsetsPage.js deleted file mode 100644 index 8928017e..00000000 --- a/src/modules/data-pages/cbioportal_SubsetsPage.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from "react" -import { Layout } from "../../components/Layout" -import Panel from "../../components/Panel" -import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" - -export default function cbioportal_SubsetsPage() { - return ( - -
    -

    - This page represents samples from different cancer studies derived from cBioPortal. -

    -
    - - - -
    - ) -} - diff --git a/src/modules/data-pages/icdom_SubsetsPage.js b/src/modules/data-pages/icdom_SubsetsPage.js deleted file mode 100644 index 89030e96..00000000 --- a/src/modules/data-pages/icdom_SubsetsPage.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from "react" -import { Layout } from "../../components/Layout" -import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" - -export default function icdom_SubsetsPage() { - return ( - -
    -

    - The cancer samples in Progenetix are mapped to several classification - systems. This page represents samples in a shallow hierarchy according to - their ICD-O 3 histology codes (rewritten to an internal prefix system). -

    -
    - -
    - ) -} - diff --git a/src/modules/data-pages/icdot_SubsetsPage.js b/src/modules/data-pages/icdot_SubsetsPage.js deleted file mode 100644 index 70eb97f3..00000000 --- a/src/modules/data-pages/icdot_SubsetsPage.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from "react" -import { Layout } from "../../components/Layout" -import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" - -export default function icdom_SubsetsPage() { - return ( - -
    -

    - The cancer samples in Progenetix are mapped to several classification - systems. This page represents samples in a shallow hierarchy according to - their ICD-O 3 topography codes (rewritten to an internal prefix system). -

    -
    - -
    - ) -} - diff --git a/src/modules/data-pages/searchPage.js b/src/modules/data-pages/searchPage.js deleted file mode 100644 index ab87fcf2..00000000 --- a/src/modules/data-pages/searchPage.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from "react" -import { Layout } from "../../components/Layout" -import parametersConfig from "../../config/beaconSearchParameters.yaml" -import beaconQueryTypes from "../../config/beaconQueryTypes.yaml" -import requestTypeExamples from "../../config/beaconSearchExamples.yaml" -import BiosamplesSearchPanel from "../../components/searchForm/BiosamplesSearchPanel" - -export default function progenetixdataPage({ cytoBands }) { - return ( - - - - ) -} diff --git a/src/modules/details-pages/analysisPage.js b/src/modules/details-pages/analysisPage.js deleted file mode 100644 index 21cdcac7..00000000 --- a/src/modules/details-pages/analysisPage.js +++ /dev/null @@ -1,131 +0,0 @@ -import { - useDataItemDelivery, - NoResultsHelp, - urlRetrieveIds -} from "../../hooks/api" -import { BeaconRESTLink, InternalLink } from "../../components/helpersShared/linkHelpers" - -import { Loader } from "../../components/Loader" -import { withUrlQuery } from "../../hooks/url-query" -import { Layout } from "../../components/Layout" - -const itemColl = "analyses" -// const exampleId = "pgxcs-kftvlijb" - -const AnalysisDetailsPage = withUrlQuery(({ urlQuery }) => { - const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) - return ( - - {!hasAllParams ? ( - NoResultsHelp(itemColl) - ) : ( - - )} - - ) -}) - -export default AnalysisDetailsPage - -function AnalysisLoader({ csId, datasetIds }) { - const { data, error, isLoading } = useDataItemDelivery( - csId, - itemColl, - datasetIds - ) - return ( - - {data && ( - - )} - - ) -} - -function AnalysisResponse({ response, csId, datasetIds }) { - if (!response.response.resultSets[0].results) { - return NoResultsHelp(itemColl) - } - return -} - -function Analysis({ analysis, csId, datasetIds }) { - return ( - -
    -

    - {csId} -

    - - {analysis.description && ( - <> -
    Description
    -

    {analysis.description}

    - - )} - - {analysis.biosampleId && ( - <> -
    Biosample
    -

    - -

    - - )} - -
    Download
    -
      -
    • Analysis data as{" "} - -
    • -
    • Sample data as{" "} - -
    • -
    • Analysis variants as{" "} - -
    • -
    • Analysis variants as{" "} - -
    • -
    • Analysis variants as{" "} - -
    • -
    - -
    ) - -} diff --git a/src/modules/details-pages/biosamplePage.js b/src/modules/details-pages/biosamplePage.js deleted file mode 100644 index c52a2833..00000000 --- a/src/modules/details-pages/biosamplePage.js +++ /dev/null @@ -1,279 +0,0 @@ -import React, { useEffect, useState } from "react" -import { - BIOKEYS, - SITE_DEFAULTS, - useDataItemDelivery, - NoResultsHelp, - urlRetrieveIds -} from "../../hooks/api" -import { BeaconRESTLink, InternalLink, ReferenceLink } from "../../components/helpersShared/linkHelpers" -import { WithData } from "../../components/Loader" -import { withUrlQuery } from "../../hooks/url-query" -import { AncestryData } from "../../components/AncestryData" -import { Layout } from "../../components/Layout" -import { ShowJSON } from "../../components/RawData" -import { AnalysisHistogram } from "../../components/SVGloaders" -import { pluralizeWord } from "../../components/helpersShared/labelHelpers" - -const itemColl = "biosamples" -// const exampleId = "pgxbs-kftvir6m" - -const SampleDetailsPage = withUrlQuery(({ urlQuery }) => { - const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) - const iURL = `${SITE_DEFAULTS.API_PATH}beacon/biosamples/${id}/individuals?datasetIds=${datasetIds}&limit=1` - var [individual, setIndividual] = useState([]); - useEffect(() => { - fetch( iURL ) - .then((response) => response.json()) - .then((data) => { - console.log(data.response.resultSets[0].results[0]); - setIndividual(data.response.resultSets[0].results[0]) - }) - .catch((err) => { - console.log(err.message); - }); - }, [setIndividual]); - - return ( - - {!hasAllParams ? ( - NoResultsHelp(itemColl) - ) : ( - - )} - - ) -}) - -export default SampleDetailsPage - -/*============================================================================*/ -/*============================================================================*/ -/*============================================================================*/ - -function BiosampleLoader({ biosId, individual, datasetIds }) { - const apiReply = useDataItemDelivery(biosId, itemColl, datasetIds) - - return ( - ( - - )} - /> - ) -} - -/*============================================================================*/ - -function BiosampleResponse({ biosId, response, individual, datasetIds }) { - if (!response.response.resultSets[0].results) { - return NoResultsHelp(itemColl) - } - return -} - -/*============================================================================*/ - -function Biosample({ biosId, biosample, individual, datasetIds }) { - - // console.log(individual); - - return ( - -
    - -

    - Sample Details for {biosId} -

    - - {biosample.notes && ( - <> -
    Description
    -

    {biosample.notes}

    - - )} - -
    Diagnostic Classifications
    -
      - {BIOKEYS.map(bioc => ( -
    • - {biosample[bioc].label}{": "} - -
    • - ))} -
    - - {/*------------------------------------------------------------------------*/} - -
    Donor Details
    - -
      - - {individual?.description && ( -
    • - Description{": "} - {individual.description} -
    • - )} - - {individual?.indexDisease?.diseaseCode && ( -
    • - Diagnosis{": "} - {individual.indexDisease.diseaseCode.id}{" ("} - {individual.indexDisease.diseaseCode?.label}{")"} -
    • - - )} - - {individual?.description && ( -
    • - Description{": "} - {individual.description} -
    • - )} - - {individual?.sex && ( -
    • - Genotypic Sex{": "} - {individual?.sex?.label} ({individual.sex.id}) -
    • - )} - - {individual?.indexDisease?.onset && ( -
    • - Age at Collection{": "} - {individual.indexDisease.onset.age} -
    • - )} - -
    - - {individual?.genomeAncestry && individual?.genomeAncestry?.length > 0 && ( - <> -
    Genomic Ancestry
    - - - )} - - {/*------------------------------------------------------------------------*/} - - {biosample?.provenance && ( - <> -
    Provenance
    -
      - {biosample.provenance?.material?.label && ( - <> -
    • Material: {biosample.biosampleStatus.label}
    • - - )} - {biosample.provenance?.geoLocation?.properties?.label && ( - <> -
    • - Origin: {biosample.provenance.geoLocation.properties.label} -
    • - - )} -
    - - )} - - {biosample.externalReferences && ( - <> -
    External References
    -
      - {biosample.externalReferences.map((externalReference, i) => ( -
    • - {externalReference.description && ( - `${externalReference.description}: ` - )} - {externalReference.label && ( - `${externalReference.label}: ` - )} - {ReferenceLink(externalReference) ? ( - - ) : ( - externalReference.id - )} -
    • - ))} -
    - - )} - - { biosample.info && biosample.info?.callsetIds?.length > 0 && ( - <> -
    CNV {pluralizeWord("Plot", biosample.info.callsetIds.length)}
    - {biosample.info?.callsetIds.map((csid, i) => ( - - ))} - - )} - -
    Download
    -
      -
    • Sample data as{" "} - -
    • -
    • Sample data as{" "} - -
    • -
    • Sample variants as{" "} - -
    • -
    • Sample variants as{" "} - -
    • -
    • Sample variants as{" "} - -
    • -
    - - - -
    - ) -} diff --git a/src/modules/details-pages/individualPage.js b/src/modules/details-pages/individualPage.js deleted file mode 100644 index e3717dd4..00000000 --- a/src/modules/details-pages/individualPage.js +++ /dev/null @@ -1,184 +0,0 @@ -import { - useDataItemDelivery, - NoResultsHelp, - urlRetrieveIds -} from "../../hooks/api" -import { ReferenceLink, BeaconRESTLink, InternalLink, ExternalLink } from "../../components/helpersShared/linkHelpers" -import { AncestryData } from "../../components/AncestryData" -import { WithData } from "../../components/Loader" -import { withUrlQuery } from "../../hooks/url-query" -import { Layout } from "../../components/Layout" -import { ShowJSON } from "../../components/RawData" - -const itemColl = "individuals" -// const exampleId = "pgxind-kftx266l" - -const IndividualDetailsPage = withUrlQuery(({ urlQuery }) => { - const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) - return ( - - {!hasAllParams ? ( - NoResultsHelp(itemColl) - ) : ( - - )} - - ) -}) - -export default IndividualDetailsPage - -function IndividualLoader({ id, datasetIds }) { - const apiReply = useDataItemDelivery(id, itemColl, datasetIds) - return ( - ( - - )} - /> - ) -} - -function IndividualResponse({ response, datasetIds }) { - if (!response.response.resultSets[0].results) { - return NoResultsHelp(itemColl) - } - return -} - -function Individual({ individual, datasetIds }) { - return ( -
    -

    - Individual Details {individual.id} -

    - - {individual.description && ( - <> -
    Description
    -

    {individual.description}

    - - )} - - {individual.sex && ( - <> -
    Genotypic Sex
    -
      -
    • {individual.sex?.label} ({individual.sex.id})
    • -
    - - )} - - {individual.onset && -

    - Age at Collection: {individual.onset?.age} -

    - } - - {individual.diseaseCode && - <> -
    Diagnosis
    -

    {individual.diseaseCode?.label}

    - - } - - {individual.cellLines && - <> -
    Cell Lines
    -
      - {individual.cellLines.map((cl, i) => ( -
    • - {cl.description && (cl.description)} - -
    • - ))} -
    - - } - - {individual?.genomeAncestry && individual?.genomeAncestry?.length > 0 && ( - <> -
    Genomic Ancestry
    - - - )} - - {individual.biosamples && individual.biosamples.length > 0 && - <> -
    Biosamples
    - {individual.biosamples.map((bs, i) => ( -
  • - -
  • - ))} - - } - -
    Download
    -
      -
    • Subject data as{" "} - -
    • -
    • Sample data as{" "} - -
    • -
    • Variants as{" "} - -
    • -
    • Variants as{" "} - -
    • -
    • Variants as{" "} - -
    • -
    - - - -
    - ) -} - diff --git a/src/modules/details-pages/publicationPage.js b/src/modules/details-pages/publicationPage.js deleted file mode 100644 index 07c6a171..00000000 --- a/src/modules/details-pages/publicationPage.js +++ /dev/null @@ -1,147 +0,0 @@ -import React from "react" -import { usePublication } from "../../hooks/api" -import { epmcUrl, EpmcLink, ExternalLink } from "../../components/helpersShared/linkHelpers" -import { WithData } from "../../components/Loader" -import { withUrlQuery } from "../../hooks/url-query" -import { SubsetHistogram } from "../../components/SVGloaders" -import { Layout } from "../../components/Layout" - -const PublicationDetailsPage = withUrlQuery(({ urlQuery }) => { - const { id } = urlQuery - return ( - - {!id ? : } - - ) -}) -export default PublicationDetailsPage - -function NoResults() { - return ( -
    - This page will only show content if called with a specific Pubmed ID which - already exists in the Progenetix `publications` database, e.g.{" "} - - /publication/?id=PMID:9405679 - - . Please start over from the Progenetix Publication Collection page. -
    - ) -} - -function PublicationLoader({ id }) { - const publicationReply = usePublication(id) - return ( - ( - - )} - /> - ) -} - -function PublicationResponse({ results, id }) { - if (results?.length >= 1) { - return results.map((publication, i) => ( - - )) - } else { - return - } -} - -function PublicationDetails({ publication, id }) { - const progenetixBiosamplesCount = publication.counts?.progenetix ?? 0 - const arraymapBiosamplesCount = publication.counts?.arraymap ?? 0 - return ( -
    -

    - -

    -

    {publication.title}

    -

    {publication.authors}

    -

    - {publication.journal} {id} -

    -

    {publication.abstract}

    - -
    Contact
    -
      - {publication.contact?.name != "" && ( -
    • {publication.contact.name}
    • - )} - {publication.contact?.affiliation != "" && ( -
    • {publication.contact.affiliation}
    • - )} - {publication.contact?.email != "" && ( -
    • {publication.contact.email}
    • - )} -
    - -
    Origin
    -

    {publication.provenance.geoLocation.properties?.city}, {publication.provenance.geoLocation.properties?.country}

    - - {publication.progenetixCurator && ( -
    -
    Progenetix Curator
    -

    {publication.progenetixCurator}

    -
    - )} - -
    Genome Screens
    -
      - {technologies.map((technologie, i) => - publication.counts[technologie] ? ( -
    • - {technologie}: {publication.counts[technologie]} -
    • - ) : null - )} - {progenetixBiosamplesCount > 0 && ( -
    • - {progenetixBiosamplesCount} sample profiles are registered in - Progenetix -
    • - )} - {arraymapBiosamplesCount > 0 && ( -
    • - {arraymapBiosamplesCount} sample profiles are registered in arrayMap -
    • - )} -
    - {(progenetixBiosamplesCount > 0 || arraymapBiosamplesCount > 0) && ( - - Retrieve Publication Samples - - )} - - {progenetixBiosamplesCount > 0 && ( -
    - -
    - )} -
    - ) -} - -function sampleSearchHref({ id, progenetixSamplesCount }) { - const datasetsIds = [] - if (progenetixSamplesCount > 0) datasetsIds.push("progenetix") - - return `/biosamples/?allTermsFilters=${id}&datasetIds=${datasetsIds.join( - "," - )}&executeSearch=true` -} - -const technologies = ["ccgh", "acgh", "wes", "wgs"] diff --git a/src/modules/details-pages/subsetPage.js b/src/modules/details-pages/subsetPage.js deleted file mode 100644 index 2b1ddb1f..00000000 --- a/src/modules/details-pages/subsetPage.js +++ /dev/null @@ -1,25 +0,0 @@ -import { - NoResultsHelp, - urlRetrieveIds -} from "../../hooks/api" -import { SubsetLoader } from "../../components/SubsetLoader" -import { Layout } from "../../components/Layout" -import { withUrlQuery } from "../../hooks/url-query" - -// const exampleId = "NCIT:C3262" - -const SubsetDetailsPage = withUrlQuery(({ urlQuery }) => { - const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) - return ( - - {!hasAllParams ? ( - NoResultsHelp("subset details") - ) : ( - - )} - - ) -}) - -export default SubsetDetailsPage - diff --git a/src/modules/details-pages/variantPage.js b/src/modules/details-pages/variantPage.js deleted file mode 100644 index 07248d02..00000000 --- a/src/modules/details-pages/variantPage.js +++ /dev/null @@ -1,217 +0,0 @@ -import { - getDataItemUrl, - useDataItemDelivery, - NoResultsHelp, - urlRetrieveIds -} from "../../hooks/api" -import { ExternalLink, ReferenceLink } from "../../components/helpersShared/linkHelpers" -import { WithData } from "../../components/Loader" -import { withUrlQuery } from "../../hooks/url-query" -import { Layout } from "../../components/Layout" -import { ShowJSON } from "../../components/RawData" -import { BiosamplePlot } from "../../components/SVGloaders" -import React from "react" -import { refseq2chro } from "../../components/Chromosome" - -const entity = "variants" -// const exampleId = "pgxvar-5bab576a727983b2e00b8d32" - -const VariantDetailsPage = withUrlQuery(({ urlQuery }) => { - const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) - return ( - - {!hasAllParams ? ( - NoResultsHelp(entity) - ) : ( - - )} - - ) -}) - -export default VariantDetailsPage - -function VariantLoader({ id, datasetIds }) { - const apiReply = useDataItemDelivery(id, entity, datasetIds) - return ( - ( - // <> - - )} - /> - ) -} - -function VariantResponse({ response, id, datasetIds }) { - if (!response.response.resultSets[0].results[0]) { - return NoResultsHelp(entity) - } - return ( - ) -} - -function Variant({ variant, id, datasetIds }) { - var marker = variant.variantInternalId - var mParts = marker.split(':') - const chro = refseq2chro(mParts[0]) - marker = marker + " (" + mParts[1] + ")" - - return ( -
    -

    - {id} ({datasetIds}) -

    - -
    Digest
    -

    {variant.variantInternalId}

    - {variant.variation?.molecularAttributes && ( - <> -
    Molecular Attributes
    -
      - {variant.variation.molecularAttributes.geneIds && ( -
    • Gene: {variant.variation.molecularAttributes.geneIds[0]}
    • - )} - {variant.variation.molecularAttributes?.molecularEffects && ( -
    • Molecular effect: {variant.variation.molecularAttributes.molecularEffects[0].label}
    • - )} - {variant.variation.molecularAttributes.aminoacidChanges && variant.variation.molecularAttributes.aminoacidChanges.length > 0 && variant.variation.molecularAttributes.aminoacidChanges[0] !== null && ( -
    • Aminoacid changes: -
        - {variant.variation.molecularAttributes.aminoacidChanges.map((aa) => ( -
      • - {aa} -
      • - ))} -
      -
    • - )} -
    - - )} - - {variant.variation?.identifiers && ( - <> -
    Variant Identifiers
    -
      - {variant.variation.identifiers?.proteinHGVSIds && ( -
    • Protein HGVSids: -
        - {variant.variation.identifiers.proteinHGVSIds.map((ph) => -
      • - {ph} -
      • - )} -
      -
    • - )} - - {variant.variation.identifiers?.genomicHGVSIds && ( -
    • Genomic HGVSids: -
        - {variant.variation.identifiers.genomicHGVSIds.map((gh) => -
      • - {gh} -
      • - )} -
      -
    • - )} - - {variant.variation.identifiers?.clinvarIds && ( -
    • ClinVar IDs: -
        -
      • - -
      • -
      -
    • - )} - -
    - - )} - - {variant.variation?.variantAlternativeIds && ( -
    -
    Variant Alternative IDs
    -
      - {variant.variation.variantAlternativeIds.map((altid, key) => ( -
    • - {altid.id} - {altid.label} -
    • - ))} -
    -
    - )} - - {variant.variation?.variantLevelData?.clinicalInterpretations && ( - <> - {variant.variation.variantLevelData && variant.variation.variantLevelData.clinicalInterpretations.length > 0 && ( - <> -
    Clinical Interpretations
    -

    Clinical Relevance: {variant.variation.variantLevelData.clinicalInterpretations[0].clinicalRelevance}

    - - - - - - {variant.variation.variantLevelData.clinicalInterpretations?.map((clinicalInterpretations, key) => { - return ( - - - - - ) - })} -
    IDDescription
    - {ReferenceLink(clinicalInterpretations.effect) ? ( - - ) : ( - clinicalInterpretations.effect.id - )} - {clinicalInterpretations.effect.label}
    - - )} - - )} - -
    - Download Data as Beacon v2{" "} - - {"{JSON↗}"} - -
    - - - - {variant.caseLevelData[0]?.biosampleId && marker && chro && ( - <> -
    Plot
    - - - )} - -
    - ) -} diff --git a/src/modules/publications/PublicationsListPage.js b/src/modules/publications/PublicationsListPage.js deleted file mode 100644 index 0185f956..00000000 --- a/src/modules/publications/PublicationsListPage.js +++ /dev/null @@ -1,168 +0,0 @@ -import React, { useState } from "react" -// import React, { useEffect, useState } from "react" -import { Layout } from "../../components/Layout" -import { Infodot } from "../../components/Infodot" -import { ExternalLink, InternalLink } from "../../components/helpersShared/linkHelpers" -import { PublicationTable } from "../../components/publicationComps/PublicationTables" -import { usePublicationList } from "../../hooks/api" -import { WithData } from "../../components/Loader" -// import { useAsyncSelect } from "../../hooks/asyncSelect" -// import CustomSelect from "../../components/Select" -// import dynamic from "next/dynamic" -// import { sumBy } from "lodash" -import { matchSorter } from "match-sorter" -import useDebounce from "../../hooks/debounce" - -export default function PublicationsListPage() { - // const [geoCity, setGeoCity] = useState(null) - // const [geodistanceKm, setGeodistanceKm] = useState(100) - const [searchInput, setSearchInput] = useState(null) - const debouncedSearchInput = useDebounce(searchInput, 500) - return ( - -
    -

    - The current page lists articles describing whole genome screening - (WGS, WES, aCGH, cCGH) experiments in cancer, registered in the - Progenetix publication collection. Please submit information about additional - articles to our{" "} - - {" "}or email us at{" "}contact@progenetix.org.{" "}The - inclusion criteria are described{" "} - . -

    -
    -
    -
    -
    - {" "} - setSearchInput(e.target.value)} - /> -
    -
    -
    - -
    - ) -} - -function FilteredPublication({ publications, textSearch }) { - const filteredPublications = matchSorter(publications, textSearch, { - keys: ["id", "authors", "title", "pubYear", "pubmedid", "provenance.geoLocation.properties.city"], - threshold: matchSorter.rankings.CONTAINS - }) - return ( - <> -
    - -
    - {/**/} - - ) -} - -function PublicationsLoader({ geoCity, geodistanceKm, textSearch }) { - const publicationsResult = usePublicationList({ - geoCity, - geodistanceKm - }) - - return ( - ( - - )} - /> - ) -} - -/* -
    - - -
    -{geoCity && ( -
    - - setGeodistanceKm(e.target.value)} - /> -
    -)} - -function GeoCityPublicationSelector({ setGeoCity }) { - const { inputValue, value, onChange, onInputChange } = useAsyncSelect() - useEffect(() => setGeoCity(value), [setGeoCity, value]) - const { data, isLoading } = useGeoCity({ city: inputValue }) - let options = [] - if (data) { - if (data.response) { - options = data.response.results.map((g) => ({ - value: g.id, - data: g, - label: `${g.geoLocation.properties.city} (${g.geoLocation.properties.country})` - })) - } - } - return ( - - ) -} -*/ - -// function PublicationsMapContainer({ publications }) { -// const acghSum = sumBy(publications, "counts.acgh") -// const ccghSum = sumBy(publications, "counts.ccgh") -// const wesSum = sumBy(publications, "counts.wes") -// const wgsSum = sumBy(publications, "counts.wgs") -// const publicationsCount = publications.length -// return ( -// <> -//
    -// -//
    -//

    -// Geographic distribution (by corresponding author) of the{" "} -// {acghSum} genomic array, {ccghSum} chromosomal CGH and{" "} -// {wesSum + wgsSum} whole genome/exome based cancer genome datasets -// from the {publicationsCount} listed publications. Area sizes -// correspond to the sample numbers reported from a given location. -//

    -// -// ) -// } - -// const PublicationsMap = dynamic(() => import("../../components/publicationComps/PublicationsMap"), { -// ssr: false -// }) diff --git a/src/modules/publications/PublicationsProgenetixRefListPage.js b/src/modules/publications/PublicationsProgenetixRefListPage.js deleted file mode 100644 index 851da318..00000000 --- a/src/modules/publications/PublicationsProgenetixRefListPage.js +++ /dev/null @@ -1,124 +0,0 @@ -import React, { useState } from "react" -import { Layout } from "../../components/Layout" -import { Infodot } from "../../components/Infodot" -import { PublicationFewCountTable } from "../../components/publicationComps/PublicationTables" -import { ExternalLink } from "../../components/helpersShared/linkHelpers" -import { useProgenetixRefPublicationList } from "../../hooks/api" -import { WithData } from "../../components/Loader" -// import dynamic from "next/dynamic" -import { matchSorter } from "match-sorter" -import useDebounce from "../../hooks/debounce" -import Panel from "../../components/Panel" - -export default function PublicationsProgenetixRefListPage() { - const [searchInput, setSearchInput] = useState(null) - const debouncedSearchInput = useDebounce(searchInput, 500) - const imgHere = { - float: "right", - width: "400px", - border: "0px", - margin: "-100px -10px 0px 0px" - } - - return ( - - - -
    - - This page lists articles which we found to have made use of, or referred to, the Progenetix resource ecosystem. These articles may not necessarily contain original case profiles themselves. -
    -
    - Please contact us to alert - us about additional articles you are aware of. Also, you can now directly - submit suggestions for matching publications to the{" "} - . -
    - - {/*Some article filtering */} -
    -
    - {" "} - setSearchInput(e.target.value)} - /> -
    -
    -
    - - {/* - The PublicationsLoader creates her own Panel for the article table - and then adds the map below. - */} - - - -
    - ) -} - -function FilteredPublication({ publications, textSearch }) { - const filteredPublications = matchSorter(publications, textSearch, { - keys: ["id", "authors", "title", "pubYear", "pubmedid", "provenance.geoLocation.properties.city"], - threshold: matchSorter.rankings.CONTAINS - }) - return ( - <> - - - - {/**/} - - ) -} - -function PublicationsLoader({ textSearch }) { - const publicationsResult = useProgenetixRefPublicationList({ - // geoCity, - // geodistanceKm - }) - - return ( - ( - - )} - /> - ) -} - -// function PublicationsMapContainer({ publications }) { -// const publicationsCount = publications.length -// return ( -// <> -//
    -// -//
    -//

    -// Geographic distribution (by corresponding author) of the{" "} -// {publicationsCount} listed publications which have been found to -// cite and/or use Progenetix. -//

    -// -// ) -// } - -// const PublicationsMap = dynamic(() => import("../../components/publicationComps/PublicationsMap"), { -// ssr: false -// }) - diff --git a/src/modules/service-pages/FileLoaderPage.js b/src/modules/service-pages/FileLoaderPage.js deleted file mode 100644 index 3953e8e2..00000000 --- a/src/modules/service-pages/FileLoaderPage.js +++ /dev/null @@ -1,228 +0,0 @@ -import { SITE_DEFAULTS } from "../../hooks/api" -import { Layout } from "../../components/Layout" -import React, { useState } from "react" -import { useDropzone } from "react-dropzone" -import { uploadFile } from "../../hooks/api" -// import { getVisualizationLink } from "../service-pages/dataVisualizationPage" -// import { SubsetHistogram } from "../../components/SVGloaders" -// import Link from "next/link" -// import ExternalLink from "../../components/helpersShared/linkHelpers" -import Panel from "../../components/Panel" - -export default function FileLoaderPage() { - return ( - - -

    - Here we provide users an option to visualize their own CNV data, using - the standard Progenetix plotting options for histograms and samples. - This functionality is currently limited to single segmens files - without the group labeling options. However, we provide the plotting - libraries as a Perl package through our{" "} - - Github - {" "} - repository. NEW in 2023: We transition to new plotting - methods, provided through the `bycon` package and with demonstration - applications in{" "} - - byconaut - . -

    -
    - -
    - -
    - - -

    - NEW 2021: We now recommend the use of our .pgxseg{" "} - file format for th eupload of CNV segments files. As an extension of - the standard tab-delimited segment file format below, the{" "} - .pgxseg file format allows the addition of e.g. group - label information. The file format is described on our{" "} - - documentation site - - {""}, including link to an example file. -

    -

    - Otherwise, data has to be submitted as tab-delimited .tsv{" "} - segment files. An example file is being provided{" "} - - here - - . -

    -

    - While the header values are not being interpreted (i.e. it doesn not - matter if the column is labeled referenceName or{" "} - chro), the column order has to be respected: -

    -
      -
    1. - biosample_id -
        -
      • please use only word characters, underscores, dashes
      • -
      • - the sample value is used for splitting multi-sample - files into their individual profiles -
      • -
      -
    2. -
    3. - reference_name -
        -
      • the reference chromosome
      • -
      • 1-22, X, Y (23 => X; 24 => Y)
      • -
      -
    4. -
    5. - start -
        -
      • base positions according to the used reference genome
      • -
      -
    6. -
    7. - end -
        -
      • as above
      • -
      -
    8. -
    9. - value -
        -
      • the value of the segment
      • -
      • should be 0-centered log2
      • -
      • - segments not passing the calling thresholds (fallback{" "} - 0.15, -0.15) are being filtered out -
      • -
      • - one can use dummy values (e.g. 1 for gains,{" "} - -1 for losses) -
      • -
      -
    10. -
    11. - variant_type (optional) -
        -
      • the called type of the segment
      • -
      • - one of EFO:0030067 (CN gain) or EFO:0030067 (deletion) -
      • -
      • - this will override a status derived from thresholding the value - in mean -
      • -
      -
    12. -
    -
    -
    - ) -} - -function DataVisualizationUpload() { - const [result, setResult] = useState(null) - return ( -
    - {result ? ( - setResult(null)} /> - ) : ( - - )} -
    - ) -} - -function Dropzone({ setResult }) { - const { getRootProps, getInputProps } = useDropzone({ - accept: [".tsv", ".tab", ".pgxseg"], - onDrop: async (acceptedFiles) => { - const data = new FormData() - data.append("upload_file", acceptedFiles[0], acceptedFiles[0].name) - // data.append("plotType", "histoplot") - const result = await uploadFile(data) - setResult(result) - } - }) - - return ( - <> -
    -
    - -

    Drag and drop some files here, or click to select files.

    -
    -
    - - ) -} - -function Results({ results, onCancelClicked }) { - const fileId = results.fileId - // const visualizationLink = getVisualizationLink("", "", fileId, "", "") - const histoPlotLink = `${SITE_DEFAULTS.API_PATH}services/sampleplots/?datasetIds=upload&fileId=${fileId}` - const samplesPlotLink = `${SITE_DEFAULTS.API_PATH}services/sampleplots/?datasetIds=upload&plotType=samplesplot&fileId=${fileId}` - - console.log("histoPlotLink...", histoPlotLink) - - return ( - <> -
    -
    -

    The file has been successfully uploaded!

    -

    -{/* - Visualization form - -*/} - - CNV Histogram - -

    -

    - - Samples Plot - -

    - or{" "} - -
    -
    - - ) -} diff --git a/src/modules/service-pages/OntologymapsPage.js b/src/modules/service-pages/OntologymapsPage.js deleted file mode 100644 index 487fc151..00000000 --- a/src/modules/service-pages/OntologymapsPage.js +++ /dev/null @@ -1,185 +0,0 @@ -import React, { useEffect, useState } from "react" -import { Infodot } from "../../components/Infodot" -import { Layout } from "../../components/Layout" -import { - ontologymapsBaseUrl, - ontologymapsPrefUrl, - SITE_DEFAULTS -} from "../../hooks/api" -import CustomSelect from "../../components/Select" -import { Loader } from "../../components/Loader" -import { withUrlQuery } from "../../hooks/url-query" -import { - CodeGroups, - useOntologymaps, - useGetFilteredOptions -} from "./ontomapsComponents" - -const filterPrecision = "start" -const prefixes = "NCIT,pgx:icdom,pgx:icdot" -const apiAllMapsURL = `${ontologymapsBaseUrl}filters=${prefixes}` - -export default function OntologymapsPage() { - return ( - -
    - -

    - The ontologymaps service provides equivalency mapping - between ICD-O and other classification systems, notably NCIt and - UBERON. It makes use of the sample-level mappings for NCIT and ICD-O 3 - codes developed for the individual samples in the Progenetix - collection. -

    -

    NCIT and ICD-O 3

    -

    - While NCIT treats diseases as{" "} - histologic and{" "} - topographic described entities (e.g.{" "} - NCIT:C7700:{" "} - Ovarian{" "} - adenocarcinoma), these two - components are represented separately in ICD-O, through the{" "} - Morphology and{" "} - Topography coding arms (e.g. here{" "} - 8140/3 +{" "} - C56.9). -

    -

    - More documentation with focus on the API functionality can be found on - the documentation pages. -

    -

    - The data of all mappings can be retrieved trough this API call:{" "} - - {"{JSON↗}"} - -

    -
    - -
    - ) -} - -const NCITmapsSelection = withUrlQuery(({ urlQuery, setUrlQuery }) => { - const { options: allOntologiesOptions } = useGetFilteredOptions({ - filters: prefixes, - filterPrecision: filterPrecision - }) - - const [firstSelection, setFirstSelection] = useState(urlQuery.firstSelection) - const handleFirstSelectionChange = (firstSelection) => { - setUrlQuery({ - ...(firstSelection ? { firstSelection } : null) - }) - setSecondSelection(null) - setFirstSelection(firstSelection) - } - useEffect(() => { - setFirstSelection(urlQuery.firstSelection) - }, [urlQuery.firstSelection]) - - const [secondSelection, setSecondSelection] = useState( - urlQuery.secondSelection - ) - const handleSecondSelectionChange = (secondSelection) => { - setUrlQuery({ - ...(urlQuery.firstSelection - ? { firstSelection: urlQuery.firstSelection } - : null), - ...(secondSelection ? { secondSelection } : null) - }) - setSecondSelection(secondSelection) - } - useEffect(() => { - setSecondSelection(urlQuery.secondSelection) - }, [urlQuery.secondSelection]) - - // compute second selection options - const { - isLoading: secondSelectionLoading, - error: secondSelectionError, - options: secondSelectionOptions - } = useGetFilteredOptions({ - filters: firstSelection, - filterResult: firstSelection - }) - - // compute result - const selections = [firstSelection, secondSelection].filter((s) => !!s) - let filters - if (selections.length === 0) { - filters = selections - } else { - filters = selections.join(",") - filters = filters + "," + prefixes - } - const { - data: resultsData, - isLoading: resultsLoading, - error: resultsError - } = useOntologymaps({ filters }) - - return ( -
    -
    - Code Selection - -
    -
    - o.value === firstSelection) ?? null - } - onChange={(option) => handleFirstSelectionChange(option?.value)} - isClearable - placeholder="First: Type & select NCIT or ICD-O code" - /> - {firstSelection && ( - - {secondSelectionOptions && - resultsData?.response.results[0].termGroups?.length > 1 ? ( - o.value === secondSelection - ) ?? null - } - onChange={(option) => - handleSecondSelectionChange(option?.value) - } - isClearable - placeholder="Optional: Limit with second selection" - /> - ) : ( -
    - )} - - {resultsData?.response.results[0].termGroups?.length > 0 ? ( - - ) : ( -
    No groups found.
    - )} -
    -
    - )} -
    -
    - ) -}) diff --git a/src/modules/service-pages/UBERONmapsPage.js b/src/modules/service-pages/UBERONmapsPage.js deleted file mode 100644 index 9c6b7710..00000000 --- a/src/modules/service-pages/UBERONmapsPage.js +++ /dev/null @@ -1,172 +0,0 @@ -import React, { useEffect, useState } from "react" -import { Infodot } from "../../components/Infodot" -import { Layout } from "../../components/Layout" -import { - ontologymapsBaseUrl, - ontologymapsPrefUrl, - SITE_DEFAULTS -} from "../../hooks/api" -import CustomSelect from "../../components/Select" -import { Loader } from "../../components/Loader" -import { withUrlQuery } from "../../hooks/url-query" -import { - CodeGroups, - useOntologymaps, - useGetFilteredOptions -} from "./ontomapsComponents" - -const filterPrecision = "start" -const prefixes = "UBERON,pgx:icdot" -const apiAllMapsURL = `${ontologymapsBaseUrl}filters=${prefixes}` - -export default function UBERONmapsPage() { - return ( - -
    - -

    - The ontologymaps service provides equivalency mapping - between ICD-O and other classification systems, notably NCIt and - UBERON. It makes use of the sample-level mappings developed for the - individual samples in the Progenetix collection. -

    -

    UBERON and ICD-O 3

    -

    - More documentation with focus on the API functionality can be found on - the documentation pages. -

    -

    - The data of all mappings can be retrieved trough this API call:{" "} - - {"{JSON↗}"} - -

    -
    - -
    - ) -} - -const UBERONmapsSelection = withUrlQuery(({ urlQuery, setUrlQuery }) => { - const { options: allOntologiesOptions } = useGetFilteredOptions({ - filters: prefixes, - filterPrecision: filterPrecision - }) - - const [firstSelection, setFirstSelection] = useState(urlQuery.firstSelection) - const handleFirstSelectionChange = (firstSelection) => { - setUrlQuery({ - ...(firstSelection ? { firstSelection } : null) - }) - setSecondSelection(null) - setFirstSelection(firstSelection) - } - useEffect(() => { - setFirstSelection(urlQuery.firstSelection) - }, [urlQuery.firstSelection]) - - const [secondSelection, setSecondSelection] = useState( - urlQuery.secondSelection - ) - const handleSecondSelectionChange = (secondSelection) => { - setUrlQuery({ - ...(urlQuery.firstSelection - ? { firstSelection: urlQuery.firstSelection } - : null), - ...(secondSelection ? { secondSelection } : null) - }) - setSecondSelection(secondSelection) - } - useEffect(() => { - setSecondSelection(urlQuery.secondSelection) - }, [urlQuery.secondSelection]) - - // compute second selection options - const { - isLoading: secondSelectionLoading, - error: secondSelectionError, - options: secondSelectionOptions - } = useGetFilteredOptions({ - filters: firstSelection, - filterResult: firstSelection - }) - - // compute result - const selections = [firstSelection, secondSelection].filter((s) => !!s) - let filters - if (selections.length === 0) { - filters = selections - } else { - filters = selections.join(",") - filters = filters + "," + prefixes - } - const { - data: resultsData, - isLoading: resultsLoading, - error: resultsError - } = useOntologymaps({ filters }) - - return ( -
    -
    - Code Selection - -
    -
    - o.value === firstSelection) ?? null - } - onChange={(option) => handleFirstSelectionChange(option?.value)} - isClearable - placeholder="Type & select UBERON or ICD-O Topography code" - /> - {firstSelection && ( - - {secondSelectionOptions && - resultsData?.response.results[0].termGroups?.length > 1 ? ( - o.value === secondSelection - ) ?? null - } - onChange={(option) => - handleSecondSelectionChange(option?.value) - } - isClearable - placeholder="Optional: Limit with second selection" - /> - ) : ( -
    - )} - - {resultsData?.response.results[0].termGroups?.length > 0 ? ( - - ) : ( -
    No groups found.
    - )} -
    -
    - )} -
    -
    - ) -}) diff --git a/src/modules/service-pages/dataVisualizationPage.js b/src/modules/service-pages/dataVisualizationPage.js deleted file mode 100644 index 58a2632a..00000000 --- a/src/modules/service-pages/dataVisualizationPage.js +++ /dev/null @@ -1,345 +0,0 @@ -import { withUrlQuery } from "../../hooks/url-query" -import { Layout } from "../../components/Layout" -import React, { useRef, useState } from "react" -// import { GeneLabelOptions } from "../../components/formShared/GenespanUtilities" -import { useForm } from "react-hook-form" -// import SelectField from "../../components/formShared/SelectField" -import InputField from "../../components/formShared/InputField" -import cn from "classnames" -import { useDataVisualization, useExtendedSWR } from "../../hooks/api" -import { WithData } from "../../components/Loader" -import { useContainerDimensions } from "../../hooks/containerDimensions" -// import { useAsyncSelect } from "../../hooks/asyncSelect" - -import SVGloader from "../../components/SVGloaders" -import { svgFetcher } from "../../hooks/fetcher" - -const sampleMaxNo = 1000 - -const HANDOVER_IDS = { - histoplot: "pgx:HO.histoplot", - samplesplot: "pgx:HO.samplesplot" -} - -export const getVisualizationLink = (datasetIds, accessId, fileId, skip, limit, count) => - `/service-collection/dataVisualization?datasetIds=${datasetIds}&accessid=${accessId}&fileId=${fileId}&sampleCount=${count}&skip=${skip}&limit=${limit}` - -const DataVisualizationPage = withUrlQuery(({ urlQuery }) => { - const { datasetIds, accessid, fileId, skip, limit, sampleCount } = urlQuery - const componentRef = useRef() - const { width } = useContainerDimensions(componentRef) - return ( - - {!accessid && !fileId ? ( - - ) : ( -
    - {sampleCount > sampleMaxNo && ( -

    - Please limit the visualization to about {sampleMaxNo} samples; otherwise this might time out... -

    - )} - {width > 0 && ( - - )} -
    - )} -
    - ) -}) - -export default DataVisualizationPage - -function NoResults() { - return ( -
    - This page will only show content if called with a specific accessid - or fileId . -
    - Please start over from the Search Samples page or{" "} - upload a file. -
    - ) -} - -// TODO: rewrite to use simple plot endpoint calls instead of the biosamples + handovers construct... -function DataVisualizationPanel({ datasetIds, accessid, fileId, skip, limit, width }) { - const [formValues, setFormValues] = useState({}) - const dataResult = useDataVisualization({ - "datasetIds": datasetIds, - "accessid": accessid, - "fileId": fileId, - "skip": skip, - "limit": limit, - "requestedGranularity": "count", - "includeHandovers": "true", - ...formValues - }) - const onSubmit = (values) => { - setFormValues(values) - dataResult.mutate(null) - } - return ( -
    -
    -
    - -
    -
    - - } - /> -
    - ) -} - -function DataVisualizationForm({ isQuerying, limit, onSubmit }) { - const defaultValues = { - "plotRegionLabels": null, - "plotGeneSymbols": null - } - const { register, handleSubmit, errors } = useForm({ defaultValues }) - return ( -
    -
    -
    - -
    -{/* -
    - -
    - -
    - -
    -*/} -{/* -
    - -
    -*/} -
    -
    -
    - -
    -
    - -
    -{/* -
    -
    -*/} -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    -{/* -*/} - -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    -
    - ) -} - -function ResultPanel({ formValues, response, width, datasetIds }) { - const resultsHandovers = response.response.resultSets[0].resultsHandovers - const handoverById = (givenId) => - resultsHandovers.find(({ handoverType: { id } }) => id === givenId) - - const mapped = [`plot_width=${width}`]; - Object.entries(formValues).forEach(([k, v]) => { - if (v != null && v != "") { - mapped.push(`${k}=${v}`); - } - }); - - const histoplotUrl = handoverById(HANDOVER_IDS.histoplot).url + "&plotPars=" + mapped.join('::') + "&datasetIds=" + datasetIds - const samplesplotUrl = handoverById(HANDOVER_IDS.samplesplot).url + "&plotPars=" + mapped.join('::') + "&datasetIds=" + datasetIds - - return ( - - ) -} - -// const groupByOptions = [ -// { value: "", label: "No Grouping" }, -// { value: "NCIT", label: "NCIT Neoplasm Code" }, -// { value: "icdom", label: "ICD-O Morphology Code" }, -// { value: "icdot", label: "ICD Topography Code" }, -// { value: "UBERON", label: "UBERON Anatomy Concepts" }, -// { value: "TNM", label: "NCIT TNM Finding" }, -// // { value: "NCITgrade", label: "NCIT Disease Grade" }, -// // { value: "NCITstage", label: "NCIT Disease Stage" }, -// // { value: "EFOfus", label: "followup status" }, -// { value: "pubmed", label: "Publication (PubMed ID)" }, -// // { value: "geo:GSE", label: "GEO Series ID" }, -// // { value: "geo:GPL", label: "GEO Platform ID" }, -// { -// value: "cellosaurus", -// label: "Cellosaurus Cell line ID" -// } -// ] - -// function GeneSpanSelector({ control, errors, register }) { -// const { inputValue, onInputChange } = useAsyncSelect() -// const { options, isLoading } = GeneLabelOptions(inputValue) -// return ( -// -// ) -// } diff --git a/src/pages/analysis.js b/src/pages/analysis.js index e3cf27c0..cc7bd0b2 100644 --- a/src/pages/analysis.js +++ b/src/pages/analysis.js @@ -1,2 +1,131 @@ -import Page from "../modules/details-pages/analysisPage" -export default Page +import { + useDataItemDelivery, + NoResultsHelp, + urlRetrieveIds +} from "../hooks/api" +import { BeaconRESTLink, InternalLink } from "../components/helpersShared/linkHelpers" + +import { Loader } from "../components/Loader" +import { withUrlQuery } from "../hooks/url-query" +import { Layout } from "../components/Layout" + +const itemColl = "analyses" +// const exampleId = "pgxcs-kftvlijb" + +const AnalysisDetailsPage = withUrlQuery(({ urlQuery }) => { + const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) + return ( + + {!hasAllParams ? ( + NoResultsHelp(itemColl) + ) : ( + + )} + + ) +}) + +export default AnalysisDetailsPage + +function AnalysisLoader({ csId, datasetIds }) { + const { data, error, isLoading } = useDataItemDelivery( + csId, + itemColl, + datasetIds + ) + return ( + + {data && ( + + )} + + ) +} + +function AnalysisResponse({ response, csId, datasetIds }) { + if (!response.response.resultSets[0].results) { + return NoResultsHelp(itemColl) + } + return +} + +function Analysis({ analysis, csId, datasetIds }) { + return ( + +
    +

    + {csId} +

    + + {analysis.description && ( + <> +
    Description
    +

    {analysis.description}

    + + )} + + {analysis.biosampleId && ( + <> +
    Biosample
    +

    + +

    + + )} + +
    Download
    +
      +
    • Analysis data as{" "} + +
    • +
    • Sample data as{" "} + +
    • +
    • Analysis variants as{" "} + +
    • +
    • Analysis variants as{" "} + +
    • +
    • Analysis variants as{" "} + +
    • +
    + +
    ) + +} diff --git a/src/pages/biosample.js b/src/pages/biosample.js index 6f66b7c2..3d66d0e8 100644 --- a/src/pages/biosample.js +++ b/src/pages/biosample.js @@ -1,2 +1,279 @@ -import Page from "../modules/details-pages/biosamplePage" -export default Page +import React, { useEffect, useState } from "react" +import { + BIOKEYS, + SITE_DEFAULTS, + useDataItemDelivery, + NoResultsHelp, + urlRetrieveIds +} from "../hooks/api" +import { BeaconRESTLink, InternalLink, ReferenceLink } from "../components/helpersShared/linkHelpers" +import { WithData } from "../components/Loader" +import { withUrlQuery } from "../hooks/url-query" +import { AncestryData } from "../components/AncestryData" +import { Layout } from "../components/Layout" +import { ShowJSON } from "../components/RawData" +import { AnalysisHistogram } from "../components/SVGloaders" +import { pluralizeWord } from "../components/helpersShared/labelHelpers" + +const itemColl = "biosamples" +// const exampleId = "pgxbs-kftvir6m" + +const SampleDetailsPage = withUrlQuery(({ urlQuery }) => { + const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) + const iURL = `${SITE_DEFAULTS.API_PATH}beacon/biosamples/${id}/individuals?datasetIds=${datasetIds}&limit=1` + var [individual, setIndividual] = useState([]); + useEffect(() => { + fetch( iURL ) + .then((response) => response.json()) + .then((data) => { + console.log(data.response.resultSets[0].results[0]); + setIndividual(data.response.resultSets[0].results[0]) + }) + .catch((err) => { + console.log(err.message); + }); + }, [setIndividual]); + + return ( + + {!hasAllParams ? ( + NoResultsHelp(itemColl) + ) : ( + + )} + + ) +}) + +export default SampleDetailsPage + +/*============================================================================*/ +/*============================================================================*/ +/*============================================================================*/ + +function BiosampleLoader({ biosId, individual, datasetIds }) { + const apiReply = useDataItemDelivery(biosId, itemColl, datasetIds) + + return ( + ( + + )} + /> + ) +} + +/*============================================================================*/ + +function BiosampleResponse({ biosId, response, individual, datasetIds }) { + if (!response.response.resultSets[0].results) { + return NoResultsHelp(itemColl) + } + return +} + +/*============================================================================*/ + +function Biosample({ biosId, biosample, individual, datasetIds }) { + + // console.log(individual); + + return ( + +
    + +

    + Sample Details for {biosId} +

    + + {biosample.notes && ( + <> +
    Description
    +

    {biosample.notes}

    + + )} + +
    Diagnostic Classifications
    +
      + {BIOKEYS.map(bioc => ( +
    • + {biosample[bioc].label}{": "} + +
    • + ))} +
    + + {/*------------------------------------------------------------------------*/} + +
    Donor Details
    + +
      + + {individual?.description && ( +
    • + Description{": "} + {individual.description} +
    • + )} + + {individual?.indexDisease?.diseaseCode && ( +
    • + Diagnosis{": "} + {individual.indexDisease.diseaseCode.id}{" ("} + {individual.indexDisease.diseaseCode?.label}{")"} +
    • + + )} + + {individual?.description && ( +
    • + Description{": "} + {individual.description} +
    • + )} + + {individual?.sex && ( +
    • + Genotypic Sex{": "} + {individual?.sex?.label} ({individual.sex.id}) +
    • + )} + + {individual?.indexDisease?.onset && ( +
    • + Age at Collection{": "} + {individual.indexDisease.onset.age} +
    • + )} + +
    + + {individual?.genomeAncestry && individual?.genomeAncestry?.length > 0 && ( + <> +
    Genomic Ancestry
    + + + )} + + {/*------------------------------------------------------------------------*/} + + {biosample?.provenance && ( + <> +
    Provenance
    +
      + {biosample.provenance?.material?.label && ( + <> +
    • Material: {biosample.biosampleStatus.label}
    • + + )} + {biosample.provenance?.geoLocation?.properties?.label && ( + <> +
    • + Origin: {biosample.provenance.geoLocation.properties.label} +
    • + + )} +
    + + )} + + {biosample.externalReferences && ( + <> +
    External References
    +
      + {biosample.externalReferences.map((externalReference, i) => ( +
    • + {externalReference.description && ( + `${externalReference.description}: ` + )} + {externalReference.label && ( + `${externalReference.label}: ` + )} + {ReferenceLink(externalReference) ? ( + + ) : ( + externalReference.id + )} +
    • + ))} +
    + + )} + + { biosample.info && biosample.info?.callsetIds?.length > 0 && ( + <> +
    CNV {pluralizeWord("Plot", biosample.info.callsetIds.length)}
    + {biosample.info?.callsetIds.map((csid, i) => ( + + ))} + + )} + +
    Download
    +
      +
    • Sample data as{" "} + +
    • +
    • Sample data as{" "} + +
    • +
    • Sample variants as{" "} + +
    • +
    • Sample variants as{" "} + +
    • +
    • Sample variants as{" "} + +
    • +
    + + + +
    + ) +} diff --git a/src/pages/biosamples.js b/src/pages/biosamples.js deleted file mode 100644 index fe86d155..00000000 --- a/src/pages/biosamples.js +++ /dev/null @@ -1,12 +0,0 @@ -import Page from "../modules/data-pages/searchPage" -import { getCytoBands } from "../utils/genome" -export default Page - -// This function gets called at build time on server-side. -export const getStaticProps = async () => ({ - props: { - cytoBands: await getCytoBands() - } -}) - -// This page is an alias for search.js since /biosamples has been shared berfore... \ No newline at end of file diff --git a/src/pages/individual.js b/src/pages/individual.js index 63ad84d3..16de36b0 100644 --- a/src/pages/individual.js +++ b/src/pages/individual.js @@ -1,2 +1,184 @@ -import Page from "../modules/details-pages/individualPage" -export default Page +import { + useDataItemDelivery, + NoResultsHelp, + urlRetrieveIds +} from "../hooks/api" +import { ReferenceLink, BeaconRESTLink, InternalLink, ExternalLink } from "../components/helpersShared/linkHelpers" +import { AncestryData } from "../components/AncestryData" +import { WithData } from "../components/Loader" +import { withUrlQuery } from "../hooks/url-query" +import { Layout } from "../components/Layout" +import { ShowJSON } from "../components/RawData" + +const itemColl = "individuals" +// const exampleId = "pgxind-kftx266l" + +const IndividualDetailsPage = withUrlQuery(({ urlQuery }) => { + const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) + return ( + + {!hasAllParams ? ( + NoResultsHelp(itemColl) + ) : ( + + )} + + ) +}) + +export default IndividualDetailsPage + +function IndividualLoader({ id, datasetIds }) { + const apiReply = useDataItemDelivery(id, itemColl, datasetIds) + return ( + ( + + )} + /> + ) +} + +function IndividualResponse({ response, datasetIds }) { + if (!response.response.resultSets[0].results) { + return NoResultsHelp(itemColl) + } + return +} + +function Individual({ individual, datasetIds }) { + return ( +
    +

    + Individual Details {individual.id} +

    + + {individual.description && ( + <> +
    Description
    +

    {individual.description}

    + + )} + + {individual.sex && ( + <> +
    Genotypic Sex
    +
      +
    • {individual.sex?.label} ({individual.sex.id})
    • +
    + + )} + + {individual.onset && +

    + Age at Collection: {individual.onset?.age} +

    + } + + {individual.diseaseCode && + <> +
    Diagnosis
    +

    {individual.diseaseCode?.label}

    + + } + + {individual.cellLines && + <> +
    Cell Lines
    +
      + {individual.cellLines.map((cl, i) => ( +
    • + {cl.description && (cl.description)} + +
    • + ))} +
    + + } + + {individual?.genomeAncestry && individual?.genomeAncestry?.length > 0 && ( + <> +
    Genomic Ancestry
    + + + )} + + {individual.biosamples && individual.biosamples.length > 0 && + <> +
    Biosamples
    + {individual.biosamples.map((bs, i) => ( +
  • + +
  • + ))} + + } + +
    Download
    +
      +
    • Subject data as{" "} + +
    • +
    • Sample data as{" "} + +
    • +
    • Variants as{" "} + +
    • +
    • Variants as{" "} + +
    • +
    • Variants as{" "} + +
    • +
    + + + +
    + ) +} + diff --git a/src/pages/progenetix-cohorts/DIPG.js b/src/pages/progenetix-cohorts/DIPG.js index 18bace5f..f2179e11 100644 --- a/src/pages/progenetix-cohorts/DIPG.js +++ b/src/pages/progenetix-cohorts/DIPG.js @@ -1,11 +1,48 @@ -import Page from "../../modules/data-pages/DIPG_dataPage" -import { getCytoBands } from "../../utils/genome" -export default Page +import React from "react" +import { Layout } from "../../components/Layout" +import { SubsetLoader } from "../../components/SubsetLoader" +import Panel from "../../components/Panel" +import { ExternalLink } from "../../components/helpersShared/linkHelpers" -export const getStaticProps = async () => { - return { - props: { - cytoBands: await getCytoBands() - } - } +const datasetIds = "progenetix" +const subsetId = "pgx:cohort-DIPG" + +export default function Page() { + return ( + + + + + + + + + ) } + +function ThisSubset() { + return ( + <> +
    + + This page allows the exploration of genomic variants in aggressive + childhood gliomas, enabled by the data originally collected for{" "} + . +
    + + ) +} diff --git a/src/pages/progenetix-cohorts/TCGA.js b/src/pages/progenetix-cohorts/TCGA.js index 8e1f50aa..fe9a403b 100644 --- a/src/pages/progenetix-cohorts/TCGA.js +++ b/src/pages/progenetix-cohorts/TCGA.js @@ -1,11 +1,50 @@ -import Page from "../../modules/data-pages/TCGAcancers_dataPage" -import { getCytoBands } from "../../utils/genome" -export default Page +import React from "react" +import { Layout } from "../../components/Layout" +import { SubsetLoader } from "../../components/SubsetLoader" +import Panel from "../../components/Panel" +import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" -export const getStaticProps = async () => { - return { - props: { - cytoBands: await getCytoBands() - } - } +const datasetIds = "progenetix" +const subsetId = "pgx:cohort-TCGAcancers" + +export default function Page() { + return ( + + + + + + + + + + + + ) } + +function ThisSubset() { + return ( + <> +
    + This page represents the TCGA subset of the Progenetix + collection, based on 22142 samples (tumor and reeferences) from The + Cancer Genome Atlas project. The results are based upon data generated + by the TCGA Research Network. Disease-specific subsets of TCGA data (aka. projects) can be + accessed below. + +
    + + ) +} diff --git a/src/pages/progenetix-cohorts/arraymap.js b/src/pages/progenetix-cohorts/arraymap.js index 54196198..735d2138 100644 --- a/src/pages/progenetix-cohorts/arraymap.js +++ b/src/pages/progenetix-cohorts/arraymap.js @@ -1,11 +1,43 @@ -import Page from "../../modules/data-pages/arraymap_dataPage" -import { getCytoBands } from "../../utils/genome" -export default Page +import React from "react" +import { Layout } from "../../components/Layout" +import { SubsetLoader } from "../../components/SubsetLoader" +import Panel from "../../components/Panel" -export const getStaticProps = async () => { - return { - props: { - cytoBands: await getCytoBands() - } - } +const datasetIds = "progenetix" +const subsetId = "pgx:cohort-arraymap" + +export default function Page() { + return ( + + + + + + + + + ) } + +function ThisSubset() { + return ( + <> +
    + The arrayMap data represents a subset of the Progenetix collection for + which the probe-specific array has been used for data generation. For + these samples, individual array probe plots will be accessible through + the sample details pages. + +
    + + ) +} diff --git a/src/pages/publication.js b/src/pages/publication.js index 8425a208..9b3d101f 100644 --- a/src/pages/publication.js +++ b/src/pages/publication.js @@ -1,2 +1,147 @@ -import Page from "../modules/details-pages/publicationPage" -export default Page +import React from "react" +import { usePublication } from "../hooks/api" +import { epmcUrl, EpmcLink, ExternalLink } from "../components/helpersShared/linkHelpers" +import { WithData } from "../components/Loader" +import { withUrlQuery } from "../hooks/url-query" +import { SubsetHistogram } from "../components/SVGloaders" +import { Layout } from "../components/Layout" + +const PublicationDetailsPage = withUrlQuery(({ urlQuery }) => { + const { id } = urlQuery + return ( + + {!id ? : } + + ) +}) +export default PublicationDetailsPage + +function NoResults() { + return ( +
    + This page will only show content if called with a specific Pubmed ID which + already exists in the Progenetix `publications` database, e.g.{" "} + + /publication/?id=PMID:9405679 + + . Please start over from the Progenetix Publication Collection page. +
    + ) +} + +function PublicationLoader({ id }) { + const publicationReply = usePublication(id) + return ( + ( + + )} + /> + ) +} + +function PublicationResponse({ results, id }) { + if (results?.length >= 1) { + return results.map((publication, i) => ( + + )) + } else { + return + } +} + +function PublicationDetails({ publication, id }) { + const progenetixBiosamplesCount = publication.counts?.progenetix ?? 0 + const arraymapBiosamplesCount = publication.counts?.arraymap ?? 0 + return ( +
    +

    + +

    +

    {publication.title}

    +

    {publication.authors}

    +

    + {publication.journal} {id} +

    +

    {publication.abstract}

    + +
    Contact
    +
      + {publication.contact?.name != "" && ( +
    • {publication.contact.name}
    • + )} + {publication.contact?.affiliation != "" && ( +
    • {publication.contact.affiliation}
    • + )} + {publication.contact?.email != "" && ( +
    • {publication.contact.email}
    • + )} +
    + +
    Origin
    +

    {publication.provenance.geoLocation.properties?.city}, {publication.provenance.geoLocation.properties?.country}

    + + {publication.progenetixCurator && ( +
    +
    Progenetix Curator
    +

    {publication.progenetixCurator}

    +
    + )} + +
    Genome Screens
    +
      + {technologies.map((technologie, i) => + publication.counts[technologie] ? ( +
    • + {technologie}: {publication.counts[technologie]} +
    • + ) : null + )} + {progenetixBiosamplesCount > 0 && ( +
    • + {progenetixBiosamplesCount} sample profiles are registered in + Progenetix +
    • + )} + {arraymapBiosamplesCount > 0 && ( +
    • + {arraymapBiosamplesCount} sample profiles are registered in arrayMap +
    • + )} +
    + {(progenetixBiosamplesCount > 0 || arraymapBiosamplesCount > 0) && ( + + Retrieve Publication Samples + + )} + + {progenetixBiosamplesCount > 0 && ( +
    + +
    + )} +
    + ) +} + +function sampleSearchHref({ id, progenetixSamplesCount }) { + const datasetsIds = [] + if (progenetixSamplesCount > 0) datasetsIds.push("progenetix") + + return `/biosamples/?allTermsFilters=${id}&datasetIds=${datasetsIds.join( + "," + )}&executeSearch=true` +} + +const technologies = ["ccgh", "acgh", "wes", "wgs"] diff --git a/src/pages/publications.js b/src/pages/publications.js index 2cdefbd9..7ab62b21 100644 --- a/src/pages/publications.js +++ b/src/pages/publications.js @@ -1,2 +1,168 @@ -import Page from "../modules/publications/PublicationsListPage" -export default Page +import React, { useState } from "react" +// import React, { useEffect, useState } from "react" +import { Layout } from "../components/Layout" +import { Infodot } from "../components/Infodot" +import { ExternalLink, InternalLink } from "../components/helpersShared/linkHelpers" +import { PublicationTable } from "../components/publicationComps/PublicationTables" +import { usePublicationList } from "../hooks/api" +import { WithData } from "../components/Loader" +// import { useAsyncSelect } from "../hooks/asyncSelect" +// import CustomSelect from "../components/Select" +// import dynamic from "next/dynamic" +// import { sumBy } from "lodash" +import { matchSorter } from "match-sorter" +import useDebounce from "../hooks/debounce" + +export default function PublicationsListPage() { + // const [geoCity, setGeoCity] = useState(null) + // const [geodistanceKm, setGeodistanceKm] = useState(100) + const [searchInput, setSearchInput] = useState(null) + const debouncedSearchInput = useDebounce(searchInput, 500) + return ( + +
    +

    + The current page lists articles describing whole genome screening + (WGS, WES, aCGH, cCGH) experiments in cancer, registered in the + Progenetix publication collection. Please submit information about additional + articles to our{" "} + + {" "}or email us at{" "}contact@progenetix.org.{" "}The + inclusion criteria are described{" "} + . +

    +
    +
    +
    +
    + {" "} + setSearchInput(e.target.value)} + /> +
    +
    +
    + +
    + ) +} + +function FilteredPublication({ publications, textSearch }) { + const filteredPublications = matchSorter(publications, textSearch, { + keys: ["id", "authors", "title", "pubYear", "pubmedid", "provenance.geoLocation.properties.city"], + threshold: matchSorter.rankings.CONTAINS + }) + return ( + <> +
    + +
    + {/**/} + + ) +} + +function PublicationsLoader({ geoCity, geodistanceKm, textSearch }) { + const publicationsResult = usePublicationList({ + geoCity, + geodistanceKm + }) + + return ( + ( + + )} + /> + ) +} + +/* +
    + + +
    +{geoCity && ( +
    + + setGeodistanceKm(e.target.value)} + /> +
    +)} + +function GeoCityPublicationSelector({ setGeoCity }) { + const { inputValue, value, onChange, onInputChange } = useAsyncSelect() + useEffect(() => setGeoCity(value), [setGeoCity, value]) + const { data, isLoading } = useGeoCity({ city: inputValue }) + let options = [] + if (data) { + if (data.response) { + options = data.response.results.map((g) => ({ + value: g.id, + data: g, + label: `${g.geoLocation.properties.city} (${g.geoLocation.properties.country})` + })) + } + } + return ( + + ) +} +*/ + +// function PublicationsMapContainer({ publications }) { +// const acghSum = sumBy(publications, "counts.acgh") +// const ccghSum = sumBy(publications, "counts.ccgh") +// const wesSum = sumBy(publications, "counts.wes") +// const wgsSum = sumBy(publications, "counts.wgs") +// const publicationsCount = publications.length +// return ( +// <> +//
    +// +//
    +//

    +// Geographic distribution (by corresponding author) of the{" "} +// {acghSum} genomic array, {ccghSum} chromosomal CGH and{" "} +// {wesSum + wgsSum} whole genome/exome based cancer genome datasets +// from the {publicationsCount} listed publications. Area sizes +// correspond to the sample numbers reported from a given location. +//

    +// +// ) +// } + +// const PublicationsMap = dynamic(() => import("../components/publicationComps/PublicationsMap"), { +// ssr: false +// }) diff --git a/src/pages/publicationsProgenetixRef.js b/src/pages/publicationsProgenetixRef.js index 70b4461c..3c72f34b 100644 --- a/src/pages/publicationsProgenetixRef.js +++ b/src/pages/publicationsProgenetixRef.js @@ -1,2 +1,124 @@ -import Page from "../modules/publications/PublicationsProgenetixRefListPage" -export default Page +import React, { useState } from "react" +import { Layout } from "../components/Layout" +import { Infodot } from "../components/Infodot" +import { PublicationFewCountTable } from "../components/publicationComps/PublicationTables" +import { ExternalLink } from "../components/helpersShared/linkHelpers" +import { useProgenetixRefPublicationList } from "../hooks/api" +import { WithData } from "../components/Loader" +// import dynamic from "next/dynamic" +import { matchSorter } from "match-sorter" +import useDebounce from "../hooks/debounce" +import Panel from "../components/Panel" + +export default function PublicationsProgenetixRefListPage() { + const [searchInput, setSearchInput] = useState(null) + const debouncedSearchInput = useDebounce(searchInput, 500) + const imgHere = { + float: "right", + width: "400px", + border: "0px", + margin: "-100px -10px 0px 0px" + } + + return ( + + + +
    + + This page lists articles which we found to have made use of, or referred to, the Progenetix resource ecosystem. These articles may not necessarily contain original case profiles themselves. +
    +
    + Please contact us to alert + us about additional articles you are aware of. Also, you can now directly + submit suggestions for matching publications to the{" "} + . +
    + + {/*Some article filtering */} +
    +
    + {" "} + setSearchInput(e.target.value)} + /> +
    +
    +
    + + {/* + The PublicationsLoader creates her own Panel for the article table + and then adds the map below. + */} + + + +
    + ) +} + +function FilteredPublication({ publications, textSearch }) { + const filteredPublications = matchSorter(publications, textSearch, { + keys: ["id", "authors", "title", "pubYear", "pubmedid", "provenance.geoLocation.properties.city"], + threshold: matchSorter.rankings.CONTAINS + }) + return ( + <> + + + + {/**/} + + ) +} + +function PublicationsLoader({ textSearch }) { + const publicationsResult = useProgenetixRefPublicationList({ + // geoCity, + // geodistanceKm + }) + + return ( + ( + + )} + /> + ) +} + +// function PublicationsMapContainer({ publications }) { +// const publicationsCount = publications.length +// return ( +// <> +//
    +// +//
    +//

    +// Geographic distribution (by corresponding author) of the{" "} +// {publicationsCount} listed publications which have been found to +// cite and/or use Progenetix. +//

    +// +// ) +// } + +// const PublicationsMap = dynamic(() => import("../components/publicationComps/PublicationsMap"), { +// ssr: false +// }) + diff --git a/src/pages/search.js b/src/pages/search.js index 4bdc1914..d3c964a6 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -1,4 +1,4 @@ -import Page from "../modules/data-pages/searchPage" +import Page from "../components/SearchPage" import { getCytoBands } from "../utils/genome" export default Page diff --git a/src/pages/service-collection/dataVisualization.js b/src/pages/service-collection/dataVisualization.js index 80f629be..f9ca4e88 100644 --- a/src/pages/service-collection/dataVisualization.js +++ b/src/pages/service-collection/dataVisualization.js @@ -1,2 +1,342 @@ -import Page from "../../modules/service-pages/dataVisualizationPage" -export default Page +import { withUrlQuery } from "../../hooks/url-query" +import { Layout } from "../../components/Layout" +import React, { useRef, useState } from "react" +// import { GeneLabelOptions } from "../../components/formShared/GenespanUtilities" +import { useForm } from "react-hook-form" +// import SelectField from "../../components/formShared/SelectField" +import InputField from "../../components/formShared/InputField" +import cn from "classnames" +import { useDataVisualization, useExtendedSWR } from "../../hooks/api" +import { WithData } from "../../components/Loader" +import { useContainerDimensions } from "../../hooks/containerDimensions" +// import { useAsyncSelect } from "../../hooks/asyncSelect" + +import SVGloader from "../../components/SVGloaders" +import { svgFetcher } from "../../hooks/fetcher" + +const sampleMaxNo = 1000 + +const HANDOVER_IDS = { + histoplot: "pgx:HO.histoplot", + samplesplot: "pgx:HO.samplesplot" +} + +const DataVisualizationPage = withUrlQuery(({ urlQuery }) => { + const { datasetIds, accessid, fileId, skip, limit, sampleCount } = urlQuery + const componentRef = useRef() + const { width } = useContainerDimensions(componentRef) + return ( + + {!accessid && !fileId ? ( + + ) : ( +
    + {sampleCount > sampleMaxNo && ( +

    + Please limit the visualization to about {sampleMaxNo} samples; otherwise this might time out... +

    + )} + {width > 0 && ( + + )} +
    + )} +
    + ) +}) + +export default DataVisualizationPage + +function NoResults() { + return ( +
    + This page will only show content if called with a specific accessid + or fileId . +
    + Please start over from the Search Samples page or{" "} + upload a file. +
    + ) +} + +// TODO: rewrite to use simple plot endpoint calls instead of the biosamples + handovers construct... +function DataVisualizationPanel({ datasetIds, accessid, fileId, skip, limit, width }) { + const [formValues, setFormValues] = useState({}) + const dataResult = useDataVisualization({ + "datasetIds": datasetIds, + "accessid": accessid, + "fileId": fileId, + "skip": skip, + "limit": limit, + "requestedGranularity": "count", + "includeHandovers": "true", + ...formValues + }) + const onSubmit = (values) => { + setFormValues(values) + dataResult.mutate(null) + } + return ( +
    +
    +
    + +
    +
    + + } + /> +
    + ) +} + +function DataVisualizationForm({ isQuerying, limit, onSubmit }) { + const defaultValues = { + "plotRegionLabels": null, + "plotGeneSymbols": null + } + const { register, handleSubmit, errors } = useForm({ defaultValues }) + return ( +
    +
    +
    + +
    +{/* +
    + +
    + +
    + +
    +*/} +{/* +
    + +
    +*/} +
    +
    +
    + +
    +
    + +
    +{/* +
    +
    +*/} +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +{/* +*/} + +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    +
    + ) +} + +function ResultPanel({ formValues, response, width, datasetIds }) { + const resultsHandovers = response.response.resultSets[0].resultsHandovers + const handoverById = (givenId) => + resultsHandovers.find(({ handoverType: { id } }) => id === givenId) + + const mapped = [`plot_width=${width}`]; + Object.entries(formValues).forEach(([k, v]) => { + if (v != null && v != "") { + mapped.push(`${k}=${v}`); + } + }); + + const histoplotUrl = handoverById(HANDOVER_IDS.histoplot).url + "&plotPars=" + mapped.join('::') + "&datasetIds=" + datasetIds + const samplesplotUrl = handoverById(HANDOVER_IDS.samplesplot).url + "&plotPars=" + mapped.join('::') + "&datasetIds=" + datasetIds + + return ( + + ) +} + +// const groupByOptions = [ +// { value: "", label: "No Grouping" }, +// { value: "NCIT", label: "NCIT Neoplasm Code" }, +// { value: "icdom", label: "ICD-O Morphology Code" }, +// { value: "icdot", label: "ICD Topography Code" }, +// { value: "UBERON", label: "UBERON Anatomy Concepts" }, +// { value: "TNM", label: "NCIT TNM Finding" }, +// // { value: "NCITgrade", label: "NCIT Disease Grade" }, +// // { value: "NCITstage", label: "NCIT Disease Stage" }, +// // { value: "EFOfus", label: "followup status" }, +// { value: "pubmed", label: "Publication (PubMed ID)" }, +// // { value: "geo:GSE", label: "GEO Series ID" }, +// // { value: "geo:GPL", label: "GEO Platform ID" }, +// { +// value: "cellosaurus", +// label: "Cellosaurus Cell line ID" +// } +// ] + +// function GeneSpanSelector({ control, errors, register }) { +// const { inputValue, onInputChange } = useAsyncSelect() +// const { options, isLoading } = GeneLabelOptions(inputValue) +// return ( +// +// ) +// } diff --git a/src/pages/service-collection/ontologymaps.js b/src/pages/service-collection/ontologymaps.js index 2ef63d15..ba2f616b 100644 --- a/src/pages/service-collection/ontologymaps.js +++ b/src/pages/service-collection/ontologymaps.js @@ -1,2 +1,185 @@ -import Page from "../../modules/service-pages/OntologymapsPage" -export default Page +import React, { useEffect, useState } from "react" +import { Infodot } from "../../components/Infodot" +import { Layout } from "../../components/Layout" +import { + ontologymapsBaseUrl, + ontologymapsPrefUrl, + SITE_DEFAULTS +} from "../../hooks/api" +import CustomSelect from "../../components/Select" +import { Loader } from "../../components/Loader" +import { withUrlQuery } from "../../hooks/url-query" +import { + CodeGroups, + useOntologymaps, + useGetFilteredOptions +} from "../../components/OntomapsComponents" + +const filterPrecision = "start" +const prefixes = "NCIT,pgx:icdom,pgx:icdot" +const apiAllMapsURL = `${ontologymapsBaseUrl}filters=${prefixes}` + +export default function OntologymapsPage() { + return ( + +
    + +

    + The ontologymaps service provides equivalency mapping + between ICD-O and other classification systems, notably NCIt and + UBERON. It makes use of the sample-level mappings for NCIT and ICD-O 3 + codes developed for the individual samples in the Progenetix + collection. +

    +

    NCIT and ICD-O 3

    +

    + While NCIT treats diseases as{" "} + histologic and{" "} + topographic described entities (e.g.{" "} + NCIT:C7700:{" "} + Ovarian{" "} + adenocarcinoma), these two + components are represented separately in ICD-O, through the{" "} + Morphology and{" "} + Topography coding arms (e.g. here{" "} + 8140/3 +{" "} + C56.9). +

    +

    + More documentation with focus on the API functionality can be found on + the documentation pages. +

    +

    + The data of all mappings can be retrieved trough this API call:{" "} + + {"{JSON↗}"} + +

    +
    + +
    + ) +} + +const NCITmapsSelection = withUrlQuery(({ urlQuery, setUrlQuery }) => { + const { options: allOntologiesOptions } = useGetFilteredOptions({ + filters: prefixes, + filterPrecision: filterPrecision + }) + + const [firstSelection, setFirstSelection] = useState(urlQuery.firstSelection) + const handleFirstSelectionChange = (firstSelection) => { + setUrlQuery({ + ...(firstSelection ? { firstSelection } : null) + }) + setSecondSelection(null) + setFirstSelection(firstSelection) + } + useEffect(() => { + setFirstSelection(urlQuery.firstSelection) + }, [urlQuery.firstSelection]) + + const [secondSelection, setSecondSelection] = useState( + urlQuery.secondSelection + ) + const handleSecondSelectionChange = (secondSelection) => { + setUrlQuery({ + ...(urlQuery.firstSelection + ? { firstSelection: urlQuery.firstSelection } + : null), + ...(secondSelection ? { secondSelection } : null) + }) + setSecondSelection(secondSelection) + } + useEffect(() => { + setSecondSelection(urlQuery.secondSelection) + }, [urlQuery.secondSelection]) + + // compute second selection options + const { + isLoading: secondSelectionLoading, + error: secondSelectionError, + options: secondSelectionOptions + } = useGetFilteredOptions({ + filters: firstSelection, + filterResult: firstSelection + }) + + // compute result + const selections = [firstSelection, secondSelection].filter((s) => !!s) + let filters + if (selections.length === 0) { + filters = selections + } else { + filters = selections.join(",") + filters = filters + "," + prefixes + } + const { + data: resultsData, + isLoading: resultsLoading, + error: resultsError + } = useOntologymaps({ filters }) + + return ( +
    +
    + Code Selection + +
    +
    + o.value === firstSelection) ?? null + } + onChange={(option) => handleFirstSelectionChange(option?.value)} + isClearable + placeholder="First: Type & select NCIT or ICD-O code" + /> + {firstSelection && ( + + {secondSelectionOptions && + resultsData?.response.results[0].termGroups?.length > 1 ? ( + o.value === secondSelection + ) ?? null + } + onChange={(option) => + handleSecondSelectionChange(option?.value) + } + isClearable + placeholder="Optional: Limit with second selection" + /> + ) : ( +
    + )} + + {resultsData?.response.results[0].termGroups?.length > 0 ? ( + + ) : ( +
    No groups found.
    + )} +
    +
    + )} +
    +
    + ) +}) diff --git a/src/pages/service-collection/uberonmaps.js b/src/pages/service-collection/uberonmaps.js index 88223b84..60b6904e 100644 --- a/src/pages/service-collection/uberonmaps.js +++ b/src/pages/service-collection/uberonmaps.js @@ -1,2 +1,172 @@ -import Page from "../../modules/service-pages/UBERONmapsPage" -export default Page +import React, { useEffect, useState } from "react" +import { Infodot } from "../../components/Infodot" +import { Layout } from "../../components/Layout" +import { + ontologymapsBaseUrl, + ontologymapsPrefUrl, + SITE_DEFAULTS +} from "../../hooks/api" +import CustomSelect from "../../components/Select" +import { Loader } from "../../components/Loader" +import { withUrlQuery } from "../../hooks/url-query" +import { + CodeGroups, + useOntologymaps, + useGetFilteredOptions +} from "../../components/OntomapsComponents" + +const filterPrecision = "start" +const prefixes = "UBERON,pgx:icdot" +const apiAllMapsURL = `${ontologymapsBaseUrl}filters=${prefixes}` + +export default function UBERONmapsPage() { + return ( + +
    + +

    + The ontologymaps service provides equivalency mapping + between ICD-O and other classification systems, notably NCIt and + UBERON. It makes use of the sample-level mappings developed for the + individual samples in the Progenetix collection. +

    +

    UBERON and ICD-O 3

    +

    + More documentation with focus on the API functionality can be found on + the documentation pages. +

    +

    + The data of all mappings can be retrieved trough this API call:{" "} + + {"{JSON↗}"} + +

    +
    + +
    + ) +} + +const UBERONmapsSelection = withUrlQuery(({ urlQuery, setUrlQuery }) => { + const { options: allOntologiesOptions } = useGetFilteredOptions({ + filters: prefixes, + filterPrecision: filterPrecision + }) + + const [firstSelection, setFirstSelection] = useState(urlQuery.firstSelection) + const handleFirstSelectionChange = (firstSelection) => { + setUrlQuery({ + ...(firstSelection ? { firstSelection } : null) + }) + setSecondSelection(null) + setFirstSelection(firstSelection) + } + useEffect(() => { + setFirstSelection(urlQuery.firstSelection) + }, [urlQuery.firstSelection]) + + const [secondSelection, setSecondSelection] = useState( + urlQuery.secondSelection + ) + const handleSecondSelectionChange = (secondSelection) => { + setUrlQuery({ + ...(urlQuery.firstSelection + ? { firstSelection: urlQuery.firstSelection } + : null), + ...(secondSelection ? { secondSelection } : null) + }) + setSecondSelection(secondSelection) + } + useEffect(() => { + setSecondSelection(urlQuery.secondSelection) + }, [urlQuery.secondSelection]) + + // compute second selection options + const { + isLoading: secondSelectionLoading, + error: secondSelectionError, + options: secondSelectionOptions + } = useGetFilteredOptions({ + filters: firstSelection, + filterResult: firstSelection + }) + + // compute result + const selections = [firstSelection, secondSelection].filter((s) => !!s) + let filters + if (selections.length === 0) { + filters = selections + } else { + filters = selections.join(",") + filters = filters + "," + prefixes + } + const { + data: resultsData, + isLoading: resultsLoading, + error: resultsError + } = useOntologymaps({ filters }) + + return ( +
    +
    + Code Selection + +
    +
    + o.value === firstSelection) ?? null + } + onChange={(option) => handleFirstSelectionChange(option?.value)} + isClearable + placeholder="Type & select UBERON or ICD-O Topography code" + /> + {firstSelection && ( + + {secondSelectionOptions && + resultsData?.response.results[0].termGroups?.length > 1 ? ( + o.value === secondSelection + ) ?? null + } + onChange={(option) => + handleSecondSelectionChange(option?.value) + } + isClearable + placeholder="Optional: Limit with second selection" + /> + ) : ( +
    + )} + + {resultsData?.response.results[0].termGroups?.length > 0 ? ( + + ) : ( +
    No groups found.
    + )} +
    +
    + )} +
    +
    + ) +}) diff --git a/src/pages/service-collection/uploader.js b/src/pages/service-collection/uploader.js index 94455fb1..6a2b0dad 100644 --- a/src/pages/service-collection/uploader.js +++ b/src/pages/service-collection/uploader.js @@ -1,2 +1,224 @@ -import Page from "../../modules/service-pages/FileLoaderPage" -export default Page +import { SITE_DEFAULTS } from "../../hooks/api" +import { Layout } from "../../components/Layout" +import React, { useState } from "react" +import { useDropzone } from "react-dropzone" +import { uploadFile } from "../../hooks/api" +import Panel from "../../components/Panel" + +export default function FileLoaderPage() { + return ( + + +

    + Here we provide users an option to visualize their own CNV data, using + the standard Progenetix plotting options for histograms and samples. + This functionality is currently limited to single segmens files + without the group labeling options. However, we provide the plotting + libraries as a Perl package through our{" "} + + Github + {" "} + repository. NEW in 2023: We transition to new plotting + methods, provided through the `bycon` package and with demonstration + applications in{" "} + + byconaut + . +

    +
    + +
    + +
    + + +

    + NEW 2021: We now recommend the use of our .pgxseg{" "} + file format for th eupload of CNV segments files. As an extension of + the standard tab-delimited segment file format below, the{" "} + .pgxseg file format allows the addition of e.g. group + label information. The file format is described on our{" "} + + documentation site + + {""}, including link to an example file. +

    +

    + Otherwise, data has to be submitted as tab-delimited .tsv{" "} + segment files. An example file is being provided{" "} + + here + + . +

    +

    + While the header values are not being interpreted (i.e. it doesn not + matter if the column is labeled referenceName or{" "} + chro), the column order has to be respected: +

    +
      +
    1. + biosample_id +
        +
      • please use only word characters, underscores, dashes
      • +
      • + the sample value is used for splitting multi-sample + files into their individual profiles +
      • +
      +
    2. +
    3. + reference_name +
        +
      • the reference chromosome
      • +
      • 1-22, X, Y (23 => X; 24 => Y)
      • +
      +
    4. +
    5. + start +
        +
      • base positions according to the used reference genome
      • +
      +
    6. +
    7. + end +
        +
      • as above
      • +
      +
    8. +
    9. + value +
        +
      • the value of the segment
      • +
      • should be 0-centered log2
      • +
      • + segments not passing the calling thresholds (fallback{" "} + 0.15, -0.15) are being filtered out +
      • +
      • + one can use dummy values (e.g. 1 for gains,{" "} + -1 for losses) +
      • +
      +
    10. +
    11. + variant_type (optional) +
        +
      • the called type of the segment
      • +
      • + one of EFO:0030067 (CN gain) or EFO:0030067 (deletion) +
      • +
      • + this will override a status derived from thresholding the value + in mean +
      • +
      +
    12. +
    +
    +
    + ) +} + +function DataVisualizationUpload() { + const [result, setResult] = useState(null) + return ( +
    + {result ? ( + setResult(null)} /> + ) : ( + + )} +
    + ) +} + +function Dropzone({ setResult }) { + const { getRootProps, getInputProps } = useDropzone({ + accept: [".tsv", ".tab", ".pgxseg"], + onDrop: async (acceptedFiles) => { + const data = new FormData() + data.append("upload_file", acceptedFiles[0], acceptedFiles[0].name) + // data.append("plotType", "histoplot") + const result = await uploadFile(data) + setResult(result) + } + }) + + return ( + <> +
    +
    + +

    Drag and drop some files here, or click to select files.

    +
    +
    + + ) +} + +function Results({ results, onCancelClicked }) { + const fileId = results.fileId + // const visualizationLink = getVisualizationLink("", "", fileId, "", "") + const histoPlotLink = `${SITE_DEFAULTS.API_PATH}services/sampleplots/?datasetIds=upload&fileId=${fileId}` + const samplesPlotLink = `${SITE_DEFAULTS.API_PATH}services/sampleplots/?datasetIds=upload&plotType=samplesplot&fileId=${fileId}` + + console.log("histoPlotLink...", histoPlotLink) + + return ( + <> +
    +
    +

    The file has been successfully uploaded!

    +

    +{/* + Visualization form + +*/} + + CNV Histogram + +

    +

    + + Samples Plot + +

    + or{" "} + +
    +
    + + ) +} diff --git a/src/pages/subset.js b/src/pages/subset.js index eff089d6..c3c86c4a 100644 --- a/src/pages/subset.js +++ b/src/pages/subset.js @@ -1,2 +1,23 @@ -import Page from "../modules/details-pages/subsetPage" -export default Page +import { + NoResultsHelp, + urlRetrieveIds +} from "../hooks/api" +import { SubsetLoader } from "../components/SubsetLoader" +import { Layout } from "../components/Layout" +import { withUrlQuery } from "../hooks/url-query" + +const SubsetDetailsPage = withUrlQuery(({ urlQuery }) => { + const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) + return ( + + {!hasAllParams ? ( + NoResultsHelp("subset details") + ) : ( + + )} + + ) +}) + +export default SubsetDetailsPage + diff --git a/src/pages/subsets/NCIT-subsets.js b/src/pages/subsets/NCIT-subsets.js index d6e573a6..954d7c45 100644 --- a/src/pages/subsets/NCIT-subsets.js +++ b/src/pages/subsets/NCIT-subsets.js @@ -1,2 +1,25 @@ -import Page from "../../modules/data-pages/NCIT_SubsetsPage" -export default Page +import React from "react" +import { Layout } from "../../components/Layout" +import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" + +export default function Page() { + return ( + +
    +

    + The cancer samples in Progenetix are mapped to several classification + systems. For each of the classes, aggregated date is available by + clicking the code. Additionally, a selection of the corresponding + samples can be initiated by clicking the sample number or selecting + one or more classes through the checkboxes. +

    +

    + Sample selection follows a hierarchical system in which samples + matching the child terms of a selected class are included in the + response. +

    +
    + +
    + ) +} diff --git a/src/pages/subsets/NCITclinical-subsets.js b/src/pages/subsets/NCITclinical-subsets.js index 5830ed1b..f575d82a 100644 --- a/src/pages/subsets/NCITclinical-subsets.js +++ b/src/pages/subsets/NCITclinical-subsets.js @@ -1,2 +1,29 @@ -import Page from "../../modules/data-pages/NCITclinical_SubsetsPage" -export default Page +import React from "react" +import { Layout } from "../../components/Layout" +import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" + +export default function NCITclinical_SubsetsPage() { + return ( + +
    +

    + Where available cancer samples in Progenetix are mapped to with their + standard clinical and histological parameters such as TNM classification + or histological grade. +

    +

    + For each of the classes, aggregated date is available by + clicking the code. Additionally, a selection of the corresponding + samples can be initiated by clicking the sample number or selecting + one or more classes through the checkboxes. Sample selection follows + a hierarchical system in which samples + matching the child terms of a selected class are included in the + response. +

    +
    + + + +
    + ) +} diff --git a/src/pages/subsets/cbioportal-subsets.js b/src/pages/subsets/cbioportal-subsets.js index 25c36c62..783ee610 100644 --- a/src/pages/subsets/cbioportal-subsets.js +++ b/src/pages/subsets/cbioportal-subsets.js @@ -1,2 +1,20 @@ -import Page from "../../modules/data-pages/cbioportal_SubsetsPage" -export default Page +import React from "react" +import { Layout } from "../../components/Layout" +import Panel from "../../components/Panel" +import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" + +export default function Page() { + return ( + +
    +

    + This page represents samples from different cancer studies derived from cBioPortal. +

    +
    + + + +
    + ) +} + diff --git a/src/pages/subsets/icdom-subsets.js b/src/pages/subsets/icdom-subsets.js index 244813b9..a3ef6241 100644 --- a/src/pages/subsets/icdom-subsets.js +++ b/src/pages/subsets/icdom-subsets.js @@ -1,2 +1,19 @@ -import Page from "../../modules/data-pages/icdom_SubsetsPage" -export default Page +import React from "react" +import { Layout } from "../../components/Layout" +import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" + +export default function Page() { + return ( + +
    +

    + The cancer samples in Progenetix are mapped to several classification + systems. This page represents samples in a shallow hierarchy according to + their ICD-O 3 histology codes (rewritten to an internal prefix system). +

    +
    + +
    + ) +} + diff --git a/src/pages/subsets/icdot-subsets.js b/src/pages/subsets/icdot-subsets.js index 0bdf6d9a..2df83ca2 100644 --- a/src/pages/subsets/icdot-subsets.js +++ b/src/pages/subsets/icdot-subsets.js @@ -1,2 +1,19 @@ -import Page from "../../modules/data-pages/icdot_SubsetsPage" -export default Page +import React from "react" +import { Layout } from "../../components/Layout" +import SubsetsHierarchyLoader from "../../components/SubsetsHierarchyLoader" + +export default function Page() { + return ( + +
    +

    + The cancer samples in Progenetix are mapped to several classification + systems. This page represents samples in a shallow hierarchy according to + their ICD-O 3 topography codes (rewritten to an internal prefix system). +

    +
    + +
    + ) +} + diff --git a/src/pages/variant.js b/src/pages/variant.js index 356c1247..f041a0a6 100644 --- a/src/pages/variant.js +++ b/src/pages/variant.js @@ -1,2 +1,217 @@ -import Page from "../modules/details-pages/variantPage" -export default Page +import { + getDataItemUrl, + useDataItemDelivery, + NoResultsHelp, + urlRetrieveIds +} from "../hooks/api" +import { ExternalLink, ReferenceLink } from "../components/helpersShared/linkHelpers" +import { WithData } from "../components/Loader" +import { withUrlQuery } from "../hooks/url-query" +import { Layout } from "../components/Layout" +import { ShowJSON } from "../components/RawData" +import { BiosamplePlot } from "../components/SVGloaders" +import React from "react" +import { refseq2chro } from "../components/Chromosome" + +const entity = "variants" +// const exampleId = "pgxvar-5bab576a727983b2e00b8d32" + +const VariantDetailsPage = withUrlQuery(({ urlQuery }) => { + const { id, datasetIds, hasAllParams } = urlRetrieveIds(urlQuery) + return ( + + {!hasAllParams ? ( + NoResultsHelp(entity) + ) : ( + + )} + + ) +}) + +export default VariantDetailsPage + +function VariantLoader({ id, datasetIds }) { + const apiReply = useDataItemDelivery(id, entity, datasetIds) + return ( + ( + // <> + + )} + /> + ) +} + +function VariantResponse({ response, id, datasetIds }) { + if (!response.response.resultSets[0].results[0]) { + return NoResultsHelp(entity) + } + return ( + ) +} + +function Variant({ variant, id, datasetIds }) { + var marker = variant.variantInternalId + var mParts = marker.split(':') + const chro = refseq2chro(mParts[0]) + marker = marker + " (" + mParts[1] + ")" + + return ( +
    +

    + {id} ({datasetIds}) +

    + +
    Digest
    +

    {variant.variantInternalId}

    + {variant.variation?.molecularAttributes && ( + <> +
    Molecular Attributes
    +
      + {variant.variation.molecularAttributes.geneIds && ( +
    • Gene: {variant.variation.molecularAttributes.geneIds[0]}
    • + )} + {variant.variation.molecularAttributes?.molecularEffects && ( +
    • Molecular effect: {variant.variation.molecularAttributes.molecularEffects[0].label}
    • + )} + {variant.variation.molecularAttributes.aminoacidChanges && variant.variation.molecularAttributes.aminoacidChanges.length > 0 && variant.variation.molecularAttributes.aminoacidChanges[0] !== null && ( +
    • Aminoacid changes: +
        + {variant.variation.molecularAttributes.aminoacidChanges.map((aa) => ( +
      • + {aa} +
      • + ))} +
      +
    • + )} +
    + + )} + + {variant.variation?.identifiers && ( + <> +
    Variant Identifiers
    +
      + {variant.variation.identifiers?.proteinHGVSIds && ( +
    • Protein HGVSids: +
        + {variant.variation.identifiers.proteinHGVSIds.map((ph) => +
      • + {ph} +
      • + )} +
      +
    • + )} + + {variant.variation.identifiers?.genomicHGVSIds && ( +
    • Genomic HGVSids: +
        + {variant.variation.identifiers.genomicHGVSIds.map((gh) => +
      • + {gh} +
      • + )} +
      +
    • + )} + + {variant.variation.identifiers?.clinvarIds && ( +
    • ClinVar IDs: +
        +
      • + +
      • +
      +
    • + )} + +
    + + )} + + {variant.variation?.variantAlternativeIds && ( +
    +
    Variant Alternative IDs
    +
      + {variant.variation.variantAlternativeIds.map((altid, key) => ( +
    • + {altid.id} - {altid.label} +
    • + ))} +
    +
    + )} + + {variant.variation?.variantLevelData?.clinicalInterpretations && ( + <> + {variant.variation.variantLevelData && variant.variation.variantLevelData.clinicalInterpretations.length > 0 && ( + <> +
    Clinical Interpretations
    +

    Clinical Relevance: {variant.variation.variantLevelData.clinicalInterpretations[0].clinicalRelevance}

    + + + + + + {variant.variation.variantLevelData.clinicalInterpretations?.map((clinicalInterpretations, key) => { + return ( + + + + + ) + })} +
    IDDescription
    + {ReferenceLink(clinicalInterpretations.effect) ? ( + + ) : ( + clinicalInterpretations.effect.id + )} + {clinicalInterpretations.effect.label}
    + + )} + + )} + +
    + Download Data as Beacon v2{" "} + + {"{JSON↗}"} + +
    + + + + {variant.caseLevelData[0]?.biosampleId && marker && chro && ( + <> +
    Plot
    + + + )} + +
    + ) +} diff --git a/src/styles/components/Chromosome.scss b/src/styles/components/Chromosome.scss index 67493ba0..54868563 100644 --- a/src/styles/components/Chromosome.scss +++ b/src/styles/components/Chromosome.scss @@ -5,22 +5,28 @@ } .stain--gpos100 { - fill: hsl(var(--hue), var(--sat), 15%); + fill: linear-gradient(to bottom, rgb(39,39,39), rgb(0,0,0) 70%, rgb(39,39,39)); +/* fill: hsl(var(--hue), var(--sat), 15%);*/ } .stain--gpos75 { - fill: hsl(var(--hue), var(--sat), 30%); +/* fill: hsl(var(--hue), var(--sat), 30%);*/ + fill: linear-gradient(to bottom, rgb(255,87,87), rgb(39,39,39) 70%, rgb(87,87,87)); } .stain--gpos66 { - fill: hsl(var(--hue), var(--sat), 40%); + fill: linear-gradient(to bottom, rgb(87,87,87), rgb(39,39,39) 70%, rgb(87,87,87)); +/* fill: hsl(var(--hue), var(--sat), 40%);*/ } .stain--gpos50 { - fill: hsl(var(--hue), var(--sat), 45%); +/* fill: hsl(var(--hue), var(--sat), 45%);*/ + fill: linear-gradient(to bottom, rgb(196,196,196), rgb(111,111,111) 70%, rgb(196,196,196)); } .stain--gpos33 { - fill: hsl(var(--hue), var(--sat), 50%); +/* fill: hsl(var(--hue), var(--sat), 50%);*/ + fill: linear-gradient(to bottom, rgb(201,201,201), rgb(125,125,125) 70%, rgb(201,201,201)); } .stain--gpos25 { - fill: hsl(var(--hue), var(--sat), 38%); +/* fill: hsl(var(--hue), var(--sat), 38%);*/ + fill: linear-gradient(to bottom, rgb(223,223,223), rgb(196,196,196) 70%, rgb(223,223,223)); } .stain--gvar { fill: hsl(var(--hue), var(--sat), 90%); @@ -36,10 +42,10 @@ } svg .selection { - fill: #ff9899; +/* fill: #ff9899; fill-opacity: 0.2; stroke: #ff9899; -} +*/} svg .selectionEnd { fill: #3298dc; fill-opacity: 0.2;