dsh-molbio-panel 0.1.9 → 0.1.10
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/README.md +2 -2
- package/index.mjs +1 -1
- package/lib/client.js +49 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,12 +12,12 @@ DSH Web GUI 的**浏览器内 Molbio 面板**:右侧栏的一个 tab,列出
|
|
|
12
12
|
面板必须走 **bundle 渠道**(`dsh.client` 双面包):preset 渠道挂不了客户端 UI
|
|
13
13
|
(详见 `dsh-molbio-tools` 仓库的 `docs/client-pipeline-exploration.md`)。
|
|
14
14
|
|
|
15
|
-
而 `dsh-molbio-tools` 的宿主半边会注册 **
|
|
15
|
+
而 `dsh-molbio-tools` 的宿主半边会注册 **64 个工具**——把它挂进一个共享的 Web profile,
|
|
16
16
|
等于给**该 profile 的每个会话**都塞进这些工具。所以面板单独成包:
|
|
17
17
|
|
|
18
18
|
| 包 | 宿主半边 | 用途 |
|
|
19
19
|
| --- | --- | --- |
|
|
20
|
-
| `dsh-molbio-tools` |
|
|
20
|
+
| `dsh-molbio-tools` | 64 个 molbio 工具 | 分子生物学专用 profile / preset |
|
|
21
21
|
| `dsh-molbio-panel` | **不注册任何工具**(空实现) | 只想在共享 profile 里加一个面板 |
|
|
22
22
|
|
|
23
23
|
宿主半边刻意保持空:客户端扫描按 **Loader 条目**取包清单,条目只要能加载,浏览器半就能
|
package/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* dsh-molbio-panel — host half.
|
|
3
3
|
*
|
|
4
4
|
* This package exists so the browser panel can be installed WITHOUT dragging
|
|
5
|
-
* the
|
|
5
|
+
* the molbio toolset into every session of a profile. It is a `dsh.client`
|
|
6
6
|
* dual-face package: the host half below, and the browser half built from the
|
|
7
7
|
* `dsh-molbio-tools` sources into `lib/client.js`.
|
|
8
8
|
*
|
package/lib/client.js
CHANGED
|
@@ -4976,10 +4976,23 @@ window.__ModuleLoader__.load({
|
|
|
4976
4976
|
|
|
4977
4977
|
/** Summary statistics over parsed entries. */
|
|
4978
4978
|
function entryStats(entries, qualityMode = false) {
|
|
4979
|
-
|
|
4979
|
+
// Count in a loop instead of spreading into Math.min/Math.max: a large FASTQ
|
|
4980
|
+
// can hold hundreds of thousands of reads (and millions of quality
|
|
4981
|
+
// characters), and spreading such an array overflows the engine's argument
|
|
4982
|
+
// limit with a RangeError. The numbers are identical; only the failure mode
|
|
4983
|
+
// changes.
|
|
4984
|
+
let totalBases = 0;
|
|
4985
|
+
let minLength = entries.length === 0 ? 0 : Infinity;
|
|
4986
|
+
let maxLength = 0;
|
|
4987
|
+
let longest = 0;
|
|
4980
4988
|
let gc = 0;
|
|
4981
4989
|
let at = 0;
|
|
4982
4990
|
for (const entry of entries) {
|
|
4991
|
+
const length = entry.sequence.length;
|
|
4992
|
+
totalBases += length;
|
|
4993
|
+
if (length < minLength) minLength = length;
|
|
4994
|
+
if (length > maxLength) maxLength = length;
|
|
4995
|
+
if (length > longest) longest = length;
|
|
4983
4996
|
for (const base of entry.sequence) {
|
|
4984
4997
|
if (base === 'G' || base === 'C') gc++;
|
|
4985
4998
|
else if (base === 'A' || base === 'T') at++;
|
|
@@ -4987,22 +5000,34 @@ window.__ModuleLoader__.load({
|
|
|
4987
5000
|
}
|
|
4988
5001
|
const stats = {
|
|
4989
5002
|
entries: entries.length,
|
|
4990
|
-
total_bases:
|
|
4991
|
-
min_length:
|
|
4992
|
-
max_length:
|
|
4993
|
-
mean_length:
|
|
5003
|
+
total_bases: totalBases,
|
|
5004
|
+
min_length: minLength,
|
|
5005
|
+
max_length: maxLength,
|
|
5006
|
+
mean_length: entries.length === 0 ? 0 : Math.round((totalBases / entries.length) * 100) / 100,
|
|
4994
5007
|
gc_percent: gc + at === 0 ? 0 : Math.round((gc / (gc + at)) * 1000) / 10,
|
|
4995
5008
|
};
|
|
4996
5009
|
if (qualityMode) {
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5010
|
+
let qualitySum = 0;
|
|
5011
|
+
let qualityCount = 0;
|
|
5012
|
+
let lowCount = 0;
|
|
5013
|
+
let qualityMin = Infinity;
|
|
5014
|
+
let qualityMax = -Infinity;
|
|
5015
|
+
for (const entry of entries) {
|
|
5016
|
+
for (const ch of entry.quality) {
|
|
5017
|
+
const q = ch.charCodeAt(0) - 33;
|
|
5018
|
+
qualitySum += q;
|
|
5019
|
+
qualityCount++;
|
|
5020
|
+
if (q < 20) lowCount++;
|
|
5021
|
+
if (q < qualityMin) qualityMin = q;
|
|
5022
|
+
if (q > qualityMax) qualityMax = q;
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
if (qualityCount > 0) {
|
|
5026
|
+
stats.quality_mean = Math.round((qualitySum / qualityCount) * 100) / 100;
|
|
5027
|
+
stats.quality_min = qualityMin;
|
|
5028
|
+
stats.quality_max = qualityMax;
|
|
5029
|
+
stats.low_quality_fraction = Math.round((lowCount / qualityCount) * 1000) / 1000;
|
|
5030
|
+
const maxLen = Math.min(150, longest);
|
|
5006
5031
|
const perPosition = [];
|
|
5007
5032
|
for (let pos = 0; pos < maxLen; pos++) {
|
|
5008
5033
|
const values = entries.filter((e) => e.sequence.length > pos).map((e) => e.quality.charCodeAt(pos) - 33);
|
|
@@ -7797,14 +7822,22 @@ window.__ModuleLoader__.load({
|
|
|
7797
7822
|
}
|
|
7798
7823
|
if (current !== null) peaks.push(current);
|
|
7799
7824
|
const total = points.reduce((sum, point) => sum + point.hydropathy, 0);
|
|
7825
|
+
// Loop rather than Math.min(...points): the protein length is not capped and
|
|
7826
|
+
// a long input would overflow the argument limit with a RangeError.
|
|
7827
|
+
let minimumHydropathy = Infinity;
|
|
7828
|
+
let maximumHydropathy = -Infinity;
|
|
7829
|
+
for (const point of points) {
|
|
7830
|
+
if (point.hydropathy < minimumHydropathy) minimumHydropathy = point.hydropathy;
|
|
7831
|
+
if (point.hydropathy > maximumHydropathy) maximumHydropathy = point.hydropathy;
|
|
7832
|
+
}
|
|
7800
7833
|
return {
|
|
7801
7834
|
length: sequence.length,
|
|
7802
7835
|
window,
|
|
7803
7836
|
threshold,
|
|
7804
7837
|
gravy: sequence.length === 0 ? 0 : round2([...sequence].reduce((sum, aa) => sum + KYTE_DOOLITTLE[aa], 0) / sequence.length),
|
|
7805
7838
|
mean_profile: round3(total / points.length),
|
|
7806
|
-
minimum_hydropathy: round3(
|
|
7807
|
-
maximum_hydropathy: round3(
|
|
7839
|
+
minimum_hydropathy: round3(minimumHydropathy),
|
|
7840
|
+
maximum_hydropathy: round3(maximumHydropathy),
|
|
7808
7841
|
peaks: peaks.map((peak) => ({ ...peak, maximum: round3(peak.maximum), length: peak.end - peak.start + 1 })),
|
|
7809
7842
|
points,
|
|
7810
7843
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-molbio-panel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Browser panel for the DeepSeek Harness Web GUI: a Molbio tab in the right sidebar that draws plasmid maps and sequence logos from workspace sequence files, using the same computation modules as the dsh-molbio-tools plugin.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.mjs",
|