gramene-search 2.26.0 → 2.28.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 +115 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -11485,6 +11485,110 @@ 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
|
+
|
|
11552
|
+
/**
|
|
11553
|
+
* Reference sequence for the primer designer's CAPS annotation.
|
|
11554
|
+
*
|
|
11555
|
+
* A variant listing from `/primers` carries coordinates and alleles but no
|
|
11556
|
+
* bases, and restriction sites cannot be found without them, so the designer
|
|
11557
|
+
* takes sequence from its host. Ensembl REST's `sequence/region` returns the
|
|
11558
|
+
* plus strand of a window as `{molecule, seq, id, query}`.
|
|
11559
|
+
*
|
|
11560
|
+
* Read from `config.ensemblRest`, which must be the same Ensembl release the
|
|
11561
|
+
* primers API reads variants from (release 115 for sorghum_v11). This matters
|
|
11562
|
+
* more here than it does for the gene track: a gene model from the wrong
|
|
11563
|
+
* release is visibly out of place, whereas sequence from the wrong release
|
|
11564
|
+
* produces a confident and wrong enzyme call. The designer checks every window
|
|
11565
|
+
* against the reference alleles the API reports and shows nothing if they
|
|
11566
|
+
* disagree, but the right release is still the actual fix.
|
|
11567
|
+
*/ /**
|
|
11568
|
+
* Beyond this the annotation is not worth the transfer; the variant listing is
|
|
11569
|
+
* already capped well below it, so this only guards against a stray query.
|
|
11570
|
+
*/ const $f49aa8a0cf25aef4$var$MAX_SPAN = 200000;
|
|
11571
|
+
function $f49aa8a0cf25aef4$export$30e3f6c97d3f3a29(ensemblRest) {
|
|
11572
|
+
if (!ensemblRest) return undefined;
|
|
11573
|
+
return async ({ system_name: system_name, region: region, start: start, end: end }, options)=>{
|
|
11574
|
+
if (!system_name || !region || start < 1 || end < start || end - start + 1 > $f49aa8a0cf25aef4$var$MAX_SPAN) return null;
|
|
11575
|
+
const signal = options && options.signal;
|
|
11576
|
+
const url = `${ensemblRest}/sequence/region/${encodeURIComponent(system_name)}/${encodeURIComponent(region)}:${start}-${end}` + `?content-type=application/json`;
|
|
11577
|
+
const res = await fetch(url, {
|
|
11578
|
+
headers: {
|
|
11579
|
+
Accept: 'application/json'
|
|
11580
|
+
},
|
|
11581
|
+
signal: signal
|
|
11582
|
+
});
|
|
11583
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
11584
|
+
const body = await res.json();
|
|
11585
|
+
// A short or absent read would be indexed with genomic offsets and give
|
|
11586
|
+
// wrong answers quietly; the designer discards it, and so does this.
|
|
11587
|
+
return body && typeof body.seq === 'string' ? body.seq.toUpperCase() : null;
|
|
11588
|
+
};
|
|
11589
|
+
}
|
|
11590
|
+
|
|
11591
|
+
|
|
11488
11592
|
// Primers detail: PCR/qPCR primer design, genome specificity and pan-genome
|
|
11489
11593
|
// coverage checks (gramene-primers <PrimerDesigner>, backed by the
|
|
11490
11594
|
// gramene-swagger /primers endpoints).
|
|
@@ -11519,6 +11623,15 @@ const $88d24ae9beb83d5d$var$Primers = (props)=>{
|
|
|
11519
11623
|
const conf = props.config.details.primers // true | { apiBase?, pangenome?, genotyping? }
|
|
11520
11624
|
;
|
|
11521
11625
|
const apiBase = conf && typeof conf === 'object' && conf.apiBase || props.grameneAPI;
|
|
11626
|
+
// Gene models for the variant browser come from Ensembl REST, which must be
|
|
11627
|
+
// the same release the primers API reads variants from.
|
|
11628
|
+
const ensemblRest = props.config && props.config.ensemblRest;
|
|
11629
|
+
const genesInRegion = (0, $gXNCa$react.useMemo)(()=>(0, $31284fcdc45a1688$export$3a249e9030170bda)(ensemblRest), [
|
|
11630
|
+
ensemblRest
|
|
11631
|
+
]);
|
|
11632
|
+
const sequenceForRegion = (0, $gXNCa$react.useMemo)(()=>(0, $f49aa8a0cf25aef4$export$30e3f6c97d3f3a29)(ensemblRest), [
|
|
11633
|
+
ensemblRest
|
|
11634
|
+
]);
|
|
11522
11635
|
const byGene = props.uiViewState && props.uiViewState.byGene && props.uiViewState.byGene[geneId];
|
|
11523
11636
|
const saved = byGene && byGene.primers;
|
|
11524
11637
|
const { doSetPrimersState: doSetPrimersState } = props;
|
|
@@ -11539,6 +11652,8 @@ const $88d24ae9beb83d5d$var$Primers = (props)=>{
|
|
|
11539
11652
|
gene: gene,
|
|
11540
11653
|
systemName: gene.system_name,
|
|
11541
11654
|
modes: $88d24ae9beb83d5d$var$MODES,
|
|
11655
|
+
genesInRegion: genesInRegion,
|
|
11656
|
+
sequenceForRegion: sequenceForRegion,
|
|
11542
11657
|
defaultMode: "gene",
|
|
11543
11658
|
// an empty slice (never visited, or a snapshot without primers) leaves
|
|
11544
11659
|
// the designer uncontrolled until its first change is stored
|