Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/apps/CoherentDiffractiveImaging/app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
authors:
- ptuemmler
categories:
- Physics
tags:
- Fourier Transform
- Scattering
date: 2026-02-18
hide:
- toc
---
# Coherent Diffractive Imaging
<!-- more -->
{{embed_app("100%", "1000px")}}

!!! quote "If you use this application for your research, please cite it as:"
P. Tuemmler, J. Apportin, T. Fennel, and C. Peltz, “Fast Simulation of Wide-Angle Coherent Diffractive Imaging.” _Laser Photonics Rev_ (2025): e02001.
[https://doi.org/10.1002/lpor.202502001](https://doi.org/10.1002/lpor.202502001)

Note that this app reflects pretty much a worst case scenario regarding its numerical performance.
The calculations are performed inside a virtual environment within a web browser, which is can not leverage the full capabilities of the host machine.
If you are interested in a more performant implementation, please check out the [pyMSFT](https://gitlab.uni-rostock.de/snp/pymsft) library, which is a GPU-capable Python implementation of the methods shown in this app.
464 changes: 464 additions & 0 deletions docs/apps/CoherentDiffractiveImaging/app.py

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions docs/apps/CoherentDiffractiveImaging/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
plotly
numpy
stl-to-voxel
Binary file not shown.
314 changes: 314 additions & 0 deletions docs/apps/CoherentDiffractiveImaging/utils.py

Large diffs are not rendered by default.

175 changes: 91 additions & 84 deletions docs/apps/TemplatePlotly/animated_js/app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import numpy as np
import plotly.graph_objects as go
from shiny import App, Inputs, Outputs, Session, render, ui

Expand All @@ -14,9 +13,29 @@
)


def build_plot_from_js(javascript_text, **kwargs):
fig = go.Figure(
)

def server(input: Inputs, output: Outputs, session: Session):
plot_html = fig.to_html(
auto_play=False,
include_plotlyjs=True,
full_html=False,
div_id="animated_plot"
)

for k, v in kwargs.items():
javascript_text = javascript_text.replace(k, str(v))

loop_script = f"""
<script>
{javascript_text}
</script>
"""

return ui.HTML(plot_html + loop_script)

def server(input: Inputs, output: Outputs, session: Session):
@render.ui
def plot():
s = input.sigma()
Expand All @@ -26,91 +45,79 @@ def plot():

n = input.n()

fig = go.Figure(
)

plot_html = fig.to_html(
auto_play=False,
include_plotlyjs=True,
full_html=False,
div_id="animated_plot"
)

loop_script = f"""
<script>
(function () {{
// ----- DESTROY PREVIOUS INSTANCE -----
if (window.lorenzAnimation) {{
cancelAnimationFrame(window.lorenzAnimation.frameId);
Plotly.purge('animated_plot');
window.lorenzAnimation = null;
}}

// ----- CREATE NEW INSTANCE -----
var controller = {{
frameId: null
}};
window.lorenzAnimation = controller;

var n = {n};
var x = [], y = [], z = [];
var dt = {dt};

var s = {s};
var b = {b};
var r = {r};

for (var i = 0; i < n; i++) {{
x[i] = Math.random() * 2 - 1;
y[i] = Math.random() * 2 - 1;
z[i] = 30 + Math.random() * 10;
}}

Plotly.react('animated_plot', [{{
x: x,
y: z,
mode: 'markers',
}}], {{
xaxis: {{
range: [-40, 40],
}},
yaxis: {{
range: [0, 60],
}}
}});


function compute () {{
for (var i = 0; i < n; i++) {{
var dx = s * (y[i] - x[i]);
var dy = x[i] * (r - z[i]) - y[i];
var dz = x[i] * y[i] - b * z[i];

x[i] += dx * dt;
y[i] += dy * dt;
z[i] += dz * dt;
}}
}}

function update () {{
compute();

Plotly.animate('animated_plot', {{
data: [{{ x: x, y: z }}]
}}, {{
transition: {{ duration: 0 }},
frame: {{ duration: 0, redraw: false }}
}});

loop_script="""
(function () {
// ----- DESTROY PREVIOUS INSTANCE -----
if (window.lorenzAnimation) {
cancelAnimationFrame(window.lorenzAnimation.frameId);
Plotly.purge('animated_plot');
window.lorenzAnimation = null;
}

// ----- CREATE NEW INSTANCE -----
var controller = {
frameId: null
};
window.lorenzAnimation = controller;

var n = VAR_n;
var x = [], y = [], z = [];
var dt = VAR_dt;

var s = VAR_s;
var b = VAR_b;
var r = VAR_r;

for (var i = 0; i < n; i++) {
x[i] = Math.random() * 2 - 1;
y[i] = Math.random() * 2 - 1;
z[i] = 30 + Math.random() * 10;
}

Plotly.react('animated_plot', [{
x: x,
y: z,
mode: 'markers',
}], {
xaxis: {
range: [-40, 40],
},
yaxis: {
range: [0, 60],
}
});


function compute () {
for (var i = 0; i < n; i++) {
var dx = s * (y[i] - x[i]);
var dy = x[i] * (r - z[i]) - y[i];
var dz = x[i] * y[i] - b * z[i];

x[i] += dx * dt;
y[i] += dy * dt;
z[i] += dz * dt;
}
}

function update () {
compute();

Plotly.animate('animated_plot', {
data: [{ x: x, y: z }]
}, {
transition: { duration: 0 },
frame: { duration: 0, redraw: false }
});

controller.frameId = requestAnimationFrame(update);
}

controller.frameId = requestAnimationFrame(update);
}}

controller.frameId = requestAnimationFrame(update);
}})();
</script>
})();
"""

return ui.HTML(plot_html + loop_script)
return build_plot_from_js(loop_script, VAR_n=n, VAR_dt=dt, VAR_s=s, VAR_b=b, VAR_r=r)


app = App(app_ui, server)
4 changes: 4 additions & 0 deletions docs/stylesheets/extra.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.md-grid {
max-width: initial;
}

[data-md-color-scheme="slate"] {
--md-default-bg-color: #1d1f21;
}
6 changes: 5 additions & 1 deletion gen_shinylive.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@
_export.export(target_apppath, Path("./site"), subdir=target_shinypath, verbose=True, full_shinylive=True)

# Copy source code incase the embed_code macro is used
shutil.copyfile(app_path, Path("./site", target_shinypath, "app.py"))
# shutil.copyfile(app_path, Path("./site", target_shinypath, "app.py"))

for file_name in os.listdir(target_apppath):
print(f"Copying {Path(target_apppath, file_name)} to {Path('./site', target_shinypath, file_name)}")
shutil.copyfile(Path(target_apppath, file_name), Path("./site", target_shinypath, file_name))
4 changes: 2 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def define_env(env):
@env.macro
def embed_app(width='100%', height='600px', subdir: str = None):
current_path = Path(str(getattr(env, 'page'))) # " /blog/plotly-penguins-app.html"
return f"<div>\n<iframe src={get_app_link(current_path, subdir, 'index.html')} width={width} height={height}></iframe>\n</div>"
return f"""\n???+ example "Application"\n\t<div>\n\t<iframe src={get_app_link(current_path, subdir, 'index.html')} width={width} height={height} frameborder='0'></iframe>\n\t</div>"""

@env.macro
def embed_code(subdir: str = None, language: str = 'python', optional=True):
Expand All @@ -36,7 +36,7 @@ def embed_code(subdir: str = None, language: str = 'python', optional=True):
raise KeyError("Unsupported language")

if optional:
embed_text = "\n??? info\n" + embed_text.replace("\n", "\n\t")
embed_text = """\n??? quote "Code"\n""" + embed_text.replace("\n", "\n\t")
return embed_text

@env.macro
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ markdown_extensions:
generic: true
- attr_list
- md_in_html
- admonition
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.superfences
Expand Down