jsrc 0.2.1__tar.gz → 0.2.2__tar.gz
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.
- {jsrc-0.2.1/src/jsrc.egg-info → jsrc-0.2.2}/PKG-INFO +22 -10
- {jsrc-0.2.1 → jsrc-0.2.2}/README.md +21 -9
- {jsrc-0.2.1 → jsrc-0.2.2}/pyproject.toml +4 -1
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/cli.py +0 -8
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/grn/__init__.py +2 -1
- jsrc-0.2.2/src/jsrc/grn/build.py +88 -0
- jsrc-0.2.2/src/jsrc/grn/net2json.py +45 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/grn/serve.py +7 -12
- jsrc-0.2.2/src/jsrc/grn/sources/index.html +37 -0
- jsrc-0.2.2/src/jsrc/grn/sources/script.js +521 -0
- jsrc-0.2.1/src/jsrc/grn/viewer.py → jsrc-0.2.2/src/jsrc/grn/sources/style.css +1 -81
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/gs/train.py +1 -1
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/qc.py +0 -1
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/translate.py +11 -0
- {jsrc-0.2.1 → jsrc-0.2.2/src/jsrc.egg-info}/PKG-INFO +22 -10
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc.egg-info/SOURCES.txt +4 -1
- jsrc-0.2.1/src/jsrc/grn/net2json.py +0 -144
- {jsrc-0.2.1 → jsrc-0.2.2}/LICENSE +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/setup.cfg +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/__init__.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/analyze/__init__.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/analyze/bootstrap_phylo.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/analyze/core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/analyze/motif.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/analyze/msa_consensus.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/analyze/phylo.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/analyze/qc.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/analyze/snpindel.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/grn/anno2json.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/grn/centrality.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/grn/core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/gs/__init__.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/gs/build.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/gs/split.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/job/__init__.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/job/core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/job/gc.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/job/history.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/job/kill.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/job/logs.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/job/ls.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/job/show.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/job/submit.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/__init__.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/chromosome.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/circoslite.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/cis.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/domain.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/dotplot.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/exon.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/gene.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/heart.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/plot/rose.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/__init__.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/codon.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/digest.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/extract.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/fetch.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/kmer.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/promoter.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/rename.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/seq/window.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/vision/__init__.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/vision/core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/vision/efd.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/vision/extract.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc/vision/traits.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc.egg-info/dependency_links.txt +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc.egg-info/entry_points.txt +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc.egg-info/requires.txt +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/src/jsrc.egg-info/top_level.txt +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_analyze_extra.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_analyze_phylo.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_cli_error_behavior.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_cli_module_flows.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_grn_conversion.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_gs_train.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_job_core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_job_portability.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_plot_commands.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_plot_core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_progress.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_codon_kmer.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_core.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_digest.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_extract.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_fetch.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_promoter.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_qc.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_rename.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_translate.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_seq_window.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_vision_efd.py +0 -0
- {jsrc-0.2.1 → jsrc-0.2.2}/tests/test_vision_extract.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jsrc
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Python library for bioinformatics and scientific computing
|
|
5
5
|
Author-email: Jiaoyuan <imjiaoyuan@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -38,27 +38,36 @@ Python library for bioinformatics and scientific computing.
|
|
|
38
38
|
|
|
39
39
|
## Installation
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
Recommended (global CLI via `uv tool`):
|
|
42
42
|
```bash
|
|
43
|
-
|
|
43
|
+
uv tool install jsrc
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
uv:
|
|
46
|
+
Using `uv` virtual environment:
|
|
47
47
|
```bash
|
|
48
|
+
uv venv
|
|
49
|
+
source .venv/bin/activate
|
|
48
50
|
uv pip install jsrc
|
|
49
51
|
```
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
Using Conda virtual environment + pip:
|
|
54
|
+
```bash
|
|
55
|
+
conda create -n jsrc python=3.11 -y
|
|
56
|
+
conda activate jsrc
|
|
57
|
+
pip install jsrc
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
From source (development):
|
|
52
61
|
```bash
|
|
53
62
|
git clone https://github.com/imjiaoyuan/jsrc.git
|
|
54
63
|
cd jsrc
|
|
55
64
|
uv venv
|
|
56
|
-
uv sync --extra dev
|
|
65
|
+
uv sync --extra dev --extra all
|
|
57
66
|
```
|
|
58
67
|
|
|
59
68
|
Run `jsrc --help` to get started.
|
|
60
69
|
|
|
61
|
-
For detailed usage, see the [Documentation](docs/en/index.md)
|
|
70
|
+
For detailed usage, see the [Documentation](docs/en/index.md). 中文文档请参阅 [文档](docs/zh/index.md)。
|
|
62
71
|
|
|
63
72
|
## Quick Start
|
|
64
73
|
|
|
@@ -84,7 +93,7 @@ jsrc vision extract --help
|
|
|
84
93
|
| `plot` | Gene/exon/chromosome/domain and other plots | `jsrc plot gene ...` |
|
|
85
94
|
| `analyze` | Phylogeny, motif, consensus, SNP/INDEL, QC | `jsrc analyze phylo ...` |
|
|
86
95
|
| `gs` | Genomic selection dataset build/split/train | `jsrc gs train ...` |
|
|
87
|
-
| `grn` | GRN conversion, centrality, local
|
|
96
|
+
| `grn` | GRN conversion, centrality, build packaging, local serve | `jsrc grn build ...` |
|
|
88
97
|
| `vision` | Object extraction, morphology traits, EFD | `jsrc vision extract ...` |
|
|
89
98
|
| `job` | Background job submit/list/log/kill/history | `jsrc job submit "cmd"` |
|
|
90
99
|
|
|
@@ -136,10 +145,13 @@ jsrc vision traits -i test/leaf1.jpg --channel a --invert
|
|
|
136
145
|
|
|
137
146
|
**grn module**
|
|
138
147
|
|
|
139
|
-
Generate 1000-gene random network viewer
|
|
148
|
+
Generate and launch a 1000-gene random network viewer:
|
|
140
149
|
|
|
141
150
|
```bash
|
|
142
|
-
jsrc grn net2json -i test/grn/network.tsv -o test/grn/
|
|
151
|
+
jsrc grn net2json -i test/grn/network.tsv -o test/grn/grn.json
|
|
152
|
+
jsrc grn anno2json -i test/grn/annotation.tsv -o test/grn/annotation.json
|
|
153
|
+
jsrc grn build -d test/grn/public -g test/grn/grn.json -n test/grn/annotation.json -z test/grn/grn-viewer.zip -a -t 200
|
|
154
|
+
jsrc grn serve -d test/grn/public -g test/grn/public/json/grn.json -n test/grn/public/json/annotation.json -p 8000 -a -t 200
|
|
143
155
|
```
|
|
144
156
|
|
|
145
157
|

