Skip to content

Commit

Permalink
Merge pull request #35 from dnanto/develop
Browse files Browse the repository at this point in the history
v2.2.0
  • Loading branch information
dnanto authored Oct 12, 2024
2 parents 002fb47 + 8ef9986 commit 0db86f1
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 63 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# v2.2.0

- make facet outline optional
- add lattice generation
- add facet generation

# v2.1.3

- revert levo/dextro bug-fix, it was correct before...
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This work implements Caspar-Klug Theory to generate high-quality, vectorized cap

# Run

- Run democapsid (v2.1.3): [https://dnanto.github.io/democapsid/app.html](https://dnanto.github.io/democapsid/app.html).
- Run democapsid (v2.2.0): [https://dnanto.github.io/democapsid/app.html](https://dnanto.github.io/democapsid/app.html).

![screenshot.png](screenshot.png)

Expand Down
26 changes: 19 additions & 7 deletions app.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
<title>democapsid</title>
<link rel="stylesheet" href="css/app.css" />
<script type="text/javascript" src="js/lib/paperjs/paper-core.min.js"></script>
<script type="text/javascript" src="js/democapsid.min.js"></script>
<script type="text/javascript" src="js/democapsid.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</head>
<body>
<section class="layout">
<div class="sidebar">
<fieldset style="text-align: center">
<b>&#11041;&nbsp;<a href="https://github.com/dnanto/democapsid">democapsid v2.1.3</a>&nbsp;&#11041;</b>
<b>&#11041;&nbsp;<a href="https://github.com/dnanto/democapsid">democapsid v2.2.0</a>&nbsp;&#11041;</b>
</fieldset>
<fieldset>
<legend>model</legend>
Expand Down Expand Up @@ -52,18 +52,28 @@
<input type="range" min="-1000" max="1000" value="0" id="s" />
</div>
<div>
c=
<label for="mode_levo">levo</label>
c=[
<label for="mode_levo">levo&nbsp;&nbsp;&nbsp;</label>
<input type="radio" id="l" name="mode_mirror" value="levo" checked />
<label for="mode_dextro">dextro</label>
<input type="radio" id="d" name="mode_mirror" value="dextro" />
]
</div>
<div>
m=
<label for="mode_net">net&nbsp;</label>
m=[
<label for="mode_lattice">lattice</label>
<input type="radio" id="mode_lattice" name="mode" value="lattice" />
<label for="mode_facets">facets</label>
<input type="radio" id="mode_facets" name="mode" value="facets" />
]
</div>
<div>
&nbsp;&nbsp;[
<label for="mode_net">net&nbsp;&nbsp;&nbsp;&nbsp;</label>
<input type="radio" id="mode_net" name="mode" value="net" />
<label for="mode_capsid">capsid</label>
<input type="radio" id="mode_capsid" name="mode" value="capsid" checked />
]
</div>
</fieldset>
<fieldset>
Expand All @@ -76,11 +86,13 @@
<input type="number" id="φ" step="10" value="-90" />
</fieldset>
<fieldset>
<legend>fiber</legend>
<legend>features</legend>
<label for="penton_fiber_toggle">penton=</label>
<input type="checkbox" id="penton_fiber_toggle" checked />
<label for="knob_toggle">knob=</label>
<input type="checkbox" id="knob_toggle" checked />
<label for="facet_toggle">facet=</label>
<input type="checkbox" id="facet_toggle" />
</fieldset>
<fieldset>
<legend>aesthetics</legend>
Expand Down
48 changes: 25 additions & 23 deletions js/app.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
/*!
* democapsid v2.1.3 - Render viral capsids in the browser and export SVG.
* democapsid v2.2.0 - Render viral capsids in the browser and export SVG.
* MIT License
* Copyright (c) 2020 - 2024, Daniel Antonio Negrón (dnanto/remaindeer)
*/

const DRAW_MODES = {
lattice: draw_lattice,
facets: draw_facets,
net: draw_net,
capsid: draw_capsid,
};

const PARSERS = {
color: (e) => e.value,
alpha: (e) => Number(e.value).toString(16).padStart(2, "0"),
Expand All @@ -30,8 +37,8 @@ const DEFAULTS = Object.assign(
φ: (e) => parseFloat(e.value),
},
Object.fromEntries([
...["net", "capsid"].map((e) => ["mode_" + e, PARSERS.toggle]),
...["penton_fiber", "knob"].map((e) => [e + "_toggle", PARSERS.toggle]),
...Object.keys(DRAW_MODES).map((e) => ["mode_" + e, PARSERS.toggle]),
...["penton_fiber", "knob", "facet"].map((e) => [e + "_toggle", PARSERS.toggle]),
...["line", "fiber", "knob"].flatMap((e) => ["color", "alpha", "size"].map((f) => [e + "_" + f, PARSERS[f]])),
...["color", "alpha", "size", "length"].map((e) => ["fiber_" + e, PARSERS[e]]),
...["color", "alpha", "toggle"].flatMap((e) => Array.from({ length: 6 }, (_, i) => ["mer_" + e + "_" + (i + 1), PARSERS[e]])),
Expand Down Expand Up @@ -61,15 +68,15 @@ function params_to_tag(PARAMS) {

function download(e) {
const PARAMS = params();
const [mode, draw] = PARAMS.mode_capsid ? ["capsid", draw_capsid] : ["net", draw_net];
const mode = Object.keys(DRAW_MODES).find((e) => PARAMS["mode_" + e]);
const draw = DRAW_MODES[mode];
let name = ["h", "k", "H", "K", "a", "R", "t", "s", "c"].map((k) => PARAMS[k]);
name[7] = name[7].toFixed(2);
name = mode + "[" + name.join("_") + "]";
const ext = e.target.id.split("_")[1];
// only care about facet outline for SVG...
const g = draw(Object.assign({}, PARAMS, { facet_toggle: ext === "svg" ? PARAMS.facet_toggle : true }));
let href;
const obj = draw(PARAMS);
obj.remove();
// return;
/****/ if (ext === "svg") {
href =
"data:image/svg+xml;utf8," +
Expand All @@ -83,32 +90,27 @@ function download(e) {
} else if (ext === "csv" || ext === "tsv") {
const sep = ext === "csv" ? "," : "\t";
const mime = ext === "csv" ? "csv" : "tab-separated-values";
const g = draw(PARAMS);
const coordinates = PARAMS.mode_capsid
? g.children.filter((e) => e.data.type === "facet").flatMap((e, i) => e.children.flatMap((f, j) => f.data.segments_3D.map((g, k) => [...g, i + 1, j + 1, k + 1].join(sep))))
: g.children.flatMap((e, i) => e.children.flatMap((f, j) => f.segments.map((g, k) => [g.point.x, g.point.y, 1, i + 1, j + 1, k + 1].join(sep))));
href = `data:text/${mime};charset=utf-8,` + encodeURIComponent([["x", "y", "z", "facet", "polygon", "segment"].join(sep)].concat(coordinates).join("\r\n"));
g.remove();
} else if (ext === "json") {
const g = draw(PARAMS);
href =
"data:application/json;charset=utf-8," +
encodeURIComponent(
JSON.stringify(
g.children
.filter((e) => e.data.type === "facet" || PARAMS.mode_net)
.map((e, i) => e.children.map((f, j) => (PARAMS.mode_net ? f.segments.map((e) => [e.point.x, e.point.y, 1]) : f.data.segments_3D))),
.filter((e) => e.data.type === "facet" || !PARAMS.mode_capsid)
.map((e) => e.children.map((f) => (!PARAMS.mode_capsid ? f.segments.map((e) => [e.point.x, e.point.y, 1]) : f.data.segments_3D))),
null,
4
)
);
g.remove();
} else if (ext === "py") {
const g = draw(PARAMS);
const data = JSON.stringify(
g.children
.filter((e) => e.data.type === "facet" || PARAMS.mode_net)
.map((e, i) => e.children.map((f, j) => (PARAMS.mode_net ? f.segments.map((e) => [e.point.x, e.point.y, 1]) : f.data.segments_3D))),
.filter((e) => e.data.type === "facet" || !PARAMS.mode_capsid)
.map((e) => e.children.map((f) => (!PARAMS.mode_capsid ? f.segments.map((e) => [e.point.x, e.point.y, 1]) : f.data.segments_3D))),
null,
4
);
Expand All @@ -131,8 +133,8 @@ function download(e) {
[" n += 1"],
].join("\r\n")
);
g.remove();
}
g.remove();

var link = document.createElement("a");
link.download = name + "." + ext;
Expand All @@ -144,16 +146,16 @@ function update(e) {
paper.clear();
paper.setup("model");
const PARAMS = params();
const draw = PARAMS.mode_capsid ? draw_capsid : draw_net;
const msg = document.getElementById("msg");
const mode = Object.keys(DRAW_MODES).find((e) => PARAMS["mode_" + e]);
try {
draw(PARAMS);
const g = DRAW_MODES[mode](PARAMS);
const [h, k, H, K] = ["h", "k", "H", "K"].map((e) => PARAMS[e]);
msg.children[1].innerText = [
["net", "capsid"][PARAMS.mode_capsid * 1] + "[" + params_to_tag(PARAMS) + "]",
"model_sa_error=" + model_sa_error(PARAMS) * 100 + "%",
`T-Number=(${h})²+(${h})(${k})+(${k})²=` + (h * h + h * k + k * k),
`Q-Number=(${H})²+(${H})(${K})+(${K})²=` + (H * H + H * K + K * K),
`${mode}[${params_to_tag(PARAMS)}]`,
`model_sa_error=${model_sa_error(PARAMS) * 100}%`,
`T-Number=(${h})²+(${h})(${k})+(${k})²=${h * h + h * k + k * k}`,
`Q-Number=(${H})²+(${H})(${K})+(${K})²=${H * H + H * K + K * K}`,
].join("\n");
if (PARAMS.c === "levo") paper.view.scale(1, -1);
} catch (e) {
Expand Down
Loading

0 comments on commit 0db86f1

Please sign in to comment.