gramene-search 2.26.0 → 2.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -11485,6 +11485,70 @@ var $527ebc19dc92444d$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.conn
11485
11485
 
11486
11486
 
11487
11487
 
11488
+ /**
11489
+ * Gene models for the primer designer's variant browser.
11490
+ *
11491
+ * `/primers` has no genes-in-region endpoint — it can only fetch a gene by id —
11492
+ * so the designer takes this from its host. Ensembl REST's `overlap/region`
11493
+ * returns genes, transcripts, exons and CDS for a window in one request, all in
11494
+ * genomic coordinates, which is exactly what the browser draws.
11495
+ *
11496
+ * Read from `config.ensemblRest`, which must be the same Ensembl release the
11497
+ * primers API reads variants from (release 115 for sorghum_v11). A different
11498
+ * release would draw gene models that do not line up with the variants beside
11499
+ * them.
11500
+ */ /**
11501
+ * Beyond this the response runs to thousands of features and the models would
11502
+ * be too small to read, so the track is simply left empty.
11503
+ */ const $31284fcdc45a1688$var$MAX_SPAN = 1000000;
11504
+ function $31284fcdc45a1688$export$3a249e9030170bda(ensemblRest) {
11505
+ if (!ensemblRest) return undefined;
11506
+ return async ({ system_name: system_name, region: region, start: start, end: end }, options)=>{
11507
+ if (!system_name || !region || end - start + 1 > $31284fcdc45a1688$var$MAX_SPAN) return [];
11508
+ const signal = options && options.signal;
11509
+ const url = `${ensemblRest}/overlap/region/${encodeURIComponent(system_name)}/${encodeURIComponent(region)}:${start}-${end}` + `?feature=gene;feature=transcript;feature=exon;feature=cds;content-type=application/json`;
11510
+ const res = await fetch(url, {
11511
+ headers: {
11512
+ Accept: 'application/json'
11513
+ },
11514
+ signal: signal
11515
+ });
11516
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
11517
+ const features = await res.json();
11518
+ if (!Array.isArray(features)) return [];
11519
+ const of = (type)=>features.filter((f)=>f && f.feature_type === type);
11520
+ const transcripts = of('transcript');
11521
+ const exons = of('exon');
11522
+ const cds = of('cds');
11523
+ return of('gene').map((gene)=>{
11524
+ // One transcript per gene: the canonical one when Ensembl marks it.
11525
+ const mine = transcripts.filter((t)=>t.Parent === gene.id);
11526
+ const transcript = mine.find((t)=>t.is_canonical) || mine[0];
11527
+ const myExons = transcript ? exons.filter((e)=>e.Parent === transcript.id) : [];
11528
+ const myCds = transcript ? cds.filter((c)=>c.Parent === transcript.id) : [];
11529
+ return {
11530
+ id: gene.id,
11531
+ label: gene.external_name || gene.id,
11532
+ start: gene.start,
11533
+ end: gene.end,
11534
+ strand: gene.strand === -1 ? -1 : 1,
11535
+ // Ensembl returns only the exons overlapping the window, which is all
11536
+ // the browser can show anyway.
11537
+ exons: myExons.map((e)=>({
11538
+ start: e.start,
11539
+ end: e.end
11540
+ })),
11541
+ cds: myCds.length ? {
11542
+ start: Math.min(...myCds.map((c)=>c.start)),
11543
+ end: Math.max(...myCds.map((c)=>c.end))
11544
+ } : null,
11545
+ biotype: gene.biotype
11546
+ };
11547
+ });
11548
+ };
11549
+ }
11550
+
11551
+
11488
11552
  // Primers detail: PCR/qPCR primer design, genome specificity and pan-genome
11489
11553
  // coverage checks (gramene-primers <PrimerDesigner>, backed by the
11490
11554
  // gramene-swagger /primers endpoints).
@@ -11519,6 +11583,12 @@ const $88d24ae9beb83d5d$var$Primers = (props)=>{
11519
11583
  const conf = props.config.details.primers // true | { apiBase?, pangenome?, genotyping? }
11520
11584
  ;
11521
11585
  const apiBase = conf && typeof conf === 'object' && conf.apiBase || props.grameneAPI;
11586
+ // Gene models for the variant browser come from Ensembl REST, which must be
11587
+ // the same release the primers API reads variants from.
11588
+ const ensemblRest = props.config && props.config.ensemblRest;
11589
+ const genesInRegion = (0, $gXNCa$react.useMemo)(()=>(0, $31284fcdc45a1688$export$3a249e9030170bda)(ensemblRest), [
11590
+ ensemblRest
11591
+ ]);
11522
11592
  const byGene = props.uiViewState && props.uiViewState.byGene && props.uiViewState.byGene[geneId];
11523
11593
  const saved = byGene && byGene.primers;
11524
11594
  const { doSetPrimersState: doSetPrimersState } = props;
@@ -11539,6 +11609,7 @@ const $88d24ae9beb83d5d$var$Primers = (props)=>{
11539
11609
  gene: gene,
11540
11610
  systemName: gene.system_name,
11541
11611
  modes: $88d24ae9beb83d5d$var$MODES,
11612
+ genesInRegion: genesInRegion,
11542
11613
  defaultMode: "gene",
11543
11614
  // an empty slice (never visited, or a snapshot without primers) leaves
11544
11615
  // the designer uncontrolled until its first change is stored