|
|
@@ -4,27 +4,36 @@ Python library for bioinformatics and scientific computing.
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Recommended (global CLI via `uv tool`):
|
|
8
8
|
```bash
|
|
9
|
-
|
|
9
|
+
uv tool install jsrc
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
uv:
|
|
12
|
+
Using `uv` virtual environment:
|
|
13
13
|
```bash
|
|
14
|
+
uv venv
|
|
15
|
+
source .venv/bin/activate
|
|
14
16
|
uv pip install jsrc
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
Using Conda virtual environment + pip:
|
|
20
|
+
```bash
|
|
21
|
+
conda create -n jsrc python=3.11 -y
|
|
22
|
+
conda activate jsrc
|
|
23
|
+
pip install jsrc
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
From source (development):
|
|
18
27
|
```bash
|
|
19
28
|
git clone https://github.com/imjiaoyuan/jsrc.git
|
|
20
29
|
cd jsrc
|
|
21
30
|
uv venv
|
|
22
|
-
uv sync --extra dev
|
|
31
|
+
uv sync --extra dev --extra all
|
|
23
32
|
```
|
|
24
33
|
|
|
25
34
|
Run `jsrc --help` to get started.
|
|
26
35
|
|
|
27
|
-
For detailed usage, see the [Documentation](docs/en/index.md)
|
|
36
|
+
For detailed usage, see the [Documentation](docs/en/index.md). 中文文档请参阅 [文档](docs/zh/index.md)。
|
|
28
37
|
|
|
29
38
|
## Quick Start
|
|
30
39
|
|
|
@@ -50,7 +59,7 @@ jsrc vision extract --help
|
|
|
50
59
|
| `plot` | Gene/exon/chromosome/domain and other plots | `jsrc plot gene ...` |
|
|
51
60
|
| `analyze` | Phylogeny, motif, consensus, SNP/INDEL, QC | `jsrc analyze phylo ...` |
|
|
52
61
|
| `gs` | Genomic selection dataset build/split/train | `jsrc gs train ...` |
|
|
53
|
-
| `grn` | GRN conversion, centrality, local
|
|
62
|
+
| `grn` | GRN conversion, centrality, build packaging, local serve | `jsrc grn build ...` |
|
|
54
63
|
| `vision` | Object extraction, morphology traits, EFD | `jsrc vision extract ...` |
|
|
55
64
|
| `job` | Background job submit/list/log/kill/history | `jsrc job submit "cmd"` |
|
|
56
65
|
|
|
@@ -102,10 +111,13 @@ jsrc vision traits -i test/leaf1.jpg --channel a --invert
|
|
|
102
111
|
|
|
103
112
|
**grn module**
|
|
104
113
|
|
|
105
|
-
Generate 1000-gene random network viewer
|
|
114
|
+
Generate and launch a 1000-gene random network viewer:
|
|
106
115
|
|
|
107
116
|
```bash
|
|
108
|
-
jsrc grn net2json -i test/grn/network.tsv -o test/grn/
|
|
117
|
+
jsrc grn net2json -i test/grn/network.tsv -o test/grn/grn.json
|
|
118
|
+
jsrc grn anno2json -i test/grn/annotation.tsv -o test/grn/annotation.json
|
|
119
|
+
jsrc grn build -d test/grn/public -g test/grn/grn.json -n test/grn/annotation.json -z test/grn/grn-viewer.zip -a -t 200
|
|
120
|
+
jsrc grn serve -d test/grn/public -g test/grn/public/json/grn.json -n test/grn/public/json/annotation.json -p 8000 -a -t 200
|
|
109
121
|
```
|
|
110
122
|
|
|
111
123
|

|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "jsrc"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
description = "Python library for bioinformatics and scientific computing"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -39,5 +39,8 @@ build-backend = "setuptools.build_meta"
|
|
|
39
39
|
where = ["src"]
|
|
40
40
|
include = ["jsrc*"]
|
|
41
41
|
|
|
42
|
+
[tool.setuptools.package-data]
|
|
43
|
+
"jsrc.grn" = ["sources/*"]
|
|
44
|
+
|
|
42
45
|
[tool.black]
|
|
43
46
|
target-version = ["py310"]
|
|
@@ -14,14 +14,6 @@ def setup_logging(verbose: bool = False) -> None:
|
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
def _dispatch(module_name: str, func_name: str = "cmd") -> argparse.Action:
|
|
18
|
-
def _runner(args: argparse.Namespace) -> None:
|
|
19
|
-
module = importlib.import_module(module_name)
|
|
20
|
-
getattr(module, func_name)(args)
|
|
21
|
-
|
|
22
|
-
return _runner
|
|
23
|
-
|
|
24
|
-
|
|
25
17
|
MODULES = {
|
|
26
18
|
"seq": "jsrc.seq",
|
|
27
19
|
"plot": "jsrc.plot",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
|
-
from jsrc.grn import anno2json, centrality, net2json, serve
|
|
3
|
+
from jsrc.grn import anno2json, build, centrality, net2json, serve
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def register_subparser(subparsers: Any) -> None:
|
|
@@ -8,6 +8,7 @@ def register_subparser(subparsers: Any) -> None:
|
|
|
8
8
|
grn_sub = grn_parser.add_subparsers(dest="grn_cmd")
|
|
9
9
|
grn_parser.set_defaults(_group_parser=grn_parser)
|
|
10
10
|
|
|
11
|
+
build.register(grn_sub)
|
|
11
12
|
net2json.register(grn_sub)
|
|
12
13
|
anno2json.register(grn_sub)
|
|
13
14
|
serve.register(grn_sub)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pathlib
|
|
3
|
+
import shutil
|
|
4
|
+
import zipfile
|
|
5
|
+
from argparse import Namespace
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from jsrc.grn.core import ensure_dir, write_text
|
|
10
|
+
|
|
11
|
+
_SCRIPT_TEMPLATE = (pathlib.Path(__file__).parent / "sources" / "script.js").read_text(
|
|
12
|
+
encoding="utf-8"
|
|
13
|
+
)
|
|
14
|
+
_INDEX_HTML = (pathlib.Path(__file__).parent / "sources" / "index.html").read_text(
|
|
15
|
+
encoding="utf-8"
|
|
16
|
+
)
|
|
17
|
+
_STYLE_CSS = (pathlib.Path(__file__).parent / "sources" / "style.css").read_text(
|
|
18
|
+
encoding="utf-8"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _sync_assets(
|
|
23
|
+
base: str,
|
|
24
|
+
view_mode: str,
|
|
25
|
+
threshold: int,
|
|
26
|
+
max_nodes: int,
|
|
27
|
+
) -> None:
|
|
28
|
+
ensure_dir(base)
|
|
29
|
+
ensure_dir(os.path.join(base, "css"))
|
|
30
|
+
ensure_dir(os.path.join(base, "js"))
|
|
31
|
+
ensure_dir(os.path.join(base, "json"))
|
|
32
|
+
write_text(os.path.join(base, "index.html"), _INDEX_HTML)
|
|
33
|
+
write_text(os.path.join(base, "css/style.css"), _STYLE_CSS)
|
|
34
|
+
script = (
|
|
35
|
+
_SCRIPT_TEMPLATE.replace("__JSRC_VIEW_MODE__", view_mode)
|
|
36
|
+
.replace("__JSRC_FULL_THRESHOLD__", str(threshold))
|
|
37
|
+
.replace("__JSRC_MAX_DISPLAY_NODES__", str(max_nodes))
|
|
38
|
+
)
|
|
39
|
+
write_text(os.path.join(base, "js/script.js"), script)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _zip_viewer(viewer_dir: Path, zip_output: str) -> None:
|
|
43
|
+
zip_path = Path(zip_output).expanduser().resolve()
|
|
44
|
+
zip_path.parent.mkdir(parents=True, exist_ok=True)
|
|
45
|
+
wanted = [
|
|
46
|
+
viewer_dir / "index.html",
|
|
47
|
+
viewer_dir / "css" / "style.css",
|
|
48
|
+
viewer_dir / "js" / "script.js",
|
|
49
|
+
viewer_dir / "json" / "grn.json",
|
|
50
|
+
viewer_dir / "json" / "annotation.json",
|
|
51
|
+
]
|
|
52
|
+
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zf:
|
|
53
|
+
for f in wanted:
|
|
54
|
+
if f.exists():
|
|
55
|
+
zf.write(f, arcname=str(f.relative_to(viewer_dir)))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def cmd(args: Namespace) -> None:
|
|
59
|
+
root = Path(args.dir).expanduser().resolve()
|
|
60
|
+
view_mode = "expand" if args.expand else "auto"
|
|
61
|
+
_sync_assets(str(root), view_mode, args.threshold, args.max_nodes)
|
|
62
|
+
if args.grn_json:
|
|
63
|
+
shutil.copy(args.grn_json, root / "json" / "grn.json")
|
|
64
|
+
if args.annotation_json:
|
|
65
|
+
shutil.copy(args.annotation_json, root / "json" / "annotation.json")
|
|
66
|
+
if args.zip_output:
|
|
67
|
+
_zip_viewer(root, args.zip_output)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def register(subparsers: Any) -> None:
|
|
71
|
+
p = subparsers.add_parser("build", help="Build GRN viewer package")
|
|
72
|
+
p.add_argument("-d", "--dir", default=".", help="Output directory (default: .)")
|
|
73
|
+
p.add_argument("-g", "--grn-json", help="grn.json to copy into package")
|
|
74
|
+
p.add_argument(
|
|
75
|
+
"-n", "--annotation-json", help="annotation.json to copy into package"
|
|
76
|
+
)
|
|
77
|
+
p.add_argument("-z", "--zip-output", help="ZIP output path")
|
|
78
|
+
mode = p.add_mutually_exclusive_group()
|
|
79
|
+
mode.add_argument("-a", "--all", action="store_true", help="Full view mode")
|
|
80
|
+
mode.add_argument(
|
|
81
|
+
"-e", "--expand", action="store_true", help="Click-to-expand mode"
|
|
82
|
+
)
|
|
83
|
+
p.set_defaults(all=True)
|
|
84
|
+
p.add_argument(
|
|
85
|
+
"-t", "--threshold", type=int, default=300, help="Auto full-view threshold"
|
|
86
|
+
)
|
|
87
|
+
p.add_argument("--max-nodes", type=int, default=0, help="Max nodes (0 = all)")
|
|
88
|
+
p.set_defaults(func=cmd)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import logging
|
|
3
|
+
from argparse import Namespace
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from jsrc.grn.core import write_json
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def network_to_json(
|
|
12
|
+
input_path: str, output_path: str
|
|
13
|
+
) -> tuple[list[dict[str, Any]], int]:
|
|
14
|
+
links = []
|
|
15
|
+
with open(input_path, "r", encoding="utf-8") as f:
|
|
16
|
+
reader = csv.reader(f, delimiter="\t")
|
|
17
|
+
for row in reader:
|
|
18
|
+
if len(row) < 3:
|
|
19
|
+
continue
|
|
20
|
+
source_id = str(row[0]).replace("_", "-")
|
|
21
|
+
target_id = str(row[1]).replace("_", "-")
|
|
22
|
+
try:
|
|
23
|
+
weight = float(row[2])
|
|
24
|
+
except ValueError:
|
|
25
|
+
continue
|
|
26
|
+
links.append({"source": source_id, "target": target_id, "val": weight})
|
|
27
|
+
write_json(output_path, links)
|
|
28
|
+
nodes = set()
|
|
29
|
+
for item in links:
|
|
30
|
+
nodes.add(item["source"])
|
|
31
|
+
nodes.add(item["target"])
|
|
32
|
+
logger.info("Network JSON written: %s", output_path)
|
|
33
|
+
logger.info("Genes: %d | Edges: %d", len(nodes), len(links))
|
|
34
|
+
return links, len(nodes)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def cmd(args: Namespace) -> None:
|
|
38
|
+
network_to_json(args.input, args.output)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def register(subparsers: Any) -> None:
|
|
42
|
+
p = subparsers.add_parser("net2json", help="Convert GRN edge table to grn.json")
|
|
43
|
+
p.add_argument("-i", "--input", required=True, help="Input edge table (TSV)")
|
|
44
|
+
p.add_argument("-o", dest="output", required=True, help="Output JSON path")
|
|
45
|
+
p.set_defaults(func=cmd)
|
|
@@ -6,17 +6,12 @@ from argparse import Namespace
|
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
8
|
from jsrc.grn.core import ensure_dir, write_json
|
|
9
|
-
from jsrc.grn.
|
|
9
|
+
from jsrc.grn.build import _sync_assets
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def cmd(args: Namespace) -> None:
|
|
13
|
-
view_mode = "expand" if args.
|
|
14
|
-
|
|
15
|
-
args.dir,
|
|
16
|
-
init_empty_json=False,
|
|
17
|
-
view_mode=view_mode,
|
|
18
|
-
full_view_threshold=args.threshold,
|
|
19
|
-
)
|
|
13
|
+
view_mode = "expand" if args.expand else "auto"
|
|
14
|
+
_sync_assets(args.dir, view_mode, args.threshold, 0)
|
|
20
15
|
ensure_dir(f"{args.dir}/json")
|
|
21
16
|
src_grn = os.path.abspath(args.grn_json)
|
|
22
17
|
dst_grn = os.path.abspath(f"{args.dir}/json/grn.json")
|
|
@@ -58,12 +53,12 @@ def register(subparsers: Any) -> None:
|
|
|
58
53
|
help="Mode all: auto full-view when gene count <= threshold",
|
|
59
54
|
)
|
|
60
55
|
mode.add_argument(
|
|
61
|
-
"-
|
|
62
|
-
"--
|
|
56
|
+
"-e",
|
|
57
|
+
"--expand",
|
|
63
58
|
action="store_true",
|
|
64
|
-
help="
|
|
59
|
+
help="Click-to-expand mode",
|
|
65
60
|
)
|
|
66
|
-
p.set_defaults(all=True,
|
|
61
|
+
p.set_defaults(all=True, expand=False)
|
|
67
62
|
p.add_argument(
|
|
68
63
|
"-t",
|
|
69
64
|
"--threshold",
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>GRN</title>
|
|
6
|
+
<link rel="stylesheet" href="css/style.css">
|
|
7
|
+
<script src="//unpkg.com/d3"></script>
|
|
8
|
+
<script src="//unpkg.com/force-graph"></script>
|
|
9
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
|
10
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="controls">
|
|
14
|
+
<div class="row">
|
|
15
|
+
<button onclick="goBack()" id="btnBack" disabled><</button>
|
|
16
|
+
<button onclick="goForward()" id="btnFwd" disabled>></button>
|
|
17
|
+
<button onclick="exportImage('pdf')" class="btn-export">PDF</button>
|
|
18
|
+
<button onclick="resetView()" class="btn-reset">Reset</button>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div class="row search-row">
|
|
22
|
+
<input type="text" id="geneInput" placeholder="Enter Gene ID">
|
|
23
|
+
<button onclick="startNewSearch()" class="btn-search">Search</button>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div id="legend">Line thickness indicates weight</div>
|
|
27
|
+
<div id="nodeCount">Nodes: 0</div>
|
|
28
|
+
<div id="neighborList"></div>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div id="watermark">GRN</div>
|
|
32
|
+
<div id="emptyState">No Nodes</div>
|
|
33
|
+
<div id="graph"></div>
|
|
34
|
+
|
|
35
|
+
<script src="js/script.js"></script>
|
|
36
|
+
</body>
|
|
37
|
+
</html>
|