Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
9a909d9
Prototype: save and open a view as a BeamletOpticsProjects folder
Oct 26, 2026
d8c843a
Projects prototype: save as with a name, open by the project file .bmo
Oct 27, 2026
ea9576c
Projects prototype: GUI and agent on the same project
Oct 27, 2026
eb98785
Projects prototype: changes of the files appear live in the open window
Oct 27, 2026
393a4de
The keys of the camera do nothing while Ctrl or Cmd is held
Oct 27, 2026
2c83a9b
Projects prototype: the agent sees what the person does in the window
Oct 27, 2026
a98de37
Projects prototype: people and agents on one project, also on a share…
Oct 27, 2026
e93f7aa
BeamletOpticsProjects from its GitHub repository in [sources]
Oct 27, 2026
be51b64
Projects prototype: the window on the protocol of BeamletOpticsProjects
Oct 28, 2026
37df142
Projects prototype: the watcher reads the files in the background
Oct 28, 2026
eeec024
Merge feature/grouping into the projects prototype
Oct 28, 2026
1a8d610
Projects prototype: groups made in the window are lines of system.jl
Oct 28, 2026
a5c2092
Projects prototype: the watcher and the glides in files of their own
Oct 28, 2026
d0df14c
Projects prototype: a conflict holds only its own objects
Oct 28, 2026
47c66a0
The optical table fits the setup again after a gesture (_table_fit!)
Oct 28, 2026
a3d2b9b
Projects: the objects of one merge glide together, a group moved rigi…
Oct 28, 2026
6275710
Claims of the people in the window: implicit claims, refused gestures…
Oct 28, 2026
98bceb3
Watcher keeps up: merge at the latest every 2 s, one solve per merge,…
Oct 28, 2026
2fb625d
Projects: integration of claims, conflicts, the watcher, glides and t…
Oct 28, 2026
e27a4a8
Test of the table: it fits the setup when a drag ends
Oct 28, 2026
280195b
Claims: linked windows claim for the project, rename, aim and align a…
Oct 28, 2026
53342d6
Autosave of a live project: claims of others and busy write locks hol…
Oct 28, 2026
a6f7e21
Glides land before they leave gliding, take their tokens from the mer…
Oct 28, 2026
d7e54b7
Docs of the fixes: the pending change of the autosave, claimed lines …
Oct 28, 2026
152500c
Merge main (pivot of groups, view lock) into feature/projects-prototype
Oct 28, 2026
3d26f4b
The table fits the setup again shortly after every change; the drag o…
Oct 28, 2026
99fc212
A conflict holds the places of its object: theirs takes them from the…
Oct 28, 2026
ba63dad
A presence file that can not be written stops nothing: the look reads…
Oct 29, 2026
49ea0e3
Saving does not race the window's own look of the files; a write that…
Oct 29, 2026
1a94841
A selection of several reaches the others: presence and session files…
Oct 29, 2026
cbff47e
The window says when the packages of its project change; people and a…
Nov 4, 2026
fb55465
Merge main: parallel test runner, global and local frame, pose angles…
Nov 4, 2026
7ec83ac
Projects open from any environment: the window checks the versions of…
Nov 4, 2026
ff6daca
Merge main: pass-through detectors from the catalog, pinned cards sta…
Nov 6, 2026
c286f32
Version 0.3.1; the project tests do not depend on the speed of the ma…
Nov 6, 2026
837ac93
Links follow the move of BeamletOptics to StackEnjoyer/BeamletOptics.…
Nov 11, 2026
e1b0027
CompatHelper, as in BeamletOptics: daily, for the package, test and d…
Nov 11, 2026
7ea477d
Docs on projects: a page of its own (the folder, autosave, changes of…
Nov 11, 2026
c6d8ed0
benchmark/two_machines.jl: two machines on one project in a shared fo…
Nov 11, 2026
6c27972
Benchmarks for a slow shared drive: drive_io.jl times the single file…
Nov 11, 2026
e3912d0
A watched window writes the project files in the background: the auto…
Nov 11, 2026
63c3c2d
A card row can fill the width of the card (#64): CardWidget(...; fill…
Nov 11, 2026
6a25a4c
Skeleton of the activity of the others (plans/activity-cues.md): the …
Nov 11, 2026
8f84124
Picking the members of a system asks the claims of the system: a clic…
Nov 11, 2026
de91b75
The activity model of the others (plans/activity-cues.md, W1): a calm…
Nov 11, 2026
adaf307
The undo of a key step on an object that glides to a pose of the file…
Nov 11, 2026
294f51d
The cues of the activity of the others in the 3D view (plans/activity…
Nov 11, 2026
ba78a28
The timeline of the activity of the others (plans/activity-cues.md, W…
Nov 11, 2026
d5152af
Own types of a project take part in the window (#66, #63, #65): the w…
Nov 11, 2026
702e48b
The activity of the others in a watched window (plans/activity-cues.m…
Nov 12, 2026
3977bf7
watch_notify.jl retries a write that the drive refuses for a moment a…
Nov 12, 2026
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
20 changes: 20 additions & 0 deletions .github/workflows/CompatHelper.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: CompatHelper
on:
schedule:
- cron: 0 0 * * *
workflow_dispatch:
jobs:
CompatHelper:
runs-on: ubuntu-latest
steps:
# The runner image ships no Julia
- uses: julia-actions/setup-julia@v3
with:
version: '1'
- name: Pkg.add("CompatHelper")
run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
- name: CompatHelper.main()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }}
run: julia -e 'using CompatHelper; CompatHelper.main(; subdirs = ["", "test", "docs"])'
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# BeamletOpticsGUI.jl: developer instructions for coding agents

The interactive GUI of [BeamletOptics.jl](https://github.com/JuliaPhysics/BeamletOptics.jl) (BMO):
The interactive GUI of [BeamletOptics.jl](https://github.com/StackEnjoyer/BeamletOptics.jl) (BMO):
`live_view` and the tools around it (kinematic controls, view cube, cards, custom panels, controls
and tools), built on Makie. BMO does the physics and draws the components; this package arranges
them into an interactive window.
Expand Down Expand Up @@ -174,8 +174,9 @@ describe it as available in docs or the skill.

## Releases

The users of a registered version get BeamletOptics from the registry: Pkg reads `[sources]` only
in the active project, never in a dependency. The entries stay in the registered version; the
The users of a registered version get BeamletOptics from the registry: Pkg reads `[sources]` of
the active project and of dependencies tracked by path, never of a registered dependency (checked
on Julia 1.13). The entries stay in the registered version; the
docs of a tag remove them and use the registered BMO. BMO and the GUI are released together: the
latest registered GUI works with the latest registered BMO.

Expand Down
15 changes: 12 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "BeamletOpticsGUI"
uuid = "d62ba671-5e61-47cc-8a7f-19d21d414e61"
version = "0.3.0"
version = "0.3.1"
authors = ["Hugo Uittenbosch <hugo.uittenbosch@dlr.de>, Oliver Kliebisch <oliver.kliebisch@dlr.de> and Thomas Dekorsy <thomas.dekorsy@dlr.de>"]

[workspace]
Expand All @@ -9,12 +9,16 @@ projects = ["test", "docs"]
[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
BeamletOptics = "c387492b-ffec-4e51-9a46-bd230226031c"
BeamletOpticsProjects = "cd81f88b-d4c6-44ce-ae16-166b70b38414"
FileWatching = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
NativeFileDialog = "e1fe445b-aa65-4df4-81c1-2041507f0fd4"
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[weakdeps]
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
Expand All @@ -23,16 +27,21 @@ GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
BeamletOpticsGUIGLMakieExt = "GLMakie"

[sources]
BeamletOptics = {url = "https://github.com/JuliaPhysics/BeamletOptics.jl", rev = "master"}
BeamletOptics = {url = "https://github.com/StackEnjoyer/BeamletOptics.jl", rev = "master"}
BeamletOpticsProjects = {url = "https://github.com/StackEnjoyer/BeamletOpticsProjects.jl", rev = "feature/own-types"}

[compat]
AbstractTrees = "0.4"
BeamletOptics = "0.14"
BeamletOptics = "0.14.1"
BeamletOpticsProjects = "0.1"
FileWatching = "1"
GLMakie = "0.13"
GeometryBasics = "0.5"
InteractiveUtils = "1"
LinearAlgebra = "1"
Makie = "0.24"
NativeFileDialog = "0.2"
PrecompileTools = "1"
Preferences = "1"
TOML = "1"
julia = "1.12"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[![codecov](https://codecov.io/gh/StackEnjoyer/BeamletOpticsGUI.jl/graph/badge.svg)](https://codecov.io/gh/StackEnjoyer/BeamletOpticsGUI.jl)
[![Aqua QA](https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg)](https://github.com/JuliaTesting/Aqua.jl)

Interactive GUI for [BeamletOptics.jl](https://github.com/JuliaPhysics/BeamletOptics.jl): move the
Interactive GUI for [BeamletOptics.jl](https://github.com/StackEnjoyer/BeamletOptics.jl): move the
components of an optical setup with the mouse and keyboard, and see the beams and detector signals
update live. BeamletOptics computes the physics and draws the components; this package arranges
them into an interactive window.
Expand Down
47 changes: 47 additions & 0 deletions benchmark/drive_io.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# How long the file accesses of a project take on a drive: the accesses that the window does on its
# own thread (the autosave, the look of the watcher, the presence), one by one, without the GUI.
# Run it on each machine with a folder on the shared drive (and once with a folder on the local
# disk to compare); it writes only into `<folder>/drive-io-<host>`, which it removes at the end.
#
# julia benchmark/drive_io.jl <folder> [n = 40]
#
# Prints per access the median and the maximum in ms. Only the standard library is needed.
using Printf

const DIR = joinpath(abspath(ARGS[1]), "drive-io-" * gethostname())
const N = length(ARGS) >= 2 ? parse(Int, ARGS[2]) : 40

median(x) = (s = sort(x); n = length(s); isodd(n) ? s[(n + 1) ÷ 2] : (s[n ÷ 2] + s[n ÷ 2 + 1]) / 2)

function measure()
rm(DIR; recursive = true, force = true)
mkpath(joinpath(DIR, "sub"))
text = repeat("@component L1 = SphericalLens(0.05, -0.05, 0.005, 0.0254, ConstantRefractiveIndex(1.5)) pos = (0.0, 0.1, 0.0)\n", 30)
file = joinpath(DIR, "system.jl")
write(file, text)
for i in 1:10
write(joinpath(DIR, "sub", "f$i.toml"), "x = $i\n")
end
ops = [
"isfile" => () -> isfile(file),
"mtime" => () -> mtime(file),
"read 3 KB" => () -> read(file, String),
"readdir (10 files)" => () -> readdir(joinpath(DIR, "sub")),
"write in place" => () -> write(file, text),
"write tmp + rename" => () -> (tmp = file * ".tmp"; write(tmp, text); mv(tmp, file; force = true)),
"create + remove" => () -> (f = joinpath(DIR, "lock"); write(f, "x"); rm(f)),
"mkdir + rmdir" => () -> (d = joinpath(DIR, "d"); mkdir(d); rm(d)),
]
println("folder: ", DIR, ", ", N, " times each")
for (name, f) in ops
f()
t = Float64[]
for _ in 1:N
push!(t, @elapsed f())
end
@printf("%-20s median %8.2f ms max %8.2f ms\n", name, 1000 * median(t), 1000 * maximum(t))
end
rm(DIR; recursive = true, force = true)
end

measure()
54 changes: 54 additions & 0 deletions benchmark/save_io.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# The parts of an autosave after a change, on the local disk and over SMB, to find the file
# accesses that cost the thread of the window.
#
# julia --project=test benchmark/save_io.jl <project folder on C:> [<folder on a drive>]
#
# Without the second folder, the copy of the project is measured on the local disk and through
# \\localhost\C$\...; with it, on the local disk and in a copy inside that folder (e.g. a folder on a
# shared drive), which is removed at the end.
using GLMakie, BeamletOptics, BeamletOpticsGUI, BeamletOpticsProjects
const G = BeamletOpticsGUI
const P = BeamletOpticsProjects

ms(t) = round(1000t; digits = 1)

copy_dir = joinpath(mktempdir(), basename(ARGS[1]))
cp(ARGS[1], copy_dir)
rm(joinpath(copy_dir, ".bmo"); force = true, recursive = true)
remote = if length(ARGS) >= 2
d = joinpath(abspath(ARGS[2]), "save-io-" * gethostname(), basename(ARGS[1]))
rm(dirname(d); recursive = true, force = true)
mkpath(dirname(d))
cp(copy_dir, d)
d
else
raw"\\localhost\C$" * copy_dir[3:end]
end
try
for dir in (copy_dir, remote)
t_open = @elapsed(gui = open_project(dir; display = false, trace_budget = Inf, throttle = false, detectors = []))
obj = first(x for x in keys(gui.sync.ids) if haskey(gui.components.origin, x))
times = Dict{String, Float64}()
for i in 1:4
G.translate3d!(gui, obj, [0.0, 0.0, 1e-4])
t = Dict(
"project_stamp" => @elapsed(P.project_stamp(dir)),
"file_marks" => @elapsed(G._file_marks(dir)),
"project_parts" => @elapsed(G._project_parts(gui, dir; name = gui.sync.base.name)),
"save_project" => @elapsed(save_project(gui, dir)),
"write_presence" => @elapsed(G._write_presence!(gui)),
"write_session" => @elapsed(G._write_session!(gui)),
"files_look" => @elapsed(G._files_look(dir; stamp = true, except = G._person().id, known = String[])),
"claims" => @elapsed(P.claims(dir)),
)
i > 1 && mergewith!(+, times, t)
end
println(dir, " (open_project ", ms(t_open), " ms, the first time compiles)")
for (k, v) in sort(collect(times); by = last, rev = true)
println(" ", rpad(k, 16), ms(v / 3), " ms")
end
close(gui)
end
finally
length(ARGS) >= 2 && rm(dirname(remote); recursive = true, force = true)
end
Loading