From 39e2dff8f47a19e358051c8070fb2c79396c449b Mon Sep 17 00:00:00 2001 From: Matt Cuffaro Date: Mon, 3 Nov 2025 17:44:19 -0800 Subject: [PATCH 01/11] basic tabular view functionality CLEANUP: changing tests CLEANUP: reorganized code into parse and execute folders refactor algjuliainterop CORS and async issues resolved basic tabular view functionality edit remove decapodes material run formatter docs fix using local version remove axios undo changes newlines remove space More docs --- .gitignore | 3 + packages/algjulia-interop/Project.toml | 49 +- packages/algjulia-interop/README.md | 64 ++- packages/algjulia-interop/ext/CatlabExt.jl | 120 +++++ packages/algjulia-interop/ext/SysImageExt.jl | 24 - packages/algjulia-interop/make_sysimage.jl | 24 - packages/algjulia-interop/scripts/endpoint.jl | 51 ++ .../algjulia-interop/src/CatColabInterop.jl | 85 +--- packages/algjulia-interop/src/Types.jl | 74 +++ .../src/decapodes-service/DecapodesService.jl | 42 -- .../decapodes-service/analysis/Analysis.jl | 3 - .../analysis/initial_conditions.jl | 101 ---- .../decapodes-service/analysis/ns_helper.jl | 87 ---- .../decapodes-service/analysis/simulation.jl | 161 ------- .../src/decapodes-service/diagram.jl | 113 ----- .../src/decapodes-service/geometry.jl | 120 ----- .../src/decapodes-service/model.jl | 107 ----- .../algjulia-interop/src/kernel_management.jl | 256 ----------- .../algjulia-interop/src/kernel_support.jl | 32 -- packages/algjulia-interop/src/result.jl | 23 - .../algjulia-interop/sysimage_precompile.jl | 2 - packages/algjulia-interop/test/Project.toml | 13 +- packages/algjulia-interop/test/TestCatlab.jl | 54 +++ .../test/data/diagrams/acset.json | 166 +++++++ packages/algjulia-interop/test/runtests.jl | 238 +--------- .../diffusivity_constant/analysis.json | 47 -- .../diffusivity_constant/diagram.json | 201 -------- .../diagrams/inverse_laplacian/analysis.json | 54 --- .../diagrams/inverse_laplacian/diagram.json | 73 --- .../inverse_laplacian_longtrip/analysis.json | 1 - .../inverse_laplacian_longtrip/diagram.json | 1 - .../test_jsons/diagrams/ns_vort/analysis.json | 1 - .../test_jsons/diagrams/ns_vort/diagram.json | 1 - .../test/test_jsons/diffconst_payload1.json | 435 ------------------ .../test/test_jsons/models/model_dec.json | 250 ---------- .../test_jsons/models/model_dec_scalar.json | 274 ----------- .../test/test_jsons/payload.json | 435 ------------------ packages/frontend/pnpm-lock.yaml | 1 + packages/frontend/src/stdlib/analyses.tsx | 10 + .../src/stdlib/analyses/decapodes.tsx | 10 +- .../src/stdlib/analyses/tabular_view.css | 4 + .../src/stdlib/analyses/tabular_view.tsx | 156 +++++++ .../src/stdlib/theories/simple-schema.ts | 6 + 43 files changed, 702 insertions(+), 3270 deletions(-) create mode 100644 packages/algjulia-interop/ext/CatlabExt.jl delete mode 100644 packages/algjulia-interop/ext/SysImageExt.jl delete mode 100755 packages/algjulia-interop/make_sysimage.jl create mode 100644 packages/algjulia-interop/scripts/endpoint.jl create mode 100644 packages/algjulia-interop/src/Types.jl delete mode 100644 packages/algjulia-interop/src/decapodes-service/DecapodesService.jl delete mode 100644 packages/algjulia-interop/src/decapodes-service/analysis/Analysis.jl delete mode 100644 packages/algjulia-interop/src/decapodes-service/analysis/initial_conditions.jl delete mode 100644 packages/algjulia-interop/src/decapodes-service/analysis/ns_helper.jl delete mode 100644 packages/algjulia-interop/src/decapodes-service/analysis/simulation.jl delete mode 100644 packages/algjulia-interop/src/decapodes-service/diagram.jl delete mode 100644 packages/algjulia-interop/src/decapodes-service/geometry.jl delete mode 100644 packages/algjulia-interop/src/decapodes-service/model.jl delete mode 100644 packages/algjulia-interop/src/kernel_management.jl delete mode 100644 packages/algjulia-interop/src/kernel_support.jl delete mode 100644 packages/algjulia-interop/src/result.jl delete mode 100755 packages/algjulia-interop/sysimage_precompile.jl create mode 100644 packages/algjulia-interop/test/TestCatlab.jl create mode 100644 packages/algjulia-interop/test/data/diagrams/acset.json delete mode 100644 packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/analysis.json delete mode 100644 packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/diagram.json delete mode 100644 packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/analysis.json delete mode 100644 packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/diagram.json delete mode 100644 packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/analysis.json delete mode 100644 packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/diagram.json delete mode 100644 packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/analysis.json delete mode 100644 packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/diagram.json delete mode 100644 packages/algjulia-interop/test/test_jsons/diffconst_payload1.json delete mode 100644 packages/algjulia-interop/test/test_jsons/models/model_dec.json delete mode 100644 packages/algjulia-interop/test/test_jsons/models/model_dec_scalar.json delete mode 100644 packages/algjulia-interop/test/test_jsons/payload.json create mode 100644 packages/frontend/src/stdlib/analyses/tabular_view.css create mode 100644 packages/frontend/src/stdlib/analyses/tabular_view.tsx diff --git a/.gitignore b/.gitignore index 4dc6e7ec8..7ee78b4c2 100644 --- a/.gitignore +++ b/.gitignore @@ -109,3 +109,6 @@ catcolab-vm.qcow2 # Markdown previews README.html CHANGELOG.html + +# VSCode +.vscode/* \ No newline at end of file diff --git a/packages/algjulia-interop/Project.toml b/packages/algjulia-interop/Project.toml index 9e270ce35..0d1e76d5b 100644 --- a/packages/algjulia-interop/Project.toml +++ b/packages/algjulia-interop/Project.toml @@ -1,53 +1,28 @@ name = "CatColabInterop" uuid = "9ecda8fb-39ab-46a2-a496-7285fa6368c1" license = "MIT" -authors = ["CatColab team"] version = "0.1.1" +authors = ["CatColab team"] [deps] -ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8" -Catlab = "134e5e36-593f-5add-ad60-77f754baafbe" -CombinatorialSpaces = "b1c52339-7909-45ad-8b6a-6e388f7c67f2" -ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" -CoordRefSystems = "b46f11dc-f210-4604-bfba-323c1ec968cb" -Decapodes = "679ab3ea-c928-4fe6-8d59-fd451142d391" -DiagrammaticEquations = "6f00c28b-6bed-4403-80fa-30e0dc12f317" -Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" -GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" -IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" -JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078" -OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -Preferences = "21216c6a-2e73-6563-6e65-726566657250" -REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +Oxygen = "df9a0d86-3283-4920-82dc-4555fc0d1d8b" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" -StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +StructTypes = "856f2bd8-1eba-4b0a-8007-ebc267875bd4" [weakdeps] -PackageCompiler = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d" +ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8" +Catlab = "134e5e36-593f-5add-ad60-77f754baafbe" [extensions] -SysImageExt = "PackageCompiler" +CatlabExt = ["Catlab", "ACSets"] [compat] -ACSets = "0.2.21" -Catlab = "0.16.20" -CombinatorialSpaces = "0.7.4" -ComponentArrays = "0.15" -CoordRefSystems = "0.18.9" -Decapodes = "0.6" -DiagrammaticEquations = "0.2" -Distributions = "0.25" -GeometryBasics = "0.5.7" -IJulia = "1.26.0" -JSON3 = "1" -LinearAlgebra = "1" -MLStyle = "0.4" -OrdinaryDiffEq = "6.101.0" -PackageCompiler = "2.2.1" -Preferences = "1.5.0" -REPL = "1.11.0" +Catlab = "0.17.2" +HTTP = "1.10.19" +MLStyle = "0.4.17" +Oxygen = "1.7.5" Reexport = "1.2.2" -StaticArrays = "1" +StructTypes = "1.11.0" julia = "1.11" diff --git a/packages/algjulia-interop/README.md b/packages/algjulia-interop/README.md index f2f08390f..2ea02942e 100644 --- a/packages/algjulia-interop/README.md +++ b/packages/algjulia-interop/README.md @@ -1,47 +1,37 @@ # AlgebraicJulia Service This small package makes functionality from -[AlgebraicJulia](https://www.algebraicjulia.org/) available to CatColab, -intermediated by a Julia kernel running in the [Jupyter](https://jupyter.org/) -server. At this time, only a -[Decapodes.jl](https://github.com/AlgebraicJulia/Decapodes.jl) service is -provided. Other packages may be added in the future. - -## Setup - -1. Install [Julia](https://julialang.org/), say by using -[`juliaup`](https://github.com/JuliaLang/juliaup) -2. Install [Jupyter](https://jupyter.org/), say by using `pip` or `conda` -3. Install [IJulia](https://github.com/JuliaLang/IJulia.jl), which provides the - Julia kernel to Jupyter - -At this stage, you should be able to launch a Julia kernel inside a JupyterLab. - -Having done that, navigate to this directory and run: - -```sh -julia --project -e 'import Pkg; Pkg.instantiate()' -``` +[AlgebraicJulia](https://www.algebraicjulia.org/) available to CatColab.At this +time, only a [Catlab.jl](https://github.com/AlgebraicJulia/Catlab.jl) service is +provided. Other packages (e.g. Decapodes.jl) will be added in the future. ## Usage -To start the server, run the following in a Julia REPL -```julia -using CatColabInterop -start_server!() -``` -This will run the Jupyter kernel in the REPL. You may stop the server by -running `stop_server!()`. While the Jupyter server is running, the AlgebraicJulia service will be usable by CatColab when served locally. - -## Compiling a Sysimage +First, install [Julia](https://julialang.org/), say by using +[`juliaup`](https://github.com/JuliaLang/juliaup). + +We then need a Julia environment that has all the requisite packages installed. +The `test` folder of this repo is a perfectly good candidate for this, although +in principal one might want to use their own environment (if they don't want to +load all dependencies for all possible analyses, or if they have a locally +modified version of the code that is running the analysis). To make sure this +environment is ready to use, navigate to this directory and run +`julia --project=test` and then press `]` and enter the commands `instantiate` +and `precompile`. + +Having done that, to start the server, from this directory run: -Precompiling dependencies like `CairoMakie.jl` and `OrdinaryDiffEq.jl` can be -time-consuming. A **sysimage** is a file that stores precompilation statements, -making future invocations of `AlgebraicJuliaService` and its dependencies -immediate. +```sh +julia --project=test scripts/endpoint.jl +``` -To build a sysimage, run `build_sysimage()` in a REPL where `CatColabInterop` -module is in scope. This process may take upwards of five minutes or longer, depending on your machine. +This starts an instance that is listening on localhost port 8080. When you run +CatColab, you should be able to use analyses that communicate with Julia via +this address. -Building a sysimage installs an additional kernel which points to the sysimage. You may change the kernel to your sysimage by running `change_kernel!()`, which will populate a menu of kernels in your IJulia kernel directory. +## For developers +If one is interested in using a version of CatColabInterop.jl that doesn't match +the latest tagged release, then one must first open the Julia environment from the +test directory (`julia --project=test`) and declare one wants to use the local +version of the package (press `]` and then `dev .`) diff --git a/packages/algjulia-interop/ext/CatlabExt.jl b/packages/algjulia-interop/ext/CatlabExt.jl new file mode 100644 index 000000000..15c30202d --- /dev/null +++ b/packages/algjulia-interop/ext/CatlabExt.jl @@ -0,0 +1,120 @@ +module CatlabExt + +using ACSets +using Catlab: Presentation, FreeSchema, Left +import Catlab: id, dom +using Catlab.CategoricalAlgebra.Pointwise.FunctorialDataMigrations.Yoneda: + yoneda, colimit_representables, DiagramData +using CatColabInterop, Oxygen, HTTP +import CatColabInterop: endpoint + +""" +Take a parsed CatColab model of ThSchema and make a Catlab schema. Also +collect the mapping from UUIDs to human-readable names. +""" +function model_to_schema(m::Model)::Tuple{Schema, Dict{String,Symbol}} + obs, homs, attrtypes, attrs = Symbol[],[],[],[] + names = Dict{String, Symbol}() + + for stmt in m.obGenerators + names[stmt.id] = Symbol(only(stmt.label)) + if stmt.obType.content == "Entity" + push!(obs, names[stmt.id]) + elseif stmt.obType.content == "AttrType" + push!(attrtypes, names[stmt.id]) + else + error(stmt.obType) + end + end + + for stmt in m.morGenerators + h = (Symbol(only(stmt.label)), names[stmt.dom.content], + names[stmt.cod.content]) + names[stmt.id] = h[1] + if stmt.morType.content == "Attr" + push!(attrs, h) + else + push!(homs, h) + end + end + (Schema(Presentation(BasicSchema{Symbol}(obs, homs, attrtypes, attrs, []))), + names) +end + +""" +Take a CatColab diagram in a model of ThSchema and construct the input data +that gets parsed normally from `@acset_colim`. Mutate an existing mapping of +UUIDs to schema-level names to include UUID mappings for instance-level names. +""" +function diagram_to_data(d::Types.Diagram, names::Dict{String,Symbol} + )::DiagramData + data = DiagramData() + for o in d.obGenerators + names[o.id] = Symbol(only(o.label)) + push!(data.reprs[names[o.over.content]], names[o.id]) + end + for m in d.morGenerators + p1 = names[m.cod.content] => Symbol[] + p2 = names[m.dom.content] => [names[m.over.content]] + push!(data.eqs, p1 => p2) + end + data +end + +""" +Receiver of the data already knows the schema, so the JSON payload to CatColab +just includes the columns of data. Every part is named, so we use the names +(including for primary key columns) rather than numeric indices. +""" +function acset_to_json(X::ACSet, S::Schema, names::Dict{Symbol, Vector{String}} + )::AbstractDict + Dict{Symbol, Vector{String}}( + [t => names[t] for t in types(S)] + ∪ [f => names[c][X[f]] for (f,_,c) in homs(S)] + ∪ [f => names[c][getvalue.(X[f])] for (f,_,c) in attrs(S)] ) +end + +""" +Pick a human-readable name for all parts of the ACSet, given explicit names for +some of the parts. There is some ambiguity here (the vertex of a generic +reflexive edge `e` could be either `src(e)` or `tgt(e)`), but an arbitrary name +is chosen after minimizing length (`src(e)` preferred over `src(refl(src(e)))`). +""" +function make_names(res::ACSet, names::NamedTuple + )::Dict{Symbol, Vector{String}} + S = acset_schema(res) + function get_name(o::Symbol, i, curr=[])::Vector{Vector{Symbol}} + V(x) = o in attrtypes(S) ? AttrVar(x) : x # embellish attrvars + L(x) = o in attrtypes(S) ? Left(x) : x # embellish attrvars + found = findfirst(==((o, L(i))), names) # if (o,i) is in names + isnothing(found) || return [[found; curr]] # then just give the name + inc = [(d, new_i, f) for (f, d, _) in arrows(S, to=o) + for new_i in incident(res, V(i), f)] + return vcat([get_name(d, new_i, [f; curr]) for (d, new_i, f) in inc]...) + end + return Dict{Symbol, Vector{String}}(map(types(acset_schema(res))) do o + o => map(parts(res, o)) do i + possible_names = sort(get_name(o, i); by=length) + foldl((x,y)->"$y($x)", string.(first(possible_names))) + end + end) +end + +""" +Top level function called by CatColab. Computes an ACSet colimit of a + diagrammatic instance. Return a JSON tabular representation. +""" +function endpoint(::Val{:ACSetColim}) + @post "/acsetcolim" function(req::HTTP.Request) + payload = json(req, ModelDiagram) + schema, names = model_to_schema(payload.model) + data = diagram_to_data(payload.diagram, names) + acset_type = AnonACSet( + schema; type_assignment=Dict(a=>Nothing for a in schema.attrtypes)) + y = yoneda(constructor(acset_type)) + names, res = colimit_representables(data, y) + acset_to_json(res, schema, make_names(res, names)) + end +end + +end # module diff --git a/packages/algjulia-interop/ext/SysImageExt.jl b/packages/algjulia-interop/ext/SysImageExt.jl deleted file mode 100644 index 698555ae1..000000000 --- a/packages/algjulia-interop/ext/SysImageExt.jl +++ /dev/null @@ -1,24 +0,0 @@ -module SysImageExt - -import CatColabInterop: ServerConfig, load_kernels!, install_ccl_kernel!, CONFIG -import PackageCompiler: create_sysimage -import IJulia: installkernel - -function install_ccl_kernel!(::Val{:sysimg}; config::ServerConfig=CONFIG, sysimg = "CatColabInteropSysImage.so") - @info "Creating the sys image. This may take a while..." - mktemp() do path, io - write(io, """import CatColabInterop - include(joinpath(pkgdir(CatColabInterop), "test", "runtests.jl")) - """) - flush(io) - create_sysimage(["CatColabInterop"], sysimage_path=sysimg, precompile_execution_file=path) - end - - @info "Adding $sysimg to IJulia kernel" - installkernel("CatColabInteropSysImage", "--project=@.", "--sysimage=$sysimg") - - load_kernels!() - @info "Done!" -end - -end diff --git a/packages/algjulia-interop/make_sysimage.jl b/packages/algjulia-interop/make_sysimage.jl deleted file mode 100755 index eb1c2e763..000000000 --- a/packages/algjulia-interop/make_sysimage.jl +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env julia - -@info "Verifying PackageCompiler is installed globally" -using Pkg; Pkg.activate(); Pkg.add("PackageCompiler") -using PackageCompiler - -@info "Activating sysimage environment" -Pkg.activate(@__DIR__) - -@info "Creating the sysimage. This may take a while..." -sysimg="CatColabInterop.so" -create_sysimage(["CatColabInterop"], sysimage_path=sysimg, - precompile_execution_file="sysimage_precompile.jl") -sysimg_path=joinpath(@__DIR__, sysimg); - -@info "Adding $sysimg_path to IJulia kernel" -Pkg.activate(); Pkg.add("IJulia") -using IJulia -Pkg.build("IJulia") - -installkernel("Julia CatColab Interop", "--project=@.", "--sysimage=$sysimg_path") - -@info "Done!" -exit() diff --git a/packages/algjulia-interop/scripts/endpoint.jl b/packages/algjulia-interop/scripts/endpoint.jl new file mode 100644 index 000000000..2319e7615 --- /dev/null +++ b/packages/algjulia-interop/scripts/endpoint.jl @@ -0,0 +1,51 @@ + +# Example usage: + +# julia --project=my_alg_julia_env --threads 4 endpoint.jl Catlab AlgebraicPetri + +# Where my_alg_julia_env is a Julia environment with CatColabInterop, Oxygen, +# HTTP, and any AlgJulia dependencies. + +using CatColabInterop +using Oxygen +using HTTP + +const CORS_HEADERS = [ + "Access-Control-Allow-Origin" => "*", + "Access-Control-Allow-Headers" => "*", + "Access-Control-Allow-Methods" => "POST, GET, OPTIONS" +] + +function CorsHandler(handle) + return function (req::HTTP.Request) + # return headers on OPTIONS request + if HTTP.method(req) == "OPTIONS" + return HTTP.Response(200, CORS_HEADERS) + else + r = handle(req) + append!(r.headers, ["Access-Control-Allow-Origin" => "*"]) + r + + end + end +end + +defaults = [:Catlab,:ACSets] # all extensions to date + +# Dynamically load packages in command lin eargs +for pkg in (isempty(ARGS) ? defaults : ARGS ) + @info "using $pkg" + @eval using $pkg +end + +for m in methods(CatColabInterop.endpoint) + sig = m.sig.parameters + (length(sig)==2 && sig[2].instance isa Val) || error("Unexpected signature $sig") + name = only(sig[2].parameters) + @info "Loading endpoint $name" + name isa Symbol || error("Unexpected endpoint name $name") + fntype, argtypes... = m.sig.types + invoke(fntype.instance, Tuple{argtypes...}, Val(name)) +end + +serve(middleware=[CorsHandler]) diff --git a/packages/algjulia-interop/src/CatColabInterop.jl b/packages/algjulia-interop/src/CatColabInterop.jl index a0b0d2320..18bd4b81a 100644 --- a/packages/algjulia-interop/src/CatColabInterop.jl +++ b/packages/algjulia-interop/src/CatColabInterop.jl @@ -1,86 +1,15 @@ module CatColabInterop -using MLStyle -using Reexport - -# this code tracks integrations and allows for basic theory/model-building code to dispatch from it. -# the intent is that this is an interface for AlgebraicJulia code to interoperate with CatColab -abstract type AlgebraicJuliaIntegration end - -# cells in the JSON are tagged. these are just objects for dispatching `to_model` -@data ModelElementTag begin - ObTag() - HomTag() -end -export ObTag, HomTag - -#= -@active patterns are MLStyle-implementations of F# active patterns that forces us to work in the Maybe/Option pattern. -Practically, yet while a matter of opinion, they make @match statements cleaner; a statement amounts to a helpful pattern -name and the variables we intend to capture. -=# -@active IsObject(x) begin; x[:content][:tag] == "object" ? Some(x[:content]) : nothing end -@active IsMorphism(x) begin; x[:content][:tag] == "morphism" ? Some(x[:content]) : nothing end -export IsObject, IsMorphism - -# Obs, Homs -@data ModelElementValue begin - ObValue() - HomValue(dom,cod) -end -export ObValue, HomValue - -""" -Struct capturing the name of the object and its relevant information. -ModelElementValue may be objects or homs, each of which has different data. -""" -struct ModelElement - name::Union{Symbol, Nothing} - val::Union{<:ModelElementValue, Nothing} - function ModelElement(;name::Symbol=nothing,val::Any=nothing) - new(name, val) - end -end -export ModelElement - -Base.nameof(t::ModelElement) = t.name +export endpoint -""" Struct wrapping a dictionary """ -struct Model{T<:AlgebraicJuliaIntegration} - data::Dict{String, ModelElement} -end -export Model - -function Model(::T) where T<:AlgebraicJuliaIntegration - Model{T}(Dict{String, ModelElement}()) -end - -Base.values(model::Model) = values(model.data) +using Reexport """ -Functions to build a dictionary associating ids in the theory to elements in the model +Extend this method with endpoint(::Val{my_analysis_name}) in extension packages. """ -function to_model end -export to_model - - -# TODO supposes bijection between theories, models, diagrams, etc. -abstract type AbstractDiagram{T<:AlgebraicJuliaIntegration} end - -abstract type AbstractAnalysis{T<:AlgebraicJuliaIntegration} end - -struct ImplError <: Exception - name::String -end -export ImplError - -Base.showerror(io::IO, e::ImplError) = print(io, "$(e.name) not implemented") - -include("result.jl") -include("kernel_management.jl") -include("kernel_support.jl") -include("decapodes-service/DecapodesService.jl") +function endpoint end -@reexport using .DecapodesService +include("Types.jl") +@reexport using .Types -end +end # module diff --git a/packages/algjulia-interop/src/Types.jl b/packages/algjulia-interop/src/Types.jl new file mode 100644 index 000000000..5d61abe8b --- /dev/null +++ b/packages/algjulia-interop/src/Types.jl @@ -0,0 +1,74 @@ +# TODO make this automatically generated by CatColab +""" Common types useful for deserializing CatColab JSON payloads """ +module Types + +export ObType, MorType, DiagramObGenerator, DiagramMorGenerator, ObGenerator, + MorGenerator, Diagram, Model, ModelDiagram + +using StructTypes + +struct ObType + tag::String + content::String +end +StructTypes.StructType(::Type{ObType}) = StructTypes.Struct() + +struct MorType + tag::String + content::Union{String,ObType} +end +StructTypes.StructType(::Type{MorType}) = StructTypes.Struct() + +struct DiagramObGenerator + id::String + label::Vector{String} + obType::ObType + over::ObType +end +StructTypes.StructType(::Type{DiagramObGenerator}) = StructTypes.Struct() + +struct DiagramMorGenerator + id::String + morType::MorType + over::ObType + dom::ObType + cod::ObType +end +StructTypes.StructType(::Type{DiagramMorGenerator}) = StructTypes.Struct() + +struct ObGenerator + id::String + label::Vector{String} + obType::ObType +end +StructTypes.StructType(::Type{ObGenerator}) = StructTypes.Struct() + +struct MorGenerator + id::String + label::Vector{String} + morType::MorType + dom::ObType + cod::ObType +end +StructTypes.StructType(::Type{MorGenerator}) = StructTypes.Struct() + +struct Diagram + obGenerators::Vector{DiagramObGenerator} + morGenerators::Vector{DiagramMorGenerator} +end +StructTypes.StructType(::Type{Diagram}) = StructTypes.Struct() + +struct Model + obGenerators::Vector{ObGenerator} + morGenerators::Vector{MorGenerator} +end +StructTypes.StructType(::Type{Model}) = StructTypes.Struct() + + +struct ModelDiagram + model::Model + diagram::Diagram +end +StructTypes.StructType(::Type{ModelDiagram}) = StructTypes.Struct() + +end # module diff --git a/packages/algjulia-interop/src/decapodes-service/DecapodesService.jl b/packages/algjulia-interop/src/decapodes-service/DecapodesService.jl deleted file mode 100644 index 1539cbbfb..000000000 --- a/packages/algjulia-interop/src/decapodes-service/DecapodesService.jl +++ /dev/null @@ -1,42 +0,0 @@ -module DecapodesService - -# algebraicjulia dependencies -using ACSets -using DiagrammaticEquations -using Decapodes -using CombinatorialSpaces - -# dependencies -import JSON3 -using StaticArrays -using MLStyle -using LinearAlgebra -using ComponentArrays -using Distributions # for initial conditions - -# meshing -using CoordRefSystems -using GeometryBasics: Point2, Point3 -Point3D = Point3{Float64}; - -# simulation -using OrdinaryDiffEq - -using ..CatColabInterop -using ..CatColabInterop: AlgebraicJuliaIntegration, AbstractDiagram, AbstractAnalysis -import ..CatColabInterop: Model, to_model - -# necessary to export -export infer_types!, evalsim, default_dec_generate, default_dec_matrix_generate, - DiagonalHodge, ComponentArray - -struct ThDecapode <: AlgebraicJuliaIntegration end -export ThDecapode - -# funcitons for geometry and initial conditions -include("geometry.jl") -include("model.jl") ## model-building -include("diagram.jl") ## diagram-building -include("analysis/Analysis.jl") - -end diff --git a/packages/algjulia-interop/src/decapodes-service/analysis/Analysis.jl b/packages/algjulia-interop/src/decapodes-service/analysis/Analysis.jl deleted file mode 100644 index af3f267a3..000000000 --- a/packages/algjulia-interop/src/decapodes-service/analysis/Analysis.jl +++ /dev/null @@ -1,3 +0,0 @@ -include("ns_helper.jl") -include("initial_conditions.jl") -include("simulation.jl") diff --git a/packages/algjulia-interop/src/decapodes-service/analysis/initial_conditions.jl b/packages/algjulia-interop/src/decapodes-service/analysis/initial_conditions.jl deleted file mode 100644 index 29ce151f6..000000000 --- a/packages/algjulia-interop/src/decapodes-service/analysis/initial_conditions.jl +++ /dev/null @@ -1,101 +0,0 @@ -## INITIAL CONDITIONS - -# This ADT defines the parameters for initial conditions data. -@data InitialConditionsData begin - GaussianData(μ::Vector{Float64}, Σ::Diagonal{Float64, Vector{Float64}}) - TaylorVortexData(lat::Float64, vortices::Int, p::AbstractVortexParams) -end - -function GaussianData(μ::Vector{Float64}, Σ::Vector{Float64}) - GaussianData(μ, LinearAlgebra.Diagonal(abs.(Σ))) -end - -# default method -function GaussianData(r::Rectangle) - μ = middle(r) - GaussianData(μ, μ/10) -end - -""" Normal distribution should understand GaussianData """ -Distributions.MvNormal(ξ::GaussianData) = MvNormal(ξ.μ, ξ.Σ) - -TaylorVortexData() = TaylorVortexData(0.2, 2, TaylorVortexParams(0.5, 0.1)) - -#= -This IC contains the domain and the initial conditions data. - -While these are currently tightly-interlinked with InitialConditionsData, they are formally separated to distinguish between the initial conditions schema and the data it might be parameterized over. -=# -@data InitialConditions begin - # planar - GaussianIC(r::Rectangle, ξ::GaussianData) - # spherical - TaylorVortexIC(d::Sphere, ξ::TaylorVortexData) - SixVortexIC(m::Sphere, data::Any) -end - -# DEFAULT METHOD -GaussianIC(r::Rectangle) = GaussianIC(r, GaussianData(r)) -TaylorVortexIC(d::Sphere) = TaylorVortexIC(d, TaylorVortexData()) - -function initial_conditions(ic_specs::AbstractDict, geometry::Geometry, uuid2symb::Dict{String, Symbol}) - dict = Dict([uuid2symb[string(uuid)] => ic_specs[string(uuid)] for uuid ∈ keys(ic_specs)]...) - initial_conditions(dict, geometry) # the resulting sim will only have (C,) as initial conditions -end - -""" Takes a string, a domain, and a mesh and returns the initial conditios object associated to it. - -Example: -``` -associate("TaylorVortex", Sphere(6, 1.0), sd) == TaylorVortexIC(Sphere(6, 1.0), sd) -``` -""" -function associate(str::String, geometry::Geometry) - @match str begin - "Gaussian" => GaussianIC(geometry.domain) - "TaylorVortex" => TaylorVortexIC(geometry.domain) - _ => error("$str is not implemented") - end -end - -""" Methods for this function implement initial conditions for their given schema. There are also helper functions.""" -function initial_conditions end -export initial_conditions - -""" associates the values in a dictionary to their initial condition flags, and passes the output to initial_conditions -""" -function initial_conditions(ics::Dict{Symbol, String}, geometry::Geometry) - ic_dict = Dict([var => associate(ics[var], geometry) for var in keys(ics)]...) - # Now we have a mapping between variables and their initial condition specs. - initial_conditions(ic_dict, geometry) -end - -""" builds a mapping between symbols and their initial conditions """ -function initial_conditions(ics::Dict{Symbol,<:InitialConditions}, geometry::Geometry) - u0 = ComponentArray(; Dict([ - var => initial_conditions(ics[var], geometry) for var ∈ keys(ics) - ])...) - return u0 -end - -function initial_conditions(ics::GaussianIC, geometry::Geometry) - c_dist = MvNormal(ics.ξ) - c = [pdf(c_dist, [p[1], p[2]]) for p ∈ geometry.dualmesh[:point]] - return c -end - -function vort_ring(ics::TaylorVortexIC, geometry::Geometry) - vort_ring(ics.d, ics.ξ.lat, ics.ξ.vortices, ics.ξ.p, geometry.dualmesh, taylor_vortex) -end - -function initial_conditions(ics::TaylorVortexIC, geometry::Geometry) - # TODO prefer not to load `s0` here but che sara sara - s0 = dec_hodge_star(0, geometry.dualmesh, GeometricHodge()) - X = vort_ring(ics, geometry) - du = s0 * X - return du -end - -function initial_conditions(ics::SixVortexIC, geometry::Geometry) - X = vort_ring(0.4, 6, PointVortexParams(3.0, 0.15), point_vortex) -end diff --git a/packages/algjulia-interop/src/decapodes-service/analysis/ns_helper.jl b/packages/algjulia-interop/src/decapodes-service/analysis/ns_helper.jl deleted file mode 100644 index b74e579a0..000000000 --- a/packages/algjulia-interop/src/decapodes-service/analysis/ns_helper.jl +++ /dev/null @@ -1,87 +0,0 @@ -### -#This code was lifted from the Navier-Stokes simulation `ns.jl` in the Decapodes docs page, originally authored by Luke Morris -### -abstract type AbstractVortexParams end - -struct TaylorVortexParams <: AbstractVortexParams - G::Real - a::Real -end - -struct PointVortexParams <: AbstractVortexParams - τ::Real - a::Real -end - -""" function ring_centers(lat, n) - -Find n equispaced points at the given latitude. -""" -function ring_centers(lat, n, radius=1.0) - ϕs = range(0.0, 2π; length=n+1)[1:n] - map(ϕs) do ϕ - v_sph = Spherical(radius, lat, ϕ) - v_crt = convert(Cartesian, v_sph) - Point3D(v_crt.x.val, v_crt.y.val, v_crt.z.val) - end -end - -""" function great_circle_dist(pnt,G,a,cntr) - -Compute the length of the shortest path along a sphere, given Cartesian coordinates. -""" -function great_circle_dist(radius::Float64, pnt1::Point3D, pnt2::Point3D) - radius * acos(dot(pnt1,pnt2)) -end - -function taylor_vortex(sd::HasDeltaSet, radius::Float64, cntr::Point3D, p::TaylorVortexParams) - map(x -> taylor_vortex(x, radius, cntr, p), point(sd)) -end - -""" function taylor_vortex(pnt::Point3D, cntr::Point3D, p::TaylorVortexParams) - -Compute the value of a Taylor vortex at the given point. -""" -function taylor_vortex(pnt::Point3D, radius::Float64, cntr::Point3D, p::TaylorVortexParams) - gcd = great_circle_dist(radius, pnt, cntr) - (p.G/p.a) * (2 - (gcd/p.a)^2) * exp(0.5 * (1 - (gcd/p.a)^2)) -end - -""" function vort_ring(lat, n_vorts, p::T, formula) where {T<:AbstractVortexParams} - -Compute vorticity as primal 0-forms for a ring of vortices. - -Specify the latitude, number of vortices, and a formula for computing vortex strength centered at a point. -""" -function vort_ring(d::Sphere, lat, n_vorts, p::T, sd, formula) where {T<:AbstractVortexParams} - sum(map(x -> formula(sd, d.radius, x, p), ring_centers(lat, n_vorts, d.radius))) -end - -""" function vort_ring(lat, n_vorts, p::PointVortexParams, formula) - -Compute vorticity as primal 0-forms for a ring of vortices. - -Specify the latitude, number of vortices, and a formula for computing vortex strength centered at a point. - -Additionally, place a counter-balance vortex at the South Pole such that the integral of vorticity is 0. -""" -function vort_ring(radius, lat, n_vorts, p::PointVortexParams, formula) - Xs = sum(map(x -> formula(radius, sd, x, p), ring_centers(lat, n_vorts))) - Xsp = point_vortex(sd, Point3D(0.0, 0.0, -1.0), PointVortexParams(-1*n_vorts*p.τ, p.a)) - Xs + Xsp -end - - - - - - -""" function point_vortex(pnt::Point3D, cntr::Point3D, p::PointVortexParams) - -Compute the value of a smoothed point vortex at the given point. -""" -function point_vortex(pnt::Point3D, cntr::Point3D, p::PointVortexParams) - gcd = great_circle_dist(pnt,cntr) - p.τ / (cosh(3gcd/p.a)^2) -end - diff --git a/packages/algjulia-interop/src/decapodes-service/analysis/simulation.jl b/packages/algjulia-interop/src/decapodes-service/analysis/simulation.jl deleted file mode 100644 index 044a261d8..000000000 --- a/packages/algjulia-interop/src/decapodes-service/analysis/simulation.jl +++ /dev/null @@ -1,161 +0,0 @@ -""" Constructs an analysis from the diagram of a Decapode Model""" -function Analysis(analysis::JSON3.Object, diagram::DecapodeDiagram, hodge=GeometricHodge()) - - # TODO want a safer way to get this information - id = findfirst(cell -> haskey(cell, :content), analysis[:notebook][:cells]) - content = analysis[:notebook][:cells][id][:content][:content] - - PodeSystem(content, diagram, hodge) -end -export Analysis - -# accepts payload -function Analysis(::ThDecapode, payload::String, args...) - analysis = JSON3.read(payload) - Analysis(ThDecapode(), analysis) -end - -function Analysis(::ThDecapode, analysis::JSON3.Object, args...) - model = Model(ThDecapode(), analysis.model) - diagram = Diagram(analysis.diagram, model) - PodeSystem(analysis, diagram, args...) -end - -struct PodeSystem <: AbstractAnalysis{ThDecapode} - pode::SummationDecapode - plotVars::Dict{String, Bool} - scalars::Dict{Symbol, Any} # closures - geometry::Geometry - init::ComponentArray - generate::Any - uuiddict::Dict{Symbol, String} - duration::Int -end -export PodeSystem - -function Base.show(io::IO, system::PodeSystem) - println(io, system.pode) -end - -# the origin is the SimulationData payload -function PodeSystem(content::JSON3.Object, diagram::DecapodeDiagram, hodge=GeometricHodge()) - - domain = content[:domain] - duration = content[:duration] - initialConditions = content[:initialConditions] - mesh = content[:mesh] - # TODO we need a more principled way of defining this - plotVars = @match content[:plotVariables] begin - vars::AbstractArray => Dict{String, Bool}([ k => k ∈ vars for k in keys(diagram.vars)]) - vars => Dict{String, Bool}([ "$k" => v for (k,v) in vars]) - end - scalars = content[:scalars] - anons = Dict{Symbol, Any}() - - dot_rename!(diagram.pode) - uuid2symb = uuid_to_symb(diagram.pode, diagram.vars) - - geometry = Geometry(content) - - ♭♯_m = ♭♯_mat(geometry.dualmesh) - wedge_dp10 = dec_wedge_product_dp(Tuple{1,0}, geometry.dualmesh) - dual_d1_m = dec_dual_derivative(1, geometry.dualmesh) - star0_inv_m = dec_inv_hodge_star(0, geometry.dualmesh, hodge) - Δ0 = Δ(0,geometry.dualmesh) - #fΔ0 = factorize(Δ0); - function sys_generate(s, my_symbol) - op = @match my_symbol begin - sym && if haskey(diagram.scalars, sym) end => x -> begin - k = scalars[diagram.scalars[sym]] - k * x - end - :♭♯ => x -> ♭♯_m * x - # TODO are we indexing right? - :dpsw => x -> wedge_dp10(x, star0_inv_m*(dual_d1_m*x)) - :Δ⁻¹ => x -> begin - y = Δ0 \ x - y .- minimum(y) - end - _ => default_dec_matrix_generate(s, my_symbol, hodge) - end - return (args...) -> op(args...) - end - - u0 = initial_conditions(initialConditions, geometry, uuid2symb) - - # reversing `uuid2symb` into `symbol => uuid.` we need this to reassociate the var to its UUID - symb2uuid = Dict([v => k for (k,v) in pairs(uuid2symb)]) - - # TODO return the whole system - return PodeSystem(diagram.pode, plotVars, anons, geometry, u0, sys_generate, symb2uuid, duration) -end - -points(system::PodeSystem) = collect(values(system.geometry.dualmesh.subparts.point.m)) -indexing_bounds(system::PodeSystem) = indexing_bounds(system.geometry.domain) - -function run_sim(fm, u0, t0, constparam) - prob = ODEProblem(fm, u0, (0, t0), constparam) - soln = solve(prob, Tsit5(), saveat=0.01) -end -export run_sim - -struct SimResult - time::Vector{Float64} - state::Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - x::Vector{Float64} # axis - y::Vector{Float64} -end -export SimResult - -function SimResult(soln::ODESolution, system::PodeSystem) - idx_bounds = indexing_bounds(system) - state_val_dict = variables_state(soln, system) # Dict("UUID1" => VectorMatrixSVectr...) - SimResult(soln.t, state_val_dict, 0:idx_bounds.x, 0:idx_bounds.y) -end -# TODO generalize to HasDeltaSet - -""" for the variables in a system, associate them to their state values over the duration of the simulation """ -function variables_state(soln::ODESolution, system::PodeSystem) - plottedVars = [ k for (k, v) in system.plotVars if v == true ] - uuid2symb = Dict([ v => k for (k, v) in system.uuiddict]) # TODO why reverse again? - Dict([ String(uuid2symb[var]) => state_entire_sim(soln, system, uuid2symb[var]) for var ∈ plottedVars ]) -end - -""" given a simulation, a domain, and a variable, gets the state values over the duration of a simulation. -Called by `variables_state`[@ref] """ -function state_entire_sim(soln::ODESolution, system::PodeSystem, var::Symbol) - map(1:length(soln.t)) do i - state_at_time(soln, system, var, i) - end -end - -# TODO type `points` -function state_at_time(soln::ODESolution, system::PodeSystem, plotvar::Symbol, t::Int) - @match system.geometry.domain begin - # TODO check time indexing here - domain::Rectangle => state_at_time(soln, domain, plotvar, t) - domain::Sphere => state_at_time(soln, domain, plotvar, t, points(system)) - _ => throw(ImplError("state_at_time function for domain $domain")) - end -end - -function state_at_time(soln::ODESolution, domain::Rectangle, var::Symbol, t::Int) - (x, y) = indexing_bounds(domain) - [SVector(i, j, getproperty(soln.u[t], var)[(x+1)*(i-1) + j]) for i in 1:x+1, j in 1:y+1] -end - -# TODO just separated this from the SimResult function and added type parameters, but need to generalize -function grid(pt3::Point3, grid_size::Vector{Int}) - pt2 = [(pt3[1]+1)/2, (pt3[2]+1)/2] - [round(Int, pt2[1]*grid_size[1]), round(Int, pt2[2]*grid_size[2])] -end - -function state_at_time(soln::ODESolution, domain::Sphere, var::Symbol, t::Int, points) - l , _ = indexing_bounds(domain) # TODO this is hardcoded to return 100, 100 - northern_indices = filter(i -> points[i][3] > 0, keys(points)) - map(northern_indices) do n - i, j = grid(points[n], [l, l]) # TODO - SVector(i, j, getproperty(soln.u[t], var)[n]) - end -end - diff --git a/packages/algjulia-interop/src/decapodes-service/diagram.jl b/packages/algjulia-interop/src/decapodes-service/diagram.jl deleted file mode 100644 index fee454d4e..000000000 --- a/packages/algjulia-interop/src/decapodes-service/diagram.jl +++ /dev/null @@ -1,113 +0,0 @@ -## DIAGRAM BUILDING - - -@kwdef mutable struct DecapodeDiagram <: AbstractDiagram{ThDecapode} - pode::SummationDecapode = SummationDecapode(parse_decapode(quote end)) - scalars::Dict{Symbol, String} = Dict{Symbol, String}() - vars::Dict{String, Int} = Dict{String, Int}() - nc::Dict{Int, String} = Dict{Int, String}() -end - -function Base.nameof(model::Model, content::AbstractDict) - if isnothing(content[:over]) - :no_name - else - Symbol(model.data[content[:over][:content]].name) - end -end - -# endpoint being `dom` or `codom` -function check_endpoint!(diagram::DecapodeDiagram, endpoint) - if haskey(diagram.vars, endpoint) - diagram.vars[endpoint] - else - if endpoint ∉ values(diagram.nc) - id = isempty(keys(diagram.nc)) ? 1 : length(keys(diagram.nc)) + 1 - name = Symbol("•$id") - acset_id = add_part!(diagram.pode, :Var, name=name, type=:infer) - push!(diagram.nc, acset_id => endpoint) - acset_id - else - out = filter(x -> x[2] == endpoint, pairs(diagram.nc)) - first(keys(out)) - end - end -end - -function add_to_pode!(diagram::DecapodeDiagram, - model::Any, - content::AbstractDict, - ::ObTag) - # indexes the model by UUID - model_element = model.data[content[:over][:content]] - # checks if the cell is an anonymous (intermediate) variable. - # if so, we increment the intermediate variable counter and make an intermediate variable name. - # otherwise we use the existing name of the given content. - name = if isempty(content[:name]) - id = isempty(keys(diagram.nc)) ? 1 : maximum(keys(diagram.nc)) + 1 - push!(diagram.nc, id => "") - Symbol("•$id") - else - Symbol(content[:name]) - end - id = add_part!(diagram.pode, :Var, name=name, type=nameof(model_element)) - push!(diagram.vars, content[:id] => id) - return diagram -end -export add_to_pode! - -# TODO we are restricted to Op1 -function add_to_pode!(diagram::DecapodeDiagram, - model::Model{ThDecapode}, - content::AbstractDict, - ::HomTag) - dom = content[:dom][:content] - cod = content[:cod][:content] - - # TODO Simpler to extend the Decapodes Var table by a UUID attribute - dom_id = check_endpoint!(diagram, dom) - cod_id = check_endpoint!(diagram, cod) - - # get the name of the Op1 and add it to the model - op1 = nameof(model, content) - - add_part!(diagram.pode, :Op1, src=dom_id, tgt=cod_id, op1=op1) - # we need to add an inclusion to the TVar table - if op1 == :∂ₜ - add_part!(diagram.pode, :TVar, incl=cod_id) - end - if content[:morType][:content] isa JSON3.Object - scalar = model.data[content[:over][:content]].name - push!(diagram.scalars, scalar => content[:over][:content]) - end - diagram -end - -""" Diagram(diagram::AbstractVector{<:AbstractDict}, model::Model{ThDecapode}) => (::SummationDecapode, ::Dict{Symbol, Any}, ::Dict{String, Int}) - -This returns - 1. a Decapode - 2. a dictionary of symbols mapped to anonymous functions - 3. a dictionary of JSON UUIDs mapped to symbols -""" -function Diagram(json_array::JSON3.Array{T}, model::Model{ThDecapode}; scalars=[]) where T - diagram = DecapodeDiagram() - for cell in json_array - cell = haskey(cell, :content) ? cell[:content] : cell - @match cell begin - content && if haskey(content, :obType) end => add_to_pode!(diagram, model, content, ObTag()) - content && if haskey(content, :morType) end => add_to_pode!(diagram, model, content, HomTag()) - _ => throw(ImplError(cell)) - end - end - return diagram -end -export Diagram - -function Diagram(json_diagram::JSON3.Object, model::Model{ThDecapode}; scalars=[]) - Diagram(json_diagram[:cells], model; scalars) -end - -function uuid_to_symb(decapode::SummationDecapode, vars::Dict{String, Int}) - Dict([key => (subpart(decapode, vars[key], :name)) for key ∈ keys(vars)]) -end diff --git a/packages/algjulia-interop/src/decapodes-service/geometry.jl b/packages/algjulia-interop/src/decapodes-service/geometry.jl deleted file mode 100644 index addb0201c..000000000 --- a/packages/algjulia-interop/src/decapodes-service/geometry.jl +++ /dev/null @@ -1,120 +0,0 @@ -## INTEROP - -""" Supported domains. """ -const domain_names = [:Plane, :Sphere] - -""" Mapping from supported domains to meshes for the domain. """ -const mesh_names = Dict( - :Plane => [:Rectangle, :Periodic], - :Sphere => [:Icosphere6, :Icosphere7, :Icosphere8, :UV], -) - -""" Mapping from supported domains to initial/boundary conditions. """ -const initial_condition_names = Dict( - :Plane => [:Gaussian], - :Sphere => [:TaylorVortex, :SixVortex], -) - -""" Supported geometries, in the JSON format expected by the frontend. """ -function supported_decapodes_geometries() - domains = map(domain_names) do domain - Dict( - :name => domain, - :meshes => mesh_names[domain], - :initialConditions => initial_condition_names[domain], - ) - end - Dict(:domains => domains) -end -export supported_decapodes_geometries - -## DOMAINS - -abstract type Domain end - -# meshes associated with Planes -@data Planar <: Domain begin - Rectangle(max_x::Int, max_y::Int, dx::Float64, dy::Float64) - Periodic # TODO -end - -# rectangle methods - -# TODO it is semantically better to case to Point2? -middle(r::Rectangle) = [r.max_x/2, r.max_y/2] - -function indexing_bounds(r::Rectangle) - (x=floor(Int, r.max_x/r.dx), y=floor(Int, r.max_y/r.dy)) -end - -# meshes associated with Spheres -@data Spheric <: Domain begin - Sphere(dim::Int, radius::Float64) - UV(minlat::Int, maxlat::Int, dlat::Float64, minlong::Int, maxlong::Int, dlong::Float64, radius::Float64) -end - -# default -Sphere(dim) = Sphere(dim, 1.0) - -# TODO XXX hardcoded alert! -function indexing_bounds(m::Sphere) - (x=100, y=100) -end - -""" helper function for UV """ -function makeSphere(m::UV) - makeSphere(m.minlat, m.maxlat, m.dlat, m.minlong, m.maxlong, m.dlong, m.radius) -end - -## GEOMETRY - -struct Geometry - domain::Domain - dualmesh::HasDeltaSet -end - -function Base.show(io::IO, g::Geometry) - println(io, g.domain) -end - -function Geometry(json_object::AbstractDict) - mesh_name = Symbol(json_object[:mesh]) - domain = PREDEFINED_MESHES[mesh_name] - Geometry(domain) -end - -# function Geometry(d::Domain, args...) -# throw(ImplError("The mesh ($(d)) is")) -# end - -function Geometry(r::Rectangle, division::SimplexCenter=Circumcenter()) - s = triangulated_grid(r.max_x, r.max_y, r.dx, r.dy, Point2{Float64}) - sd = EmbeddedDeltaDualComplex2D{Bool, Float64, Point2{Float64}}(s) - subdivide_duals!(sd, division) - Geometry(r, sd) -end - -# function Geometry(r::Periodic, division::SimplexCenter=Circumcenter()) end - -function Geometry(m::Sphere, division::SimplexCenter=Circumcenter()) - s = loadmesh(Icosphere(m.dim, m.radius)) - sd = EmbeddedDeltaDualComplex2D{Bool, Float64, Point3{Float64}}(s) - subdivide_duals!(sd, division) - Geometry(m, sd) -end - -function Geometry(m::UV, division::SimplexCenter=Circumcenter()) - s, _, _ = makeSphere(m) - sd = EmbeddedDeltaDualComplex2D{Bool, Float64, Point3{Float64}}(s) - subdivide_duals!(sd, division) - Geometry(m, sd) -end - -## Prefined meshes - -const PREDEFINED_MESHES = Dict( - :Rectangle => Rectangle(100, 100, 2, 2), - :Icosphere6 => Sphere(6, 1.0), - :Icosphere7 => Sphere(7, 1.0), - :Icosphere8 => Sphere(8, 1.0), - :UV => UV(0, 180, 2.5, 0, 360, 2.5, 1.0)) diff --git a/packages/algjulia-interop/src/decapodes-service/model.jl b/packages/algjulia-interop/src/decapodes-service/model.jl deleted file mode 100644 index e1b4bb0c3..000000000 --- a/packages/algjulia-interop/src/decapodes-service/model.jl +++ /dev/null @@ -1,107 +0,0 @@ -# Build the model - -export Model - -""" -A model for the Decapodes integration is the same as the default Model method. -A dictionary mapping UUID strings with ModelElements is instantiated. -""" -Model(::ThDecapode) = Model{ThDecapode}(Dict{String, ModelElement}()) - -""" Helper function to convert CatColab values (Obs) in Decapodes """ -function to_model(model::ThDecapode, type::ObTag, name::String) - @match lowercase(name) begin - "0-form" => :Form0 - "1-form" => :Form1 - "2-form" => :Form2 - "primal 0-form" => :Form0 - "primal 1-form" => :Form1 - "primal 2-form" => :Form2 - "dual 0-form" => :DualForm0 - "dual 1-form" => :DualForm1 - "dual 2-form" => :DualForm2 - x => throw(ImplError(x)) - end -end - -""" Helper function to convert CatColab values (Homs) in Decapodes """ -function to_model(model::ThDecapode, type::HomTag, name::String) - @match replace(name," " => "") begin - "∂t" || "∂ₜ" => :∂ₜ - "Δ" => :Δ - "Δ⁻¹" => :Δ⁻¹ - "d*" || "d̃₁" => :dual_d₁ - "⋆" || "⋆₁" || "★₁" || "★1" => :⋆₁ - "⋆⁻¹" || "⋆₀⁻¹" => :⋆₀⁻¹ - "★" || "★⁻¹" => :⋆₁ - "d" || "d₀" || "d01" => :d₀ - "d12" => :d₁ - "⋆2" => :⋆₂ - "♭♯" => :♭♯ - "lamb" => :dpsw # dual-primal self-wedge - "-" => :neg - x => throw(ImplError(x)) - end -end - -# add_to_model! - -@active IsMorphismNonScalar(x) begin - x[:morType][:content] == "Nonscalar" ? Some(x) : nothing -end - -function add_to_model! end -export add_to_model! - -function add_to_model!(model::Model{ThDecapode}, content::AbstractDict, type::ObTag) - push!(model.data, content[:id] => ModelElement(;name=to_model(ThDecapode(), type, content[:name]))) -end - -function add_to_model!(model::Model{ThDecapode}, content::AbstractDict, type::HomTag) - @match content begin - IsMorphismNonScalar(x) => push!(model.data, content[:id] => - ModelElement(;name=to_model(ThDecapode(), type, content[:name]), - val=HomValue(content[:dom][:content], - content[:cod][:content]))) - _ => push!(model.data, content[:id] => - ModelElement(;name=Symbol(content[:name]), - val=HomValue(content[:dom][:content], - content[:cod][:content]))) - end -end - -# TODO generalize -function Model(::ThDecapode, path::String) - json = JSON3.read(read(path, String)) - Model(ThDecapode(), json) -end - -# for each cell, if it is... -# ...an object, we convert its type to a symbol and add it to the modeldict -# ...a morphism, we add it to the modeldict with a field for the ids of its -# domain and codomain to its -function Model(::ThDecapode, json_model::JSON3.Object) # AbstractDict is the JSON - newmodel = Model(ThDecapode()) - __name = json_model[:name] # TODO unused - for cell in json_model[:notebook][:cells] - @match cell begin - IsObject(content) => add_to_model!(newmodel, content, ObTag()) - IsMorphism(content) => add_to_model!(newmodel, content, HomTag()) - _ => throw(ImplError(cell)) - end - end - return newmodel -end -export Model - -function Model(::ThDecapode, json_array::JSON3.Array{T}; name="model") where T - newmodel = Model(ThDecapode()) - for cell in json_array - @match cell begin - content && if haskey(content, :obType) end => add_to_model!(newmodel, content, ObTag()) - content && if haskey(content, :morType) end => add_to_model!(newmodel, content, HomTag()) - _ => throw(ImplError(cell)) - end - end - return newmodel -end diff --git a/packages/algjulia-interop/src/kernel_management.jl b/packages/algjulia-interop/src/kernel_management.jl deleted file mode 100644 index c658ddb89..000000000 --- a/packages/algjulia-interop/src/kernel_management.jl +++ /dev/null @@ -1,256 +0,0 @@ -using IJulia -using Preferences -import REPL -using REPL.TerminalMenus -using MLStyle - -struct KernelNotFoundException <: Exception - dir::String -end - -KernelNotFoundException() = KernelNotFoundException(IJulia.kerneldir()) - -function Base.showerror(io::IO, err::KernelNotFoundException) - print(io, """ - IJulia cannot find any kernels in the directory `$(err.dir)`. - - To install a kernel, you may run `CatColabInterop.install_ccl_kernel()`. - Refer to the [IJulia documentation](https://julialang.github.io/IJulia.jl/stable/library/public/#IJulia.installkernel) - for more information about managing Jupyter kernels in IJulia. - - If you wish to install a sysimage instead, run - ```julia - using PackageCompiler - install_ccl_kernel(Val(:sysimge)) - ``` - """) -end - -const YESNO = ["Yes", "No"] - -const MODES = Dict("dev" => "http://localhost:5173", - "staging" => "https://next.catcolab.org", - "production" => "https://catcolab.org") - -@kwdef mutable struct ServerConfig - sysimg_path::Union{String, Nothing} = nothing - kernels::Vector{String} = readdir(IJulia.kerneldir(), join=true) - kernel::Union{String, Nothing} = @load_preference("kernel", nothing) - modes::Dict{String, String} = MODES - mode::String = @load_preference("mode", "production") - limit::Int = 1e9 - server::Union{Base.Process, Nothing} = nothing -end - -const CONFIG::ServerConfig = ServerConfig() -export CONFIG - -function origin(s::ServerConfig) - s.modes[s.mode] -end - -function Base.show(io::IO, config::ServerConfig) - kernel = !isnothing(config.kernel) ? config.kernel : "No kernel selected" - status = !isnothing(config.server) ? "Running" : "Not running." - s = """ - Current kernel: $kernel - Server: $status - Origin: $(origin(config)) - """ - print(io, s) -end - -function set_mode!(config::ServerConfig, mode::String) - if mode ∈ collect(keys(config.modes)) - config.mode = mode - @info """"$mode" set!""" - else - error("""Your selection "$mode" is not a valid mode. Please choose from $(join(config.modes, ", ", " or "))""") - end -end - -function change_mode!(prefer::Bool=true; config::ServerConfig=CONFIG) - modes = collect(keys(config.modes)) - menu = RadioMenu(modes, pagesize=3) - cursor = something(findfirst(==(config.mode), modes), 0) - choice = request("Select a mode: ", menu; cursor = cursor) - if choice != -1 - config.mode = modes[choice] - if prefer - @set_preferences!("mode" => modes[choice]) - @info "Preferred mode set to $(modes[choice])" - end - Ok("""Mode "$(config.mode)" chosen.""") - else - Err("Mode selection canceled") - end -end -export change_mode! - -function change_kernel!(prefer::Bool=true; config::ServerConfig=CONFIG) - menu = RadioMenu(config.kernels, pagesize=4) - cursor = something(findfirst(==(config.kernel), config.kernels), 0) - choice = request("Select a kernel: ", menu; cursor=cursor) - if choice != -1 - config.kernel = config.kernels[choice] - if prefer - @set_preferences!("kernel" => config.kernel) - @info "Preferred kernel set to $(config.kernels[choice])" - end - Ok("Kernel $(config.kernel) chosen.") - else - Err("Kernel selection canceled") - end -end -export change_kernel! - -""" load_kernels() - -Loads kernels visible to IJulia's [kernel_dir](@ref IJulia.kerneldir) function. -""" -function load_kernels!(;config::ServerConfig=CONFIG, warn=false) - dir = IJulia.kerneldir() - kernels = readdir(dir, join=true) - if !isempty(kernels) - config.kernels = kernels - return Ok("Kernels reloaded!") - end - # otherwise, throw a warning or an error - warn ? @warn(sprint(showerror, KernelNotFoundException(dir))) : throw(KernelNotFoundException(dir)) -end - -""" uninstall_kernel!(;config::ServerConfig=CONFIG)::Union{Nothing, Bool} - -Wraps `Base.rm` in a terminal menu interface to uninstall Julia kernels. Using `Base.rm` is recommended by IJulia. - -Usage: -``` -uninstall_kernel!() -``` -""" -function uninstall_kernel!(;config::ServerConfig=CONFIG) - isempty(config.kernels) && throw(KernelNotFoundException()) - menu = MultiSelectMenu(config.kernels, pagesize=4) - cursor = something(findfirst(==(config.kernel), config.kernels), 0) - choices = request("Select a kernel to be uninstalled: ", menu; cursor=cursor) - if !isempty(choices) - selections = getindex(config.kernels, collect(choices)) - confirm = RadioMenu(YESNO, pagesize=2) - permission = request("Kernel(s) will be uninstalled from your machine. Continue?", confirm) - if YESNO[permission] == "Yes" - for selection in selections - isdir(selection) && rm(selection; recursive=true) - @info selection isdir(selection) "Removed!" - end - preferred = @load_preference("kernel", nothing) - if preferred ∈ selections - @delete_preferences!("kernel") - @info "Preferred kernel $preferred was removed." - end - load_kernels!(;config=config, warn=true) - Ok() - else - Err("Kernel uninstallation cancelled.") - end - Ok("Kernel deletion successful.") - else - Err("Kernel uninstallation cancelled") - end -end -export uninstall_kernel! - - -""" install_ccl_kernel!() - -This calls IJulia to install a kernel `CatColabInteropKernel` in the current project directory. - -To build a sysimage, load the `SysImageExt` package extension by loading `PackageCompiler.jl`. This adds an additional method to `install_ccl_kernel!` which builds the sysimg. - -You can see installed kernels visible to IJulia by running `change_kernel!()`. - -Usage: - -For building an IJulia kernel -``` -using CatColabInterop -install_ccl_kernel!() -``` -For building the sysimg: -``` -using CatColabInterop -using PackageCompiler # loads Julia extension for building the sysimage -install_ccl_kernel!(Val(:sysimg)) -``` -""" -function install_ccl_kernel!(;config::ServerConfig=CONFIG, kwargs...) - kernel = installkernel("CatColabInteropKernel", "--project=@.", kwargs...) - load_kernels!(config=config) - preferred = @load_preference("kernel", nothing) - if isnothing(preferred) || length(config.kernels) == 1 - @set_preferences!("kernel" => kernel) - @info "Preferred kernel set to $(kernel)" - end -end -export install_ccl_kernel! - -function build_jupyter_server_cmd(args::Dict{String, Any}) - return ` - jupyter server \ - --IdentityProvider.token="" \ - --ServerApp.disable_check_xsrf=True \ - --ServerApp.allow_origin="$(args["mode"])" \ - --ServerApp.allow_credentials=True \ - --ServerApp.iopub_data_rate_limit=$(args["limit"]) \ - --MultiKernelManager.default_kernel_name="$(basename(args["kernel"]))" - ` -end - -function build_jupyter_server_cmd(config::ServerConfig) - build_jupyter_server_cmd(Dict{String, Any}("limit" => config.limit, "kernel" => config.kernel, "mode" => origin(config))) -end - -""" start_server(;config::ServerConfig=CONFIG, mode::Union{String, Nothing}=nothing, manual=false) - -This starts a Jupyter server with an optional kernel and mode. - -The **mode** is the origin for the Jupyter server. Eligible values are "dev", "staging", and "production". - -The available kernels can be checked by running `jupyter-server kernelspec list` from the command line or `;jupyter-server kernelspec list` from the REPL. - -## Usage: - -```julia -start_server!() -# do stuff -stop_server!() -``` -To select the kernel and mode in a wizard-like interface, -```julia -start_server!(;manual=true) -``` -""" -function start_server!(;config::ServerConfig=CONFIG, mode::Union{String, Nothing}=nothing, manual=false) - if manual - change_kernel!(;config=config) | Err("Start server process aborted because kernel selection was cancelled.") - change_mode!(;config=config) | Err("Start server process aborted because mode selection was cancelled.") - end - if isnothing(config.kernel) - change_kernel!(;config=config) - end - if !isnothing(mode) - set_mode!(config, mode) - end - cmd = build_jupyter_server_cmd(config) - @info "Starting server: - kernel: $(config.kernel) - mode: $(origin(config))" - config.server = open(pipeline(cmd)) -end -export start_server! - -function stop_server!(;config::ServerConfig=CONFIG) - if !isnothing(config.server) - kill(config.server, Base.SIGTERM) - end -end -export stop_server! diff --git a/packages/algjulia-interop/src/kernel_support.jl b/packages/algjulia-interop/src/kernel_support.jl deleted file mode 100644 index 15bfde4da..000000000 --- a/packages/algjulia-interop/src/kernel_support.jl +++ /dev/null @@ -1,32 +0,0 @@ -import JSON3 - -export JsonValue - -# NOTE: JsonValue should not be used for returning large amounts of data (Anything over 1kb? -# Whatever the size is for "trivially readable by humans"), there is a catastrophic performance -# dropoff as payload size increases. Performance of JsonValue vs -# display(MIME"application/json"(), JSON3.write()) has not been studied in detail, both have bad -# performance, but one might be worse than the other. Whether or not the performance is different might -# help inform a future investigation. -# -# NOTE: the use of the `show` methods is the only way I was able to get the contents of the message -# (`content["data"]?.["application/json"]`) to be interpreted as JSON in the browser. using something -# like `display(MIME"application/json"(), JSON3.write(...))` caused the -# content to be the JSON in string form, even though the mime type was "application/json" -# -# NOTE: It looks like IJulia is delivering payloads for each mime type available according to this -# docstring https://github.com/JuliaLang/IJulia.jl/blob/master/src/display.jl -# -# NOTE: Jason is not 100% confident that these show methods do what it looks like they're doing. -# -# NOTE: Sometime the Jupyter server needs to be restarted. Do not trust performance tests are run twice -# back to back right after server startup. - -""" Container for an arbitrary JSON value. """ -struct JsonValue - value::Any -end - -function Base.show(io::IO, ::MIME"application/json", json::JsonValue) - JSON3.write(io, json.value) -end diff --git a/packages/algjulia-interop/src/result.jl b/packages/algjulia-interop/src/result.jl deleted file mode 100644 index 1178e2dd9..000000000 --- a/packages/algjulia-interop/src/result.jl +++ /dev/null @@ -1,23 +0,0 @@ -struct ResultException <: Exception - msg::String -end - -Base.showerror(io::IO, err::ResultException) = print(io, err.msg) - -@data Result begin - Ok(msg::String) - Err(msg::String) -end - -Ok() = Ok("") - -Base.show(io::IO, ok::Ok) = !isempty(ok.msg) ? print(io, ok.msg) : nothing -Base.show(io::IO, err::Err) = !isempty(err.msg) ? print(io, err.msg) : nothing - -import Base: | - -(|)(left::Ok, right) = handle(left) -(|)(left::Err, right) = handle(right) - -handle(ok::Ok) = ok -handle(err::Err) = throw(ResultException(err.msg)) diff --git a/packages/algjulia-interop/sysimage_precompile.jl b/packages/algjulia-interop/sysimage_precompile.jl deleted file mode 100755 index 2fb9f0d7b..000000000 --- a/packages/algjulia-interop/sysimage_precompile.jl +++ /dev/null @@ -1,2 +0,0 @@ -import CatColabInterop -include(joinpath(pkgdir(CatColabInterop), "test", "runtests.jl")) diff --git a/packages/algjulia-interop/test/Project.toml b/packages/algjulia-interop/test/Project.toml index afd8e968a..84cb3f020 100644 --- a/packages/algjulia-interop/test/Project.toml +++ b/packages/algjulia-interop/test/Project.toml @@ -1,13 +1,8 @@ [deps] ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8" CatColabInterop = "9ecda8fb-39ab-46a2-a496-7285fa6368c1" -CombinatorialSpaces = "b1c52339-7909-45ad-8b6a-6e388f7c67f2" -ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" -Decapodes = "679ab3ea-c928-4fe6-8d59-fd451142d391" -DiagrammaticEquations = "6f00c28b-6bed-4403-80fa-30e0dc12f317" +Catlab = "134e5e36-593f-5add-ad60-77f754baafbe" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078" -OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +Oxygen = "df9a0d86-3283-4920-82dc-4555fc0d1d8b" +StructTypes = "856f2bd8-1eba-4b0a-8007-ebc267875bd4" diff --git a/packages/algjulia-interop/test/TestCatlab.jl b/packages/algjulia-interop/test/TestCatlab.jl new file mode 100644 index 000000000..eeaf86682 --- /dev/null +++ b/packages/algjulia-interop/test/TestCatlab.jl @@ -0,0 +1,54 @@ +module TestCatlab + +using CatColabInterop, Catlab +using Catlab.CategoricalAlgebra.Pointwise.FunctorialDataMigrations.Yoneda: + colimit_representables +using HTTP, Test, Oxygen, JSON3 +const CatlabExt = Base.get_extension(CatColabInterop, :CatlabExt) + +# Example JSON +#------------- +body = read((@__DIR__)*"/data/diagrams/acset.json", String) + +# Parse the JSON +#--------------- +p = JSON3.read(body, ModelDiagram) + +# Convert to ACSet +#----------------- +schema, names = CatlabExt.model_to_schema(p.model) +acset_type = AnonACSet( + schema; type_assignment=Dict(a=>Nothing for a in schema.attrtypes)) +y = yoneda(constructor(acset_type)) +data = CatlabExt.diagram_to_data(p.diagram, names) +names, res = colimit_representables(data, y) + +S = acset_schema(res) + +# This is what we expect +#------------------------ +expected = acset_type +add_part!.(Ref(expected), [:X,:Y,:Z]) +expected[1, :f] = 1 +expected[1, :g] = AttrVar(1) + +@test is_isomorphic(res, expected) + +# Test final JSON output +#----------------------- +expected_json = Dict(:Z => ["z"],:f => ["y"],:X => ["x"],:Y => ["y"],:g => ["z"]) +@test expected_json == CatlabExt.acset_to_json(res, schema, CatlabExt.make_names(res, names)) + +# Optionally test the endpoint if running endpoint.jl: +# resp = HTTP.post("http://127.0.0.1:8080/acsetcolim"; body) +# @test resp.status == 200 + +# Test make_names on a more complicated example +#---------------------------------------------- +@present SchThree(FreeSchema) begin (A,B,C)::Ob; f::Hom(A,B); g::Hom(B,C) end +@acset_type T(SchThree) +exT = @acset T begin A=2; B=3; C=3; f=[2,3]; g=[2,3,2] end +names = (z=(:C, 1), y= (:B, 1), x = (:A, 1), x2 = (:A, 2)) +@test CatlabExt.make_names(exT, names) == Dict(:A=>["x","x2"], :B=>["y","f(x)","f(x2)"], :C=>["z","g(y)","g(f(x))"]) + +end # module diff --git a/packages/algjulia-interop/test/data/diagrams/acset.json b/packages/algjulia-interop/test/data/diagrams/acset.json new file mode 100644 index 000000000..ff637da03 --- /dev/null +++ b/packages/algjulia-interop/test/data/diagrams/acset.json @@ -0,0 +1,166 @@ +{ + "model": { + "obGenerators": [ + { + "id": "019a6042-1241-77bd-8055-bfea5c206bc7", + "label": [ + "X" + ], + "obType": { + "tag": "Basic", + "content": "Entity" + } + }, + { + "id": "019a6042-1f1c-745e-bfea-753eeaccedf2", + "label": [ + "Y" + ], + "obType": { + "tag": "Basic", + "content": "Entity" + } + }, + { + "id": "019a60e3-1785-72b9-90d2-84dc8bdddc85", + "label": [ + "Z" + ], + "obType": { + "tag": "Basic", + "content": "AttrType" + } + } + ], + "morGenerators": [ + { + "id": "019a6042-2872-7654-a9b4-67becc9ef693", + "label": [ + "f" + ], + "morType": { + "tag": "Hom", + "content": { + "tag": "Basic", + "content": "Entity" + } + }, + "dom": { + "tag": "Basic", + "content": "019a6042-1241-77bd-8055-bfea5c206bc7" + }, + "cod": { + "tag": "Basic", + "content": "019a6042-1f1c-745e-bfea-753eeaccedf2" + } + }, + { + "id": "019a60e3-2ccf-74ef-a1e1-1c940564e1ca", + "label": [ + "g" + ], + "morType": { + "tag": "Basic", + "content": "Attr" + }, + "dom": { + "tag": "Basic", + "content": "019a6042-1241-77bd-8055-bfea5c206bc7" + }, + "cod": { + "tag": "Basic", + "content": "019a60e3-1785-72b9-90d2-84dc8bdddc85" + } + } + ] + }, + "diagram": { + "obGenerators": [ + { + "id": "019a6042-7531-77c7-83db-67018685b551", + "label": [ + "x" + ], + "obType": { + "tag": "Basic", + "content": "Entity" + }, + "over": { + "tag": "Basic", + "content": "019a6042-1241-77bd-8055-bfea5c206bc7" + } + }, + { + "id": "019a6042-88fb-73f5-bd90-9d337485793a", + "label": [ + "y" + ], + "obType": { + "tag": "Basic", + "content": "Entity" + }, + "over": { + "tag": "Basic", + "content": "019a6042-1f1c-745e-bfea-753eeaccedf2" + } + }, + { + "id": "019a60e3-5bdb-745c-acd5-6f341f56833a", + "label": [ + "z" + ], + "obType": { + "tag": "Basic", + "content": "AttrType" + }, + "over": { + "tag": "Basic", + "content": "019a60e3-1785-72b9-90d2-84dc8bdddc85" + } + } + ], + "morGenerators": [ + { + "id": "019a6042-98ab-7120-80b7-3223fa942e96", + "morType": { + "tag": "Hom", + "content": { + "tag": "Basic", + "content": "Entity" + } + }, + "over": { + "tag": "Basic", + "content": "019a6042-2872-7654-a9b4-67becc9ef693" + }, + "dom": { + "tag": "Basic", + "content": "019a6042-7531-77c7-83db-67018685b551" + }, + "cod": { + "tag": "Basic", + "content": "019a6042-88fb-73f5-bd90-9d337485793a" + } + }, + { + "id": "019a60e3-6dbf-74cf-8bd9-be0d073a4ee8", + "morType": { + "tag": "Basic", + "content": "Attr" + }, + "over": { + "tag": "Basic", + "content": "019a60e3-2ccf-74ef-a1e1-1c940564e1ca" + }, + "dom": { + "tag": "Basic", + "content": "019a6042-7531-77c7-83db-67018685b551" + }, + "cod": { + "tag": "Basic", + "content": "019a60e3-5bdb-745c-acd5-6f341f56833a" + } + } + ] + } +} \ No newline at end of file diff --git a/packages/algjulia-interop/test/runtests.jl b/packages/algjulia-interop/test/runtests.jl index 4688b379c..56ed0d76f 100644 --- a/packages/algjulia-interop/test/runtests.jl +++ b/packages/algjulia-interop/test/runtests.jl @@ -1,239 +1,5 @@ using Test -# -using CatColabInterop -using ACSets -using CombinatorialSpaces -using Decapodes -using DiagrammaticEquations -# -using MLStyle -using JSON3 -using ComponentArrays -using StaticArrays -using LinearAlgebra -import OrdinaryDiffEq: ReturnCode -const KEYS = Set([:mesh, :plotVariables, :initialConditions, :domain, :diagram, :model, :scalars, :duration]) - -@testset "Text-to-Pode" begin - @test to_model(ThDecapode(), ObTag(), "0-form") == :Form0 - @test to_model(ThDecapode(), ObTag(), "1-form") == :Form1 - @test to_model(ThDecapode(), ObTag(), "2-form") == :Form2 - @test to_model(ThDecapode(), ObTag(), "dual 0-form") == :DualForm0 - @test to_model(ThDecapode(), ObTag(), "dual 1-form") == :DualForm1 - @test to_model(ThDecapode(), ObTag(), "dual 2-form") == :DualForm2 - @test_throws CatColabInterop.ImplError to_model(ThDecapode(), ObTag(), "Form3") - @test to_model(ThDecapode(), HomTag(), "∂t") == :∂ₜ - @test to_model(ThDecapode(), HomTag(), "Δ") == :Δ - @test_throws CatColabInterop.ImplError to_model(ThDecapode(), HomTag(), "∧") -end - -modeljson = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "models", "model_dec.json"), "r") -model_dec = Model(ThDecapode(), modeljson) -@testset "Validating the JSON object" begin - # validate the JSON - @test keys(modeljson) == Set([:name, :notebook, :theory, :type]) - cells = modeljson[:notebook][:cells] - @test @match cells[1] begin - IsObject(_) => true - _ => false - end - @test @match cells[5] begin - IsMorphism(_) => true - _ => false - end - model = Model(ThDecapode()) - @match cells[1] begin - IsObject(content) => add_to_model!(model, content, ObTag()) - _ => nothing - end -end -@testset "Validate model" begin - # caveat: \star and \bigstar are different, but indistinguishable in some fonts - @test Set(nameof.(values(model_dec))) == Set([:DualForm1, :⋆₀⁻¹, :dual_d₁, :dpsw, :Form1, :neg, :⋆₁, :DualForm2, :Form0, :Δ⁻¹, :♭♯, :∂ₜ, :d₀]) -end - -# ## load diagram -diagram_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "inverse_laplacian", "diagram.json"), "r") -diagram = Diagram(diagram_json[:notebook], model_dec) -@testset "Diagram - Inverse Laplacian" begin - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=:A, type=:Form0) - add_part!(handcrafted_pode, :Var, name=:B, type=:Form0) - add_part!(handcrafted_pode, :Op1, src=1, tgt=2, op1=:Δ⁻¹) - @test diagram.pode == handcrafted_pode -end - -# TODO not specifying initial boundary conditions for `B` on the front-end -# means that it will be automatically specified -@testset "Analysis - Inverse Laplacian" begin - analysis_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "inverse_laplacian", "analysis.json"), "r") - system = Analysis(analysis_json, diagram) - simulator = evalsim(system.pode) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, 50.0, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) -end - -# ## load diagram -diagram_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "inverse_laplacian_longtrip", "diagram.json"), "r") -diagram = Diagram(diagram_json[:notebook], model_dec) -infer_types!(diagram.pode) -@testset "Diagram - Inverse Laplacian - Longtrip" begin - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=:u, type=:Form0) - add_part!(handcrafted_pode, :Var, name=:Δu, type=:Form0) - add_part!(handcrafted_pode, :Var, name=Symbol("•1"), type=:Form1) - add_part!(handcrafted_pode, :Var, name=Symbol("•2"), type=:DualForm1) - add_part!(handcrafted_pode, :Var, name=Symbol("•3"), type=:DualForm2) - add_part!(handcrafted_pode, :Op1, src=1, tgt=3, op1=:d₀) - add_part!(handcrafted_pode, :Op1, src=3, tgt=4, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=4, tgt=5, op1=:dual_d₁) - add_part!(handcrafted_pode, :Op1, src=5, tgt=2, op1=:⋆₀⁻¹) - add_part!(handcrafted_pode, :Op1, src=1, tgt=2, op1=:Δ⁻¹) - @test diagram.pode == handcrafted_pode -end -# TODO not specifying initial boundary conditions for `B` on the front-end means that it will be automatically specified -@testset "Analysis - Inverse Laplacian - Longtrip" begin - analysis_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "inverse_laplacian_longtrip", "analysis.json"), "r") - system = Analysis(analysis_json, diagram) - simulator = evalsim(system.pode) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, 50.0, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) -end - -# ## load diagram -diagram_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "ns_vort", "diagram.json"), "r") -diagram = Diagram(diagram_json[:notebook], model_dec) -infer_types!(diagram.pode) -@testset "Diagram - NS Vorticity" begin - # construct a decapode - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=:v, type=:DualForm1) - add_part!(handcrafted_pode, :Var, name=:dv, type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=:ψ, type=:Form0) - # infer - add_part!(handcrafted_pode, :Var, name=Symbol("•1"), type=:Form0) - add_part!(handcrafted_pode, :Var, name=Symbol("•2"), type=:Form1) - add_part!(handcrafted_pode, :Var, name=Symbol("•3"), type=:infer) - add_part!(handcrafted_pode, :Var, name=Symbol("•4"), type=:infer) - add_part!(handcrafted_pode, :Var, name=Symbol("•5"), type=:infer) - add_part!(handcrafted_pode, :Var, name=Symbol("•6"), type=:infer) - add_part!(handcrafted_pode, :Var, name=Symbol("•7"), type=:infer) - # tvar - add_part!(handcrafted_pode, :TVar, incl=9) - # op1 - add_part!(handcrafted_pode, :Op1, src=2, tgt=4, op1=:⋆₀⁻¹) - add_part!(handcrafted_pode, :Op1, src=3, tgt=5, op1=:d₀) - add_part!(handcrafted_pode, :Op1, src=5, tgt=1, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=1, tgt=6, op1=:dpsw) # TODO breaks infer_types - add_part!(handcrafted_pode, :Op1, src=6, tgt=7, op1=:♭♯) - add_part!(handcrafted_pode, :Op1, src=7, tgt=8, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=2, tgt=9, op1=:∂ₜ) - add_part!(handcrafted_pode, :Op1, src=8, tgt=10, op1=:dual_d₁) - add_part!(handcrafted_pode, :Op1, src=10, tgt=9, op1=:neg) - infer_types!(handcrafted_pode) - @test diagram.pode == handcrafted_pode -end -# TODO not specifying initial boundary conditions for `B` on the front-end -# means that it will be automatically specified -@testset "Analysis - Navier-Stokes Vorticity" begin - analysis_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "ns_vort", "analysis.json"), "r") - system = Analysis(analysis_json, diagram) - simulator = evalsim(system.pode) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, system.duration, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) -end - -## load diagram -modeljson = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "models", "model_dec_scalar.json"), "r") -model_dec_scalar = Model(ThDecapode(), modeljson) -diagram_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "diffusivity_constant", "diagram.json"), "r") -diagram = Diagram(diagram_json[:notebook], model_dec_scalar) -infer_types!(diagram.pode) -@testset "Diagram - Diffusivity Constant" begin - # construct a decapode - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=:u, type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=Symbol("du/dt"), type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=Symbol("•1"), type=:Form0) - add_part!(handcrafted_pode, :Var, name=Symbol("•2"), type=:Form1) - add_part!(handcrafted_pode, :Var, name=Symbol("•3"), type=:DualForm1) - add_part!(handcrafted_pode, :Var, name=Symbol("•4"), type=:DualForm2) - add_part!(handcrafted_pode, :TVar, incl=2) - add_part!(handcrafted_pode, :Op1, src=1, tgt=3, op1=:⋆₀⁻¹) - add_part!(handcrafted_pode, :Op1, src=3, tgt=4, op1=:d₀) - add_part!(handcrafted_pode, :Op1, src=4, tgt=5, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=5, tgt=6, op1=:dual_d₁) - add_part!(handcrafted_pode, :Op1, src=6, tgt=2, op1=:any_scalar) - add_part!(handcrafted_pode, :Op1, src=1, tgt=2, op1=:∂ₜ) - @test diagram.pode == handcrafted_pode -end -# TODO not specifying initial boundary conditions for `B` on the front-end -# means that it will be automatically specified -@testset "Analysis - Diffusivity Constant" begin - analysis_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "diffusivity_constant", "analysis.json"), "r") - system = Analysis(analysis_json, diagram) - simulator = evalsim(system.pode) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, system.duration, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) -end - - -# Payload -payloadjson = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "payload.json")) -model = Model(ThDecapode(), payloadjson.model) -diagram = Diagram(payloadjson.diagram, model) -infer_types!(diagram.pode) -# TODO need to verify -@testset "(Payload) Diagram - Diffusivity Constant" begin - # construct a decapode - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=Symbol("dv/dt"), type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=Symbol("•1"), type=:Form0) - add_part!(handcrafted_pode, :Var, name=Symbol("•2"), type=:Form1) - add_part!(handcrafted_pode, :Var, name=Symbol("•3"), type=:DualForm1) - add_part!(handcrafted_pode, :Var, name=Symbol("•4"), type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=:v, type=:DualForm2) - add_part!(handcrafted_pode, :TVar, incl=1) - add_part!(handcrafted_pode, :Op1, src=6, tgt=2, op1=:⋆₀⁻¹) - add_part!(handcrafted_pode, :Op1, src=3, tgt=4, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=5, tgt=1, op1=:any_scalar) - add_part!(handcrafted_pode, :Op1, src=6, tgt=1, op1=:∂ₜ) - add_part!(handcrafted_pode, :Op1, src=4, tgt=5, op1=:dual_d₁) - add_part!(handcrafted_pode, :Op1, src=2, tgt=3, op1=:d₀) - @test diagram.pode == handcrafted_pode -end -# TODO not specifying initial boundary conditions for `B` on the front-end -# means that it will be automatically specified -@testset "Analysis - Diffusivity Constant" begin - system = Analysis(ThDecapode(), payloadjson) - simulator = evalsim(system.pode) - # DEBUGGING SNIPPET: - # path = joinpath(@__DIR__, "testsim.jl") - # open(path, "w") do f - # write(f, string(gensim(system.pode))) - # end - # simulator = include(path) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, system.duration, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) +@testset "Catlab" begin + include("TestCatlab.jl") end diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/analysis.json b/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/analysis.json deleted file mode 100644 index 5f986cf67..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/analysis.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "analysisOf": { - "_id": "0196021c-dee3-75b3-bb79-2f940651a1a1", - "_server": "backend.catcolab.org", - "_version": null, - "type": "analysis-of" - }, - "analysisType": "diagram", - "name": "", - "notebook": { - "cells": [ - { - "content": { - "content": { - "domain": "Plane", - "duration": 10, - "initialConditions": { - "0196021c-f5fe-70f3-ac68-89ae212970ea": "Gaussian", - "0196021d-1aa4-776d-b4fb-05d24d0c6de4": "Gaussian" - }, - "mesh": "Rectangle", - "plotVariables": { - "0196021c-f5fe-70f3-ac68-89ae212970ea": true - }, - "scalars": { - "01960dde-1193-7132-b662-9bf24ed05264": 1 - } - }, - "id": "decapodes" - }, - "id": "0196021f-beef-74b0-9103-9ab1982255cf", - "tag": "formal" - }, - { - "content": { - "content": { - "layout": "graphviz-directed" - }, - "id": "graph" - }, - "id": "01960ddd-8fc3-7482-a2c8-a0a59ee85709", - "tag": "formal" - } - ] - }, - "type": "analysis" -} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/diagram.json b/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/diagram.json deleted file mode 100644 index 53d93e9fb..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/diagram.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "diagramIn": { - "_id": "0196021c-d1ff-75b1-9f38-bdecdb7680d2", - "_server": "backend.catcolab.org", - "_version": null, - "type": "diagram-in" - }, - "name": "", - "notebook": { - "cells": [ - { - "content": { - "id": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "name": "u", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "over": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0196021c-f5fe-70f3-ac68-8f4da8bb79be", - "tag": "formal" - }, - { - "content": { - "id": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "name": "du/dt", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "over": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0196021d-1aa4-776d-b4fb-098aea19edd5", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021e-9635-74de-845a-cee56d3e5cc5", - "tag": "Basic" - }, - "dom": { - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "tag": "Basic" - }, - "id": "0196021e-848d-704c-a45c-a325b63951e6", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d399-34f3-773c-91b9-857da9c4311f", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021e-848d-704c-a45c-a6b09dac0136", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd", - "tag": "Basic" - }, - "dom": { - "content": "0196021e-9635-74de-845a-cee56d3e5cc5", - "tag": "Basic" - }, - "id": "0196021e-c8a6-74df-8194-3ec769ba3d1d", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d39a-6084-7537-aec1-caf560ba416b", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021e-c8a6-74df-8194-40ee060a7684", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021f-0a11-7443-b5da-31175c628e3c", - "tag": "Basic" - }, - "dom": { - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd", - "tag": "Basic" - }, - "id": "0196021e-ecf9-7408-b881-d981c4e85222", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d39a-ed25-710f-b53f-89541021281f", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021e-ecf9-7408-b881-ddb32ac3d85e", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021f-4c93-70dc-8e61-24459f79f837", - "tag": "Basic" - }, - "dom": { - "content": "0196021f-0a11-7443-b5da-31175c628e3c", - "tag": "Basic" - }, - "id": "0196021f-1ba8-77a5-a635-8b3ca32ae99c", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021f-1ba8-77a5-a635-8f6c9f8b2c4c", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "tag": "Basic" - }, - "dom": { - "content": "0196021f-4c93-70dc-8e61-24459f79f837", - "tag": "Basic" - }, - "id": "0196021f-6b45-751e-8313-df1024cd9fa0", - "morType": { - "content": { - "content": "Object", - "tag": "Basic" - }, - "tag": "Hom" - }, - "name": "", - "over": { - "content": "01960dde-1193-7132-b662-9bf24ed05264", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021f-6b46-73b4-8b8a-1417d000ecfd", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "tag": "Basic" - }, - "dom": { - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "tag": "Basic" - }, - "id": "01960df4-b95f-7660-90b6-aaf1dc940a15", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "01960df4-b95f-7660-90b6-ae21afb022aa", - "tag": "formal" - } - ] - }, - "type": "diagram" -} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/analysis.json b/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/analysis.json deleted file mode 100644 index bcc7c72b3..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/analysis.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "analysisOf": { - "_id": "0195c95c-b3eb-7142-8b38-b7287cf2c76f", - "_server": "backend.catcolab.org", - "_version": null, - "type": "analysis-of" - }, - "analysisType": "diagram", - "name": "", - "notebook": { - "cells": [ - { - "content": { - "content": { - "domain": "Sphere", - "duration": 1, - "initialConditions": { - "0195c95c-c200-73a0-bf58-1cc188ecd0c4": "TaylorVortex", - "0195c95c-d4b4-779b-ae65-a89269f63b43": "TaylorVortex" - }, - "mesh": "Icosphere6", - "plotVariables": { - "0195c95c-c200-73a0-bf58-1cc188ecd0c4": true, - "0195c95c-d4b4-779b-ae65-a89269f63b43": false - }, - "scalars": {} - }, - "id": "decapodes" - }, - "id": "0195c95d-3b6b-71cb-8bd2-9fbc90fc609f", - "tag": "formal" - }, - { - "id": "0195ca0d-166a-7179-87d8-b5cf9dd9eaf1", - "tag": "stem" - }, - { - "content": { - "content": { - "layout": "graphviz-directed" - }, - "id": "graph" - }, - "id": "0195ca0d-b210-72c5-a091-3e57ced85ed5", - "tag": "formal" - }, - { - "id": "0195dddf-faaa-76ea-a966-ba4b9be5b36e", - "tag": "stem" - } - ] - }, - "type": "analysis" -} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/diagram.json b/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/diagram.json deleted file mode 100644 index a0c3ae2c0..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/diagram.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "diagramIn": { - "_id": "0195c95c-9917-7402-82b9-1b6c735258b7", - "_server": "backend.catcolab.org", - "_version": null, - "type": "diagram-in" - }, - "name": "", - "notebook": { - "cells": [ - { - "content": { - "id": "0195c95c-c200-73a0-bf58-1cc188ecd0c4", - "name": "A", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "over": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0195c95c-c200-73a0-bf58-22914f83428d", - "tag": "formal" - }, - { - "content": { - "id": "0195c95c-d4b4-779b-ae65-a89269f63b43", - "name": "B", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "over": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0195c95c-d4b4-779b-ae65-ad0a7af96410", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0195c95c-d4b4-779b-ae65-a89269f63b43", - "tag": "Basic" - }, - "dom": { - "content": "0195c95c-c200-73a0-bf58-1cc188ecd0c4", - "tag": "Basic" - }, - "id": "0195dde5-27aa-72fa-9cde-ff6571346ca7", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d399-b2a2-73ff-aece-cb0f26644045", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0195dde5-27aa-72fa-9cdf-0313e512eb41", - "tag": "formal" - } - ] - }, - "type": "diagram" -} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/analysis.json b/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/analysis.json deleted file mode 100644 index f42780bee..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/analysis.json +++ /dev/null @@ -1 +0,0 @@ -{"analysisOf":{"_id":"0195ecdc-cf21-7091-94a3-7644d5103743","_server":"backend.catcolab.org","_version":null,"type":"analysis-of"},"analysisType":"diagram","name":"","notebook":{"cells":[{"id":"0195ed44-aa9e-730d-807d-57cf94417236","tag":"stem"},{"content":{"content":{"domain":"Plane","duration":10,"initialConditions":{"0195ecdc-d7e1-768a-8862-76a47f2f4e06":"Gaussian","0195ecdc-f625-71c8-a044-a6ce2fb3dd31":"Gaussian"},"mesh":"Rectangle","plotVariables":{"0195ecdc-d7e1-768a-8862-76a47f2f4e06":true},"scalars":{}},"id":"decapodes"},"id":"0195ed44-c260-755f-9c1f-80c13253e575","tag":"formal"}]},"type":"analysis"} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/diagram.json b/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/diagram.json deleted file mode 100644 index 09e15e238..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/diagram.json +++ /dev/null @@ -1 +0,0 @@ -{"diagramIn":{"_id":"0195ecc4-309b-7742-b7d7-35f8ba9021f9","_server":"backend.catcolab.org","_version":null,"type":"diagram-in"},"name":"","notebook":{"cells":[{"content":{"id":"0195ecdc-d7e1-768a-8862-76a47f2f4e06","name":"u","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-a28e-7433-89f8-563bae6e6875","tag":"Basic"},"tag":"object"},"id":"0195ecdc-d7e1-768a-8862-780d2b88ba8f","tag":"formal"},{"content":{"id":"0195ecdc-f625-71c8-a044-a6ce2fb3dd31","name":"Δu","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-a28e-7433-89f8-563bae6e6875","tag":"Basic"},"tag":"object"},"id":"0195ecdc-f625-71c8-a044-a898b541279d","tag":"formal"},{"content":{"cod":{"content":"0195ecdd-c6c2-705b-ad25-44d72de6fc99","tag":"Basic"},"dom":{"content":"0195ecdc-d7e1-768a-8862-76a47f2f4e06","tag":"Basic"},"id":"0195ecdd-a1d8-771f-a5db-47c43a43da66","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-6084-7537-aec1-caf560ba416b","tag":"Basic"},"tag":"morphism"},"id":"0195ecdd-a1d8-771f-a5db-48e03a65f8a9","tag":"formal"},{"content":{"cod":{"content":"0195ecde-1719-72af-8f7e-bcfa1c6fa617","tag":"Basic"},"dom":{"content":"0195ecdd-c6c2-705b-ad25-44d72de6fc99","tag":"Basic"},"id":"0195ecdd-e894-7111-a026-21f6b8f17f86","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-ed25-710f-b53f-89541021281f","tag":"Basic"},"tag":"morphism"},"id":"0195ecdd-e895-77f9-b6ec-38d511443d63","tag":"formal"},{"content":{"cod":{"content":"0195ece5-5cc4-718f-82bb-1a5bb0cf8ac8","tag":"Basic"},"dom":{"content":"0195ecde-1719-72af-8f7e-bcfa1c6fa617","tag":"Basic"},"id":"0195ece5-4a90-7047-bcd6-10834ee90cea","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39d-d297-77a9-95a2-6ed7105fdca3","tag":"Basic"},"tag":"morphism"},"id":"0195ece5-4a90-7047-bcd6-172ee350261f","tag":"formal"},{"content":{"cod":{"content":"0195ecdc-f625-71c8-a044-a6ce2fb3dd31","tag":"Basic"},"dom":{"content":"0195ece5-5cc4-718f-82bb-1a5bb0cf8ac8","tag":"Basic"},"id":"0195ece5-80df-71a1-b50e-cf38757198ba","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d399-34f3-773c-91b9-857da9c4311f","tag":"Basic"},"tag":"morphism"},"id":"0195ece5-80df-71a1-b50e-d0d77173e3a9","tag":"formal"},{"content":{"cod":{"content":"0195ecdc-f625-71c8-a044-a6ce2fb3dd31","tag":"Basic"},"dom":{"content":"0195ecdc-d7e1-768a-8862-76a47f2f4e06","tag":"Basic"},"id":"0195ece7-6b59-76a8-b973-d83c90bae58a","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d399-b2a2-73ff-aece-cb0f26644045","tag":"Basic"},"tag":"morphism"},"id":"0195ece7-6b59-76a8-b973-dfca48ecabd6","tag":"formal"}]},"type":"diagram"} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/analysis.json b/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/analysis.json deleted file mode 100644 index 8838d4941..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/analysis.json +++ /dev/null @@ -1 +0,0 @@ -{"analysisOf":{"_id":"0195ecc4-4c4d-70e2-bee7-18221e6c42e7","_server":"backend.catcolab.org","_version":null,"type":"analysis-of"},"analysisType":"diagram","name":"","notebook":{"cells":[{"content":{"content":{"domain":"Sphere","duration":1,"initialConditions":{"0195ecc5-9eaf-71dd-a9c8-621d888e2add":"TaylorVortex","0195ecc5-b1b0-746e-8a04-ebd359da2bfd":"TaylorVortex","0195ecc5-d39a-72bf-8cd3-236d5211e122":"TaylorVortex"},"mesh":"Icosphere6","plotVariables":{"0195ecc5-9eaf-71dd-a9c8-621d888e2add":true},"scalars":{}},"id":"decapodes"},"id":"0195ecca-f11e-74c8-8fa4-fb8b03a93274","tag":"formal"}]},"type":"analysis"} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/diagram.json b/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/diagram.json deleted file mode 100644 index 4e0f694ed..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/diagram.json +++ /dev/null @@ -1 +0,0 @@ -{"diagramIn":{"_id":"0195ecc4-309b-7742-b7d7-35f8ba9021f9","_server":"backend.catcolab.org","_version":null,"type":"diagram-in"},"name":"","notebook":{"cells":[{"content":{"id":"0195ecc5-9eaf-71dd-a9c8-621d888e2add","name":"v","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-b3ef-728d-bd88-60b48fd7349a","tag":"Basic"},"tag":"object"},"id":"0195ecc5-9eb0-70f9-b2c0-36f0f3d4cd28","tag":"formal"},{"content":{"id":"0195ecc5-b1b0-746e-8a04-ebd359da2bfd","name":"dv","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-d0cb-7308-b7e0-eace5b21af24","tag":"Basic"},"tag":"object"},"id":"0195ecc5-b1b0-746e-8a04-ef250a7afe00","tag":"formal"},{"content":{"id":"0195ecc5-d39a-72bf-8cd3-236d5211e122","name":"ψ","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-a28e-7433-89f8-563bae6e6875","tag":"Basic"},"tag":"object"},"id":"0195ecc5-d39a-72bf-8cd3-26a9e71b49bf","tag":"formal"},{"content":{"cod":{"content":"0195ecc6-f2ab-719c-844b-b8413517e269","tag":"Basic"},"dom":{"content":"0195ecc5-b1b0-746e-8a04-ebd359da2bfd","tag":"Basic"},"id":"0195ecc6-ce3f-7607-bce9-cb3fa3ddb4a6","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d399-34f3-773c-91b9-857da9c4311f","tag":"Basic"},"tag":"morphism"},"id":"0195ecc6-ce3f-7607-bce9-cf213389bf95","tag":"formal"},{"content":{"cod":{"content":"0195ecc7-388f-72c0-a4f1-3b89ed8aa6e0","tag":"Basic"},"dom":{"content":"0195ecc5-d39a-72bf-8cd3-236d5211e122","tag":"Basic"},"id":"0195ecc7-10a4-755e-8cc7-a3900d37dc93","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-6084-7537-aec1-caf560ba416b","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-10a4-755e-8cc7-a45b6cbd1cb8","tag":"formal"},{"content":{"cod":{"content":"0195ecc5-9eaf-71dd-a9c8-621d888e2add","tag":"Basic"},"dom":{"content":"0195ecc7-388f-72c0-a4f1-3b89ed8aa6e0","tag":"Basic"},"id":"0195ecc7-4faa-751f-951d-4d854f43a59d","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-ed25-710f-b53f-89541021281f","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-4faa-751f-951d-50a87eb7eb09","tag":"formal"},{"content":{"cod":{"content":"0195ecc7-8f7f-720e-b1ef-befd8deb0e78","tag":"Basic"},"dom":{"content":"0195ecc5-9eaf-71dd-a9c8-621d888e2add","tag":"Basic"},"id":"0195ecc7-7698-70a8-8847-3b021b1f48fa","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39b-587f-7559-a1ff-b6ed58899461","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-7698-70a8-8847-3d286c36d0e8","tag":"formal"},{"content":{"cod":{"content":"0195ecc7-c18e-7632-990d-33dd4afe1f87","tag":"Basic"},"dom":{"content":"0195ecc7-8f7f-720e-b1ef-befd8deb0e78","tag":"Basic"},"id":"0195ecc7-9a27-77fd-bbe3-320fa00047ed","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39b-a70a-77d5-8e89-66f0e767a9da","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-9a27-77fd-bbe3-36268ee77145","tag":"formal"},{"content":{"cod":{"content":"0195ecc7-f8e6-761b-a52e-3ecbe49ddaa1","tag":"Basic"},"dom":{"content":"0195ecc7-c18e-7632-990d-33dd4afe1f87","tag":"Basic"},"id":"0195ecc7-c925-74fb-9fa4-b172831ead97","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-ed25-710f-b53f-89541021281f","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-c925-74fb-9fa4-b74dfa39bba8","tag":"formal"},{"content":{"cod":{"content":"0195ecca-5a2c-71cd-998d-d0f25a79a266","tag":"Basic"},"dom":{"content":"0195ecc5-b1b0-746e-8a04-ebd359da2bfd","tag":"Basic"},"id":"0195ecc9-bcfd-7689-bc42-75a237fe9c2c","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39c-622d-7599-bc5c-e7e8208d6cdd","tag":"Basic"},"tag":"morphism"},"id":"0195ecc9-bcfd-7689-bc42-7a6c6e84d4f3","tag":"formal"},{"content":{"cod":{"content":"0195ecca-8dd0-7735-9d74-c73dc1c8eb9e","tag":"Basic"},"dom":{"content":"0195ecc7-f8e6-761b-a52e-3ecbe49ddaa1","tag":"Basic"},"id":"0195ecca-64d2-71e7-9f79-31cb7d8cb95e","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39d-d297-77a9-95a2-6ed7105fdca3","tag":"Basic"},"tag":"morphism"},"id":"0195ecca-64d2-71e7-9f79-3708a3062d71","tag":"formal"},{"content":{"cod":{"content":"0195ecca-5a2c-71cd-998d-d0f25a79a266","tag":"Basic"},"dom":{"content":"0195ecca-8dd0-7735-9d74-c73dc1c8eb9e","tag":"Basic"},"id":"0195ecca-98d7-73f7-9297-b8b693434f99","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39e-5d44-77cd-bc5e-156c5c56ae85","tag":"Basic"},"tag":"morphism"},"id":"0195ecca-98d7-73f7-9297-be3feb46d9b9","tag":"formal"}]},"type":"diagram"} diff --git a/packages/algjulia-interop/test/test_jsons/diffconst_payload1.json b/packages/algjulia-interop/test/test_jsons/diffconst_payload1.json deleted file mode 100644 index 1a0039420..000000000 --- a/packages/algjulia-interop/test/test_jsons/diffconst_payload1.json +++ /dev/null @@ -1,435 +0,0 @@ -{ - "diagram": [ - { - "tag": "object", - "name": "du/dt", - "id": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021e-9635-74de-845a-cee56d3e5cc5", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-a28e-7433-89f8-563bae6e6875" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021e-e55e-764e-85c8-827f94d7f3bd", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021f-0a11-7443-b5da-31175c628e3c", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021f-4c93-70dc-8e61-24459f79f837", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "object", - "name": "u", - "id": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-848d-704c-a45c-a325b63951e6", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d399-34f3-773c-91b9-857da9c4311f" - }, - "dom": { - "tag": "Basic", - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea" - }, - "cod": { - "tag": "Basic", - "content": "0196021e-9635-74de-845a-cee56d3e5cc5" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-ecf9-7408-b881-d981c4e85222", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-ed25-710f-b53f-89541021281f" - }, - "dom": { - "tag": "Basic", - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd" - }, - "cod": { - "tag": "Basic", - "content": "0196021f-0a11-7443-b5da-31175c628e3c" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021f-6b45-751e-8313-df1024cd9fa0", - "morType": { - "tag": "Hom", - "content": { - "tag": "Basic", - "content": "Object" - } - }, - "over": { - "tag": "Basic", - "content": "01960dde-1193-7132-b662-9bf24ed05264" - }, - "dom": { - "tag": "Basic", - "content": "0196021f-4c93-70dc-8e61-24459f79f837" - }, - "cod": { - "tag": "Basic", - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4" - } - }, - { - "tag": "morphism", - "name": "", - "id": "01960df4-b95f-7660-90b6-aaf1dc940a15", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39c-622d-7599-bc5c-e7e8208d6cdd" - }, - "dom": { - "tag": "Basic", - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea" - }, - "cod": { - "tag": "Basic", - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021f-1ba8-77a5-a635-8b3ca32ae99c", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39d-d297-77a9-95a2-6ed7105fdca3" - }, - "dom": { - "tag": "Basic", - "content": "0196021f-0a11-7443-b5da-31175c628e3c" - }, - "cod": { - "tag": "Basic", - "content": "0196021f-4c93-70dc-8e61-24459f79f837" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-c8a6-74df-8194-3ec769ba3d1d", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-6084-7537-aec1-caf560ba416b" - }, - "dom": { - "tag": "Basic", - "content": "0196021e-9635-74de-845a-cee56d3e5cc5" - }, - "cod": { - "tag": "Basic", - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd" - } - } - ], - "model": [ - { - "id": "0194d398-a28e-7433-89f8-563bae6e6875", - "name": "0-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "name": "Dual 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "name": "Dual 2-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "name": "Primal 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d399-34f3-773c-91b9-857da9c4311f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ⋆₀⁻¹", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d399-b2a2-73ff-aece-cb0f26644045", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "Δ⁻¹", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d39a-6084-7537-aec1-caf560ba416b", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d₀", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "id": "0194d39a-ed25-710f-b53f-89541021281f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "⋆₁", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-587f-7559-a1ff-b6ed58899461", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "lamb", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-a70a-77d5-8e89-66f0e767a9da", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ♭♯", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d̃₁", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "∂ₜ", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39e-5d44-77cd-bc5e-156c5c56ae85", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "-", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "01960dde-1193-7132-b662-9bf24ed05264", - "morType": { - "content": { - "content": "Object", - "tag": "Basic" - }, - "tag": "Hom" - }, - "name": "any_scalar", - "tag": "morphism" - } - ], - "domain": "Plane", - "mesh": "Rectangle", - "initialConditions": { - "0196021c-f5fe-70f3-ac68-89ae212970ea": "Gaussian", - "0196021d-1aa4-776d-b4fb-05d24d0c6de4": "Gaussian" - }, - "plotVariables": [ - "0196021c-f5fe-70f3-ac68-89ae212970ea" - ], - "scalars": { - "01960dde-1193-7132-b662-9bf24ed05264": 0.5 - }, - "duration": 10 -} diff --git a/packages/algjulia-interop/test/test_jsons/models/model_dec.json b/packages/algjulia-interop/test/test_jsons/models/model_dec.json deleted file mode 100644 index f7053967f..000000000 --- a/packages/algjulia-interop/test/test_jsons/models/model_dec.json +++ /dev/null @@ -1,250 +0,0 @@ -{ - "name": "DEC for vorticity", - "notebook": { - "cells": [ - { - "content": { - "id": "0194d398-a28e-7433-89f8-563bae6e6875", - "name": "0-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-a28e-7433-89f8-5a563b37d845", - "tag": "formal" - }, - { - "content": { - "id": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "name": "Dual 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-b3ef-728d-bd88-64aa410935d0", - "tag": "formal" - }, - { - "content": { - "id": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "name": "Dual 2-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-d0cb-7308-b7e0-ed7c6bca5073", - "tag": "formal" - }, - { - "content": { - "id": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "name": "Primal 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d39a-89cf-762b-9d2a-58435e3f239e", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d399-34f3-773c-91b9-857da9c4311f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ⋆₀⁻¹", - "tag": "morphism" - }, - "id": "0194d399-34f3-773c-91b9-8ba5ecdb1ae3", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d399-b2a2-73ff-aece-cb0f26644045", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "Δ⁻¹", - "tag": "morphism" - }, - "id": "0194d399-b2a2-73ff-aece-ccafcd2f4901", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d39a-6084-7537-aec1-caf560ba416b", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d₀", - "tag": "morphism" - }, - "id": "0194d39a-6084-7537-aec1-cf63f29c9a9f", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "id": "0194d39a-ed25-710f-b53f-89541021281f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "⋆₁", - "tag": "morphism" - }, - "id": "0194d39a-ed25-710f-b53f-8dfad8f332aa", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-587f-7559-a1ff-b6ed58899461", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "lamb", - "tag": "morphism" - }, - "id": "0194d39b-587f-7559-a1ff-b9a4cc198cff", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-a70a-77d5-8e89-66f0e767a9da", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ♭♯", - "tag": "morphism" - }, - "id": "0194d39b-a70a-77d5-8e89-6a34504e2754", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d̃₁", - "tag": "morphism" - }, - "id": "0194d39d-d297-77a9-95a2-71f5210cecf2", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "∂ₜ", - "tag": "morphism" - }, - "id": "0194d39c-622d-7599-bc5c-e86b88f88031", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39e-5d44-77cd-bc5e-156c5c56ae85", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "-", - "tag": "morphism" - }, - "id": "0194d39e-5d44-77cd-bc5e-1aa6b0a2d8d4", - "tag": "formal" - } - ] - }, - "theory": "unary-dec", - "type": "model" -} \ No newline at end of file diff --git a/packages/algjulia-interop/test/test_jsons/models/model_dec_scalar.json b/packages/algjulia-interop/test/test_jsons/models/model_dec_scalar.json deleted file mode 100644 index 595c0490a..000000000 --- a/packages/algjulia-interop/test/test_jsons/models/model_dec_scalar.json +++ /dev/null @@ -1,274 +0,0 @@ -{ - "name": "DEC for vorticity", - "notebook": { - "cells": [ - { - "content": { - "id": "0194d398-a28e-7433-89f8-563bae6e6875", - "name": "0-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-a28e-7433-89f8-5a563b37d845", - "tag": "formal" - }, - { - "content": { - "id": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "name": "Dual 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-b3ef-728d-bd88-64aa410935d0", - "tag": "formal" - }, - { - "content": { - "id": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "name": "Dual 2-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-d0cb-7308-b7e0-ed7c6bca5073", - "tag": "formal" - }, - { - "content": { - "id": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "name": "Primal 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d39a-89cf-762b-9d2a-58435e3f239e", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d399-34f3-773c-91b9-857da9c4311f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ⋆₀⁻¹", - "tag": "morphism" - }, - "id": "0194d399-34f3-773c-91b9-8ba5ecdb1ae3", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d399-b2a2-73ff-aece-cb0f26644045", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "Δ⁻¹", - "tag": "morphism" - }, - "id": "0194d399-b2a2-73ff-aece-ccafcd2f4901", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d39a-6084-7537-aec1-caf560ba416b", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d₀", - "tag": "morphism" - }, - "id": "0194d39a-6084-7537-aec1-cf63f29c9a9f", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "id": "0194d39a-ed25-710f-b53f-89541021281f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "⋆₁", - "tag": "morphism" - }, - "id": "0194d39a-ed25-710f-b53f-8dfad8f332aa", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-587f-7559-a1ff-b6ed58899461", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "lamb", - "tag": "morphism" - }, - "id": "0194d39b-587f-7559-a1ff-b9a4cc198cff", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-a70a-77d5-8e89-66f0e767a9da", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ♭♯", - "tag": "morphism" - }, - "id": "0194d39b-a70a-77d5-8e89-6a34504e2754", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d̃₁", - "tag": "morphism" - }, - "id": "0194d39d-d297-77a9-95a2-71f5210cecf2", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "∂ₜ", - "tag": "morphism" - }, - "id": "0194d39c-622d-7599-bc5c-e86b88f88031", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39e-5d44-77cd-bc5e-156c5c56ae85", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "-", - "tag": "morphism" - }, - "id": "0194d39e-5d44-77cd-bc5e-1aa6b0a2d8d4", - "tag": "formal" - }, - { - "tag": "formal", - "id": "01960dde-1194-729d-92f7-8c876f072ff8", - "content": { - "tag": "morphism", - "id": "01960dde-1193-7132-b662-9bf24ed05264", - "name": "any_scalar", - "morType": { - "tag": "Hom", - "content": { - "tag": "Basic", - "content": "Object" - } - }, - "dom": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - }, - "cod": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - } - } - ] - }, - "theory": "unary-dec", - "type": "model" -} diff --git a/packages/algjulia-interop/test/test_jsons/payload.json b/packages/algjulia-interop/test/test_jsons/payload.json deleted file mode 100644 index a8d46701e..000000000 --- a/packages/algjulia-interop/test/test_jsons/payload.json +++ /dev/null @@ -1,435 +0,0 @@ -{ - "diagram": [ - { - "tag": "object", - "name": "dv/dt", - "id": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021e-9635-74de-845a-cee56d3e5cc5", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-a28e-7433-89f8-563bae6e6875" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021e-e55e-764e-85c8-827f94d7f3bd", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021f-0a11-7443-b5da-31175c628e3c", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021f-4c93-70dc-8e61-24459f79f837", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "object", - "name": "v", - "id": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-848d-704c-a45c-a325b63951e6", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d399-34f3-773c-91b9-857da9c4311f" - }, - "dom": { - "tag": "Basic", - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea" - }, - "cod": { - "tag": "Basic", - "content": "0196021e-9635-74de-845a-cee56d3e5cc5" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-ecf9-7408-b881-d981c4e85222", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-ed25-710f-b53f-89541021281f" - }, - "dom": { - "tag": "Basic", - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd" - }, - "cod": { - "tag": "Basic", - "content": "0196021f-0a11-7443-b5da-31175c628e3c" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021f-6b45-751e-8313-df1024cd9fa0", - "morType": { - "tag": "Hom", - "content": { - "tag": "Basic", - "content": "Object" - } - }, - "over": { - "tag": "Basic", - "content": "01960dde-1193-7132-b662-9bf24ed05264" - }, - "dom": { - "tag": "Basic", - "content": "0196021f-4c93-70dc-8e61-24459f79f837" - }, - "cod": { - "tag": "Basic", - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4" - } - }, - { - "tag": "morphism", - "name": "", - "id": "01960df4-b95f-7660-90b6-aaf1dc940a15", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39c-622d-7599-bc5c-e7e8208d6cdd" - }, - "dom": { - "tag": "Basic", - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea" - }, - "cod": { - "tag": "Basic", - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021f-1ba8-77a5-a635-8b3ca32ae99c", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39d-d297-77a9-95a2-6ed7105fdca3" - }, - "dom": { - "tag": "Basic", - "content": "0196021f-0a11-7443-b5da-31175c628e3c" - }, - "cod": { - "tag": "Basic", - "content": "0196021f-4c93-70dc-8e61-24459f79f837" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-c8a6-74df-8194-3ec769ba3d1d", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-6084-7537-aec1-caf560ba416b" - }, - "dom": { - "tag": "Basic", - "content": "0196021e-9635-74de-845a-cee56d3e5cc5" - }, - "cod": { - "tag": "Basic", - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd" - } - } - ], - "model": [ - { - "id": "0194d398-a28e-7433-89f8-563bae6e6875", - "name": "0-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "name": "Dual 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "name": "Dual 2-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "name": "Primal 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d399-34f3-773c-91b9-857da9c4311f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ⋆₀⁻¹", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d399-b2a2-73ff-aece-cb0f26644045", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "Δ⁻¹", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d39a-6084-7537-aec1-caf560ba416b", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d₀", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "id": "0194d39a-ed25-710f-b53f-89541021281f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "⋆₁", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-587f-7559-a1ff-b6ed58899461", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "lamb", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-a70a-77d5-8e89-66f0e767a9da", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ♭♯", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d̃₁", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "∂ₜ", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39e-5d44-77cd-bc5e-156c5c56ae85", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "-", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "01960dde-1193-7132-b662-9bf24ed05264", - "morType": { - "content": { - "content": "Object", - "tag": "Basic" - }, - "tag": "Hom" - }, - "name": "any_scalar", - "tag": "morphism" - } - ], - "domain": "Plane", - "mesh": "Rectangle", - "initialConditions": { - "0196021c-f5fe-70f3-ac68-89ae212970ea": "Gaussian", - "0196021d-1aa4-776d-b4fb-05d24d0c6de4": "Gaussian" - }, - "plotVariables": [ - "0196021c-f5fe-70f3-ac68-89ae212970ea" - ], - "scalars": { - "01960dde-1193-7132-b662-9bf24ed05264": 1 - }, - "duration": 10 -} diff --git a/packages/frontend/pnpm-lock.yaml b/packages/frontend/pnpm-lock.yaml index 450cac1b6..aa8fff12c 100644 --- a/packages/frontend/pnpm-lock.yaml +++ b/packages/frontend/pnpm-lock.yaml @@ -6701,3 +6701,4 @@ snapshots: tslib: 2.3.0 zwitch@2.0.4: {} + \ No newline at end of file diff --git a/packages/frontend/src/stdlib/analyses.tsx b/packages/frontend/src/stdlib/analyses.tsx index 33d9b37fa..407cc6053 100644 --- a/packages/frontend/src/stdlib/analyses.tsx +++ b/packages/frontend/src/stdlib/analyses.tsx @@ -43,6 +43,16 @@ export const diagramGraph = ( const DiagramGraph = lazy(() => import("./analyses/diagram_graph")); +export const tabularView = ( + options: AnalysisOptions, +): DiagramAnalysisMeta => ({ + ...options, + component: (props) => , + initialContent: GraphLayoutConfig.defaultConfig, +}); + +const TabularView = lazy(() => import("./analyses/tabular_view")); + export function kuramoto( options: Partial & { simulate: Simulators.KuramotoSimulator; diff --git a/packages/frontend/src/stdlib/analyses/decapodes.tsx b/packages/frontend/src/stdlib/analyses/decapodes.tsx index 060ee99d4..9e22ff324 100644 --- a/packages/frontend/src/stdlib/analyses/decapodes.tsx +++ b/packages/frontend/src/stdlib/analyses/decapodes.tsx @@ -315,14 +315,14 @@ const makeSimulationCode = (data: SimulationData) => # needed for returning large amounts of data, should be paired with a similar setting on the jupyter server IJulia.set_max_stdio(1_000_000_000) - system = Analysis(ThDecapode(), raw"""${JSON.stringify(data)}"""); - simulator = evalsim(system.pode); + simulation = DecapodeSimulation(raw"""${JSON.stringify(data)}"""); + simulator = evalsim(simulation.pode); - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()); + f = simulator(simulation.geometry.dualmesh, simulation.generate, DiagonalHodge()); - soln = run_sim(f, system.init, system.duration, ComponentArray(k=0.5,)); + result = run(f, simulation, ComponentArray(k=0.5,)) - JSON3.write(stdout, SimResult(soln, system)) + JSON3.write(stdout, result) `; /** Create data to send to the Julia kernel. */ diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.css b/packages/frontend/src/stdlib/analyses/tabular_view.css new file mode 100644 index 000000000..00634c4fb --- /dev/null +++ b/packages/frontend/src/stdlib/analyses/tabular_view.css @@ -0,0 +1,4 @@ +.tabular-view-table { + border: 1px solid black; + border-collapse: collapse; +} diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx new file mode 100644 index 000000000..b2e555883 --- /dev/null +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -0,0 +1,156 @@ +import { createResource, For, Match, Switch } from "solid-js"; + +import { PanelHeader, Spinner } from "catcolab-ui-components"; +import type { DblModel } from "catlog-wasm"; +import type { DiagramAnalysisProps } from "../../analysis"; +import type { GraphLayoutConfig } from "../../visualization"; +import "./tabular_view.css"; + +/** This should live somewhere more general, once multiple analyses use local + computation. Furthermore, although it can default to localhost 8080, one + ought be able to put some AWS credentials in their user profile to run + remote computation there. +*/ +const config = { + url: "http://127.0.0.1:8080", + method: "post", + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "POST, PUT, DELETE, GET, OPTIONS", + "Access-Control-Allow-Headers": "*", + "Access-Control-Allow-Credentials": "false", + }, +}; + +/** Create a table from row-wise data */ +function createTable(headers: Array, data: Array>) { + return ( + + {headers && ( + + + + {(header) => } + + + + )} + + + {(row) => ( + + + {(cell) => } + + + )} + + +
{header}
{cell}
+ ); +} + +/** Given a schema (DblModel of ThSchema), a JSON output `rawdata` from Catlab, + and a particular object `obname` in the schema, create an HTML table with +*/ +function createACSetTable(model: DblModel, rawdata: object, obname: string) { + // The primary key of this table is given by `rawdata[obname]` + const rows: Array = rawdata[obname as keyof typeof rawdata]; + + // Get the homs and attrs with source `obname` + const outhoms = model + .morGenerators() + .filter( + (m) => + obname === + model + .obGeneratorLabel(model.morPresentation(m)?.dom.content.toString() || "") + ?.toString(), + ); + + // Convert morgenerators to user-friendly names + const headers = [obname].concat( + outhoms.map((m) => model.morGeneratorLabel(m)?.toString() || ""), + ); + + // Data for column from indexing rawdata + const columnardata: Array> = headers.map( + (m: string) => rawdata[m as keyof typeof rawdata] || [""], + ); + + // Convert columnar data to row data + const data = Array.from(rows.keys()).map((colIndex) => + columnardata.map((row) => row[colIndex] || ""), + ); + + return createTable(headers, data); +} + +/** Stack tables on top of each other in a naive way, one per ob/attrtype */ +function createACSet(model: DblModel, rawdata: object) { + return ( +
+ + + {(ob) => + createACSetTable(model, rawdata, model.obGeneratorLabel(ob)?.toString() || "") + } + +
+ ); +} + +/** Visualize a diagram in a model of ThSchema as a collection of tables. + +Such a visualization makes sense for any discrete double theory and is in +general restricted to basic objects. See `ModelGraph` for more. + */ +export default function TabularView( + props: DiagramAnalysisProps & { + title?: string; + }, +) { + const [res] = createResource( + () => { + const model = props.liveDiagram.liveModel.elaboratedModel(); + const diagram = props.liveDiagram.elaboratedDiagram(); + return model && diagram && [model, diagram]; + }, + + async ([model, diagram]) => { + const response = await fetch("http://127.0.0.1:8080/acsetcolim", { + method: "POST", + headers: { + "Content-Type": "application/json", + ...config.headers, + }, + body: JSON.stringify({ + model: model?.presentation(), + diagram: diagram?.presentation(), + }), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return response.json(); + }, + ); + const model = props.liveDiagram.liveModel.elaboratedModel(); + if (model === undefined) { + throw "Bad model"; + } + return ( + + + +
⏳ Loading model...
+
+ +
❌ Error loading model: {res.error?.message || "Unknown error"}
+
+ {(data) =>
{createACSet(model, data())}
}
+
+ ); +} diff --git a/packages/frontend/src/stdlib/theories/simple-schema.ts b/packages/frontend/src/stdlib/theories/simple-schema.ts index 4bf73401c..d7335e7d6 100644 --- a/packages/frontend/src/stdlib/theories/simple-schema.ts +++ b/packages/frontend/src/stdlib/theories/simple-schema.ts @@ -122,6 +122,12 @@ export default function createSchemaTheory(theoryMeta: TheoryMeta): Theory { description: "Visualize the instance as a graph", help: "visualization", }), + analyses.tabularView({ + id: "tabularview", + name: "Tabular Visualization", + description: "Visualize the instance as a table", + help: "tabularview", + }), ], }); } From 9ba8a70e9cdde2e7cf2ff87a990719b4291edc03 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Wed, 7 Jan 2026 09:51:14 -0800 Subject: [PATCH 02/11] Remove unnecessary CORS --- packages/algjulia-interop/scripts/endpoint.jl | 3 +-- .../src/stdlib/analyses/tabular_view.tsx | 17 ----------------- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/packages/algjulia-interop/scripts/endpoint.jl b/packages/algjulia-interop/scripts/endpoint.jl index 2319e7615..115a0e018 100644 --- a/packages/algjulia-interop/scripts/endpoint.jl +++ b/packages/algjulia-interop/scripts/endpoint.jl @@ -23,9 +23,8 @@ function CorsHandler(handle) return HTTP.Response(200, CORS_HEADERS) else r = handle(req) - append!(r.headers, ["Access-Control-Allow-Origin" => "*"]) + r.headers = CORS_HEADERS r - end end end diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx index b2e555883..5d889fff1 100644 --- a/packages/frontend/src/stdlib/analyses/tabular_view.tsx +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -6,22 +6,6 @@ import type { DiagramAnalysisProps } from "../../analysis"; import type { GraphLayoutConfig } from "../../visualization"; import "./tabular_view.css"; -/** This should live somewhere more general, once multiple analyses use local - computation. Furthermore, although it can default to localhost 8080, one - ought be able to put some AWS credentials in their user profile to run - remote computation there. -*/ -const config = { - url: "http://127.0.0.1:8080", - method: "post", - headers: { - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Methods": "POST, PUT, DELETE, GET, OPTIONS", - "Access-Control-Allow-Headers": "*", - "Access-Control-Allow-Credentials": "false", - }, -}; - /** Create a table from row-wise data */ function createTable(headers: Array, data: Array>) { return ( @@ -122,7 +106,6 @@ export default function TabularView( method: "POST", headers: { "Content-Type": "application/json", - ...config.headers, }, body: JSON.stringify({ model: model?.presentation(), From fda91dd7ab99318df69c39dfcaa9fc21ccb85dc8 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Fri, 30 Jan 2026 10:09:44 -0800 Subject: [PATCH 03/11] Doc fixes, block tabular view on prod --- packages/algjulia-interop/README.md | 2 +- .../src/stdlib/analyses/tabular_view.tsx | 1 + .../src/stdlib/theories/simple-schema.ts | 37 +++++++++++-------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/packages/algjulia-interop/README.md b/packages/algjulia-interop/README.md index 2ea02942e..156d27090 100644 --- a/packages/algjulia-interop/README.md +++ b/packages/algjulia-interop/README.md @@ -1,7 +1,7 @@ # AlgebraicJulia Service This small package makes functionality from -[AlgebraicJulia](https://www.algebraicjulia.org/) available to CatColab.At this +[AlgebraicJulia](https://www.algebraicjulia.org/) available to CatColab. At this time, only a [Catlab.jl](https://github.com/AlgebraicJulia/Catlab.jl) service is provided. Other packages (e.g. Decapodes.jl) will be added in the future. diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx index 5d889fff1..53d9f25dd 100644 --- a/packages/frontend/src/stdlib/analyses/tabular_view.tsx +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -36,6 +36,7 @@ function createTable(headers: Array, data: Array>) { /** Given a schema (DblModel of ThSchema), a JSON output `rawdata` from Catlab, and a particular object `obname` in the schema, create an HTML table with + the outgoing homs/attributes from that object. */ function createACSetTable(model: DblModel, rawdata: object, obname: string) { // The primary key of this table is given by `rawdata[obname]` diff --git a/packages/frontend/src/stdlib/theories/simple-schema.ts b/packages/frontend/src/stdlib/theories/simple-schema.ts index d7335e7d6..25717d6bb 100644 --- a/packages/frontend/src/stdlib/theories/simple-schema.ts +++ b/packages/frontend/src/stdlib/theories/simple-schema.ts @@ -1,5 +1,5 @@ import { ThSchema } from "catlog-wasm"; -import { Theory, type TheoryMeta } from "../../theory"; +import { Theory, type TheoryMeta, DiagramAnalysisMeta } from "../../theory"; import * as analyses from "../analyses"; import styles from "../styles.module.css"; import svgStyles from "../svg_styles.module.css"; @@ -7,7 +7,27 @@ import textStyles from "../text_styles.module.css"; export default function createSchemaTheory(theoryMeta: TheoryMeta): Theory { const thSchema = new ThSchema(); + let diagramAnalyses: DiagramAnalysisMeta[] = []; + diagramAnalyses.push( + analyses.diagramGraph({ + id: "graph", + name: "Visualization", + description: "Visualize the instance as a graph", + help: "visualization", + }), + ); + + if (import.meta.env.DEV) { + diagramAnalyses.push( + analyses.tabularView({ + id: "tabularview", + name: "Tabular Visualization", + description: "Visualize the instance as a table", + help: "tabularview", + }), + ); + } return new Theory({ ...theoryMeta, theory: thSchema.theory(), @@ -115,19 +135,6 @@ export default function createSchemaTheory(theoryMeta: TheoryMeta): Theory { render: (model, data) => thSchema.renderSQL(model, data), }), ], - diagramAnalyses: [ - analyses.diagramGraph({ - id: "graph", - name: "Visualization", - description: "Visualize the instance as a graph", - help: "visualization", - }), - analyses.tabularView({ - id: "tabularview", - name: "Tabular Visualization", - description: "Visualize the instance as a table", - help: "tabularview", - }), - ], + diagramAnalyses: diagramAnalyses, }); } From 24ef5db78489b0c119f41d5b9dc76a9c3a6117ea Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Fri, 30 Jan 2026 11:15:10 -0800 Subject: [PATCH 04/11] avoid re-validating the model --- packages/algjulia-interop/README.md | 16 ++++++----- .../src/stdlib/analyses/tabular_view.tsx | 27 +++++++++++-------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/packages/algjulia-interop/README.md b/packages/algjulia-interop/README.md index 156d27090..dd37a4707 100644 --- a/packages/algjulia-interop/README.md +++ b/packages/algjulia-interop/README.md @@ -11,13 +11,15 @@ First, install [Julia](https://julialang.org/), say by using [`juliaup`](https://github.com/JuliaLang/juliaup). We then need a Julia environment that has all the requisite packages installed. -The `test` folder of this repo is a perfectly good candidate for this, although -in principal one might want to use their own environment (if they don't want to -load all dependencies for all possible analyses, or if they have a locally -modified version of the code that is running the analysis). To make sure this -environment is ready to use, navigate to this directory and run -`julia --project=test` and then press `]` and enter the commands `instantiate` -and `precompile`. +The `test` folder of this repo is a perfectly good candidate for this, although +in principal one might want to use their own environment (if they don't want to +load all dependencies for all possible analyses, or if they have a locally +modified version of the code that is running the analysis). To make sure this +environment is ready to use, navigate to this directory and run `julia --project=test` +and then press `]` (to enter package mode) and enter the +commands `instantiate` and `precompile`. If the source code of +CatColabInterop.jl is different from the latest tagged release, one must also +run `dev .` from package mode. Having done that, to start the server, from this directory run: diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx index 53d9f25dd..9f8dd4807 100644 --- a/packages/frontend/src/stdlib/analyses/tabular_view.tsx +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -55,7 +55,7 @@ function createACSetTable(model: DblModel, rawdata: object, obname: string) { // Convert morgenerators to user-friendly names const headers = [obname].concat( - outhoms.map((m) => model.morGeneratorLabel(m)?.toString() || ""), + outhoms.map((m) => model.morGeneratorLabel(m)?.join(".") ?? ""), ); // Data for column from indexing rawdata @@ -99,18 +99,22 @@ export default function TabularView( () => { const model = props.liveDiagram.liveModel.elaboratedModel(); const diagram = props.liveDiagram.elaboratedDiagram(); - return model && diagram && [model, diagram]; + if (model === undefined || diagram === undefined) { + return undefined; + } else { + return { model: model, diagram: diagram }; + } }, - async ([model, diagram]) => { + async (modeldiagram) => { const response = await fetch("http://127.0.0.1:8080/acsetcolim", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ - model: model?.presentation(), - diagram: diagram?.presentation(), + model: modeldiagram?.model.presentation(), + diagram: modeldiagram?.diagram.presentation(), }), }); @@ -118,13 +122,9 @@ export default function TabularView( throw new Error(`HTTP error! status: ${response.status}`); } - return response.json(); + return { model: modeldiagram.model, data: await response.json() }; }, ); - const model = props.liveDiagram.liveModel.elaboratedModel(); - if (model === undefined) { - throw "Bad model"; - } return ( @@ -134,7 +134,12 @@ export default function TabularView(
❌ Error loading model: {res.error?.message || "Unknown error"}
- {(data) =>
{createACSet(model, data())}
}
+ + {(data) => { + let result = data(); + return
{createACSet(result.model, result.data)}
; + }} +
); } From 8107d70347f77ce932fdcc0f741113ad10d62ea4 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Fri, 30 Jan 2026 11:24:12 -0800 Subject: [PATCH 05/11] Fix DiagramAnalysisMeta type parameter --- packages/frontend/src/stdlib/analyses.tsx | 6 +++--- packages/frontend/src/stdlib/analyses/tabular_view.tsx | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/stdlib/analyses.tsx b/packages/frontend/src/stdlib/analyses.tsx index 407cc6053..268e97788 100644 --- a/packages/frontend/src/stdlib/analyses.tsx +++ b/packages/frontend/src/stdlib/analyses.tsx @@ -45,10 +45,10 @@ const DiagramGraph = lazy(() => import("./analyses/diagram_graph")); export const tabularView = ( options: AnalysisOptions, -): DiagramAnalysisMeta => ({ +): DiagramAnalysisMeta<{}> => ({ ...options, - component: (props) => , - initialContent: GraphLayoutConfig.defaultConfig, + component: (props) => , + initialContent: () => ({}), }); const TabularView = lazy(() => import("./analyses/tabular_view")); diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx index 9f8dd4807..ce86c88e1 100644 --- a/packages/frontend/src/stdlib/analyses/tabular_view.tsx +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -3,7 +3,6 @@ import { createResource, For, Match, Switch } from "solid-js"; import { PanelHeader, Spinner } from "catcolab-ui-components"; import type { DblModel } from "catlog-wasm"; import type { DiagramAnalysisProps } from "../../analysis"; -import type { GraphLayoutConfig } from "../../visualization"; import "./tabular_view.css"; /** Create a table from row-wise data */ @@ -88,10 +87,10 @@ function createACSet(model: DblModel, rawdata: object) { /** Visualize a diagram in a model of ThSchema as a collection of tables. Such a visualization makes sense for any discrete double theory and is in -general restricted to basic objects. See `ModelGraph` for more. +general restricted to basic objects. */ export default function TabularView( - props: DiagramAnalysisProps & { + props: DiagramAnalysisProps<{}> & { title?: string; }, ) { From 52c5fe2c5495eb2688a9023df418ab1caba79230 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Fri, 30 Jan 2026 13:08:52 -0800 Subject: [PATCH 06/11] Make more specific type than Object --- packages/frontend/src/stdlib/analyses.tsx | 8 +++----- packages/frontend/src/stdlib/analyses/tabular_view.tsx | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/frontend/src/stdlib/analyses.tsx b/packages/frontend/src/stdlib/analyses.tsx index 268e97788..557eae099 100644 --- a/packages/frontend/src/stdlib/analyses.tsx +++ b/packages/frontend/src/stdlib/analyses.tsx @@ -43,12 +43,10 @@ export const diagramGraph = ( const DiagramGraph = lazy(() => import("./analyses/diagram_graph")); -export const tabularView = ( - options: AnalysisOptions, -): DiagramAnalysisMeta<{}> => ({ +export const tabularView = (options: AnalysisOptions): DiagramAnalysisMeta<{}> => ({ ...options, - component: (props) => , - initialContent: () => ({}), + component: (props) => , + initialContent: () => ({}), }); const TabularView = lazy(() => import("./analyses/tabular_view")); diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx index ce86c88e1..fd52e67ed 100644 --- a/packages/frontend/src/stdlib/analyses/tabular_view.tsx +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -37,7 +37,7 @@ function createTable(headers: Array, data: Array>) { and a particular object `obname` in the schema, create an HTML table with the outgoing homs/attributes from that object. */ -function createACSetTable(model: DblModel, rawdata: object, obname: string) { +function createACSetTable(model: DblModel, rawdata: Record, obname: string) { // The primary key of this table is given by `rawdata[obname]` const rows: Array = rawdata[obname as keyof typeof rawdata]; @@ -71,7 +71,7 @@ function createACSetTable(model: DblModel, rawdata: object, obname: string) { } /** Stack tables on top of each other in a naive way, one per ob/attrtype */ -function createACSet(model: DblModel, rawdata: object) { +function createACSet(model: DblModel, rawdata: Record) { return (
From 10b60aefe7301549897b05911d9d2e62057b3dca Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Fri, 30 Jan 2026 14:22:25 -0800 Subject: [PATCH 07/11] Use obj / mor ids rather than human names . --- packages/algjulia-interop/ext/CatlabExt.jl | 16 +++++----- .../src/stdlib/analyses/tabular_view.tsx | 29 +++++++------------ .../src/stdlib/theories/simple-schema.ts | 8 ++--- 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/packages/algjulia-interop/ext/CatlabExt.jl b/packages/algjulia-interop/ext/CatlabExt.jl index 15c30202d..34fe01fde 100644 --- a/packages/algjulia-interop/ext/CatlabExt.jl +++ b/packages/algjulia-interop/ext/CatlabExt.jl @@ -66,12 +66,12 @@ Receiver of the data already knows the schema, so the JSON payload to CatColab just includes the columns of data. Every part is named, so we use the names (including for primary key columns) rather than numeric indices. """ -function acset_to_json(X::ACSet, S::Schema, names::Dict{Symbol, Vector{String}} +function acset_to_json(X::ACSet, S::Schema, ids::Dict{String, Symbol}, names::Dict{Symbol, Vector{String}} )::AbstractDict - Dict{Symbol, Vector{String}}( - [t => names[t] for t in types(S)] - ∪ [f => names[c][X[f]] for (f,_,c) in homs(S)] - ∪ [f => names[c][getvalue.(X[f])] for (f,_,c) in attrs(S)] ) + Dict{String, Vector{String}}( + [findfirst(==(t), ids) => names[t] for t in types(S)] + ∪ [findfirst(==(f), ids) => names[c][X[f]] for (f,_,c) in homs(S)] + ∪ [findfirst(==(f), ids) => names[c][getvalue.(X[f])] for (f,_,c) in attrs(S)] ) end """ @@ -107,13 +107,13 @@ Top level function called by CatColab. Computes an ACSet colimit of a function endpoint(::Val{:ACSetColim}) @post "/acsetcolim" function(req::HTTP.Request) payload = json(req, ModelDiagram) - schema, names = model_to_schema(payload.model) - data = diagram_to_data(payload.diagram, names) + schema, ids = model_to_schema(payload.model) + data = diagram_to_data(payload.diagram, ids) acset_type = AnonACSet( schema; type_assignment=Dict(a=>Nothing for a in schema.attrtypes)) y = yoneda(constructor(acset_type)) names, res = colimit_representables(data, y) - acset_to_json(res, schema, make_names(res, names)) + acset_to_json(res, schema, ids, make_names(res, names)) end end diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx index fd52e67ed..5afa6f5ff 100644 --- a/packages/frontend/src/stdlib/analyses/tabular_view.tsx +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -37,20 +37,15 @@ function createTable(headers: Array, data: Array>) { and a particular object `obname` in the schema, create an HTML table with the outgoing homs/attributes from that object. */ -function createACSetTable(model: DblModel, rawdata: Record, obname: string) { +function createACSetTable(model: DblModel, rawdata: Record, obId: string) { // The primary key of this table is given by `rawdata[obname]` - const rows: Array = rawdata[obname as keyof typeof rawdata]; + const rows: Array = rawdata[obId] || []; + const obname: string = model.obGeneratorLabel(obId)?.toString() || ""; // Get the homs and attrs with source `obname` const outhoms = model .morGenerators() - .filter( - (m) => - obname === - model - .obGeneratorLabel(model.morPresentation(m)?.dom.content.toString() || "") - ?.toString(), - ); + .filter((m) => obId === model.morPresentation(m)?.dom.content.toString()); // Convert morgenerators to user-friendly names const headers = [obname].concat( @@ -58,12 +53,12 @@ function createACSetTable(model: DblModel, rawdata: Record, ob ); // Data for column from indexing rawdata - const columnardata: Array> = headers.map( - (m: string) => rawdata[m as keyof typeof rawdata] || [""], - ); + const columnardata: Array> = [obId] + .concat(outhoms) + .map((m: string) => rawdata[m as keyof typeof rawdata] || [""]); // Convert columnar data to row data - const data = Array.from(rows.keys()).map((colIndex) => + const data = Array.from(rows?.keys()).map((colIndex) => columnardata.map((row) => row[colIndex] || ""), ); @@ -75,11 +70,7 @@ function createACSet(model: DblModel, rawdata: Record) { return (
- - {(ob) => - createACSetTable(model, rawdata, model.obGeneratorLabel(ob)?.toString() || "") - } - + {(ob) => createACSetTable(model, rawdata, ob)}
); } @@ -135,7 +126,7 @@ export default function TabularView( {(data) => { - let result = data(); + const result = data(); return
{createACSet(result.model, result.data)}
; }}
diff --git a/packages/frontend/src/stdlib/theories/simple-schema.ts b/packages/frontend/src/stdlib/theories/simple-schema.ts index 25717d6bb..dd47ca2c0 100644 --- a/packages/frontend/src/stdlib/theories/simple-schema.ts +++ b/packages/frontend/src/stdlib/theories/simple-schema.ts @@ -1,5 +1,5 @@ import { ThSchema } from "catlog-wasm"; -import { Theory, type TheoryMeta, DiagramAnalysisMeta } from "../../theory"; +import { type DiagramAnalysisMeta, Theory, type TheoryMeta } from "../../theory"; import * as analyses from "../analyses"; import styles from "../styles.module.css"; import svgStyles from "../svg_styles.module.css"; @@ -7,16 +7,14 @@ import textStyles from "../text_styles.module.css"; export default function createSchemaTheory(theoryMeta: TheoryMeta): Theory { const thSchema = new ThSchema(); - let diagramAnalyses: DiagramAnalysisMeta[] = []; - - diagramAnalyses.push( + let diagramAnalyses: DiagramAnalysisMeta[] = [ analyses.diagramGraph({ id: "graph", name: "Visualization", description: "Visualize the instance as a graph", help: "visualization", }), - ); + ]; if (import.meta.env.DEV) { diagramAnalyses.push( From 623e20a12cc40e304a04b230897f284a18c94c4d Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Fri, 6 Feb 2026 16:00:11 -0800 Subject: [PATCH 08/11] CLEANUP: Eliminate remaining uses of `toString` on model types. Also, fix a lint about the type `{}` in TypeScript. --- packages/frontend/src/stdlib/analyses.tsx | 4 +++- .../src/stdlib/analyses/tabular_view.tsx | 17 +++++++++-------- .../src/stdlib/theories/simple-schema.ts | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/frontend/src/stdlib/analyses.tsx b/packages/frontend/src/stdlib/analyses.tsx index 557eae099..5bbdf5ddc 100644 --- a/packages/frontend/src/stdlib/analyses.tsx +++ b/packages/frontend/src/stdlib/analyses.tsx @@ -43,7 +43,9 @@ export const diagramGraph = ( const DiagramGraph = lazy(() => import("./analyses/diagram_graph")); -export const tabularView = (options: AnalysisOptions): DiagramAnalysisMeta<{}> => ({ +export const tabularView = ( + options: AnalysisOptions, +): DiagramAnalysisMeta> => ({ ...options, component: (props) => , initialContent: () => ({}), diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx index 5afa6f5ff..6c8a13730 100644 --- a/packages/frontend/src/stdlib/analyses/tabular_view.tsx +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -40,22 +40,23 @@ function createTable(headers: Array, data: Array>) { function createACSetTable(model: DblModel, rawdata: Record, obId: string) { // The primary key of this table is given by `rawdata[obname]` const rows: Array = rawdata[obId] || []; - const obname: string = model.obGeneratorLabel(obId)?.toString() || ""; + const obname = model.obGeneratorLabel(obId)?.join(".") || ""; - // Get the homs and attrs with source `obname` - const outhoms = model - .morGenerators() - .filter((m) => obId === model.morPresentation(m)?.dom.content.toString()); + // Get the homs and attrs with source `obId` + const outhoms = model.morGenerators().filter((morId) => { + const mor = model.morPresentation(morId); + return mor?.dom.tag === "Basic" && mor.dom.content === obId; + }); // Convert morgenerators to user-friendly names const headers = [obname].concat( - outhoms.map((m) => model.morGeneratorLabel(m)?.join(".") ?? ""), + outhoms.map((morId) => model.morGeneratorLabel(morId)?.join(".") ?? ""), ); // Data for column from indexing rawdata const columnardata: Array> = [obId] .concat(outhoms) - .map((m: string) => rawdata[m as keyof typeof rawdata] || [""]); + .map((m) => rawdata[m as keyof typeof rawdata] || [""]); // Convert columnar data to row data const data = Array.from(rows?.keys()).map((colIndex) => @@ -81,7 +82,7 @@ Such a visualization makes sense for any discrete double theory and is in general restricted to basic objects. */ export default function TabularView( - props: DiagramAnalysisProps<{}> & { + props: DiagramAnalysisProps> & { title?: string; }, ) { diff --git a/packages/frontend/src/stdlib/theories/simple-schema.ts b/packages/frontend/src/stdlib/theories/simple-schema.ts index dd47ca2c0..4897f4be6 100644 --- a/packages/frontend/src/stdlib/theories/simple-schema.ts +++ b/packages/frontend/src/stdlib/theories/simple-schema.ts @@ -7,7 +7,7 @@ import textStyles from "../text_styles.module.css"; export default function createSchemaTheory(theoryMeta: TheoryMeta): Theory { const thSchema = new ThSchema(); - let diagramAnalyses: DiagramAnalysisMeta[] = [ + const diagramAnalyses: DiagramAnalysisMeta[] = [ analyses.diagramGraph({ id: "graph", name: "Visualization", From 9856c996c98f25e23fa29a77e2997187ec998d99 Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Fri, 6 Feb 2026 16:13:13 -0800 Subject: [PATCH 09/11] CLEANUP: Simplify (de)structuring in tabular view for acsets. --- .../frontend/src/stdlib/analyses/tabular_view.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx index 6c8a13730..83d82f493 100644 --- a/packages/frontend/src/stdlib/analyses/tabular_view.tsx +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -90,22 +90,20 @@ export default function TabularView( () => { const model = props.liveDiagram.liveModel.elaboratedModel(); const diagram = props.liveDiagram.elaboratedDiagram(); - if (model === undefined || diagram === undefined) { - return undefined; - } else { - return { model: model, diagram: diagram }; + if (model && diagram) { + return { model, diagram }; } }, - async (modeldiagram) => { + async ({ model, diagram }) => { const response = await fetch("http://127.0.0.1:8080/acsetcolim", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ - model: modeldiagram?.model.presentation(), - diagram: modeldiagram?.diagram.presentation(), + model: model.presentation(), + diagram: diagram.presentation(), }), }); @@ -113,7 +111,7 @@ export default function TabularView( throw new Error(`HTTP error! status: ${response.status}`); } - return { model: modeldiagram.model, data: await response.json() }; + return { model, data: await response.json() }; }, ); return ( From 0c57b4e45b546706bbe2a6db2e1328d5f0f569e6 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Tue, 17 Feb 2026 12:20:35 -0800 Subject: [PATCH 10/11] Componentify acset table view --- .../src/stdlib/analyses/tabular_view.tsx | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx index 83d82f493..17f64090f 100644 --- a/packages/frontend/src/stdlib/analyses/tabular_view.tsx +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -5,8 +5,36 @@ import type { DblModel } from "catlog-wasm"; import type { DiagramAnalysisProps } from "../../analysis"; import "./tabular_view.css"; -/** Create a table from row-wise data */ -function createTable(headers: Array, data: Array>) { +/** Given a schema (DblModel of ThSchema), a JSON output `rawdata` from Catlab, + and a particular object `obname` in the schema, create an HTML table with + the outgoing homs/attributes from that object. +*/ +function ACSetTable(props: { model: DblModel; rawdata: Record; obId: string }) { + // The primary key of this table is given by `rawdata[obname]` + const rows: Array = props.rawdata[props.obId] || []; + const obname = props.model.obGeneratorLabel(props.obId)?.join(".") || ""; + + // Get the homs and attrs with source `obId` + const outhoms = props.model.morGenerators().filter((morId) => { + const mor = props.model.morPresentation(morId); + return mor?.dom.tag === "Basic" && mor.dom.content === props.obId; + }); + + // Convert morgenerators to user-friendly names + const headers = [obname].concat( + outhoms.map((morId) => props.model.morGeneratorLabel(morId)?.join(".") ?? ""), + ); + + // Data for column from indexing rawdata + const columnardata: Array> = [props.obId] + .concat(outhoms) + .map((m) => props.rawdata[m as keyof typeof props.rawdata] || [""]); + + // Convert columnar data to row data + const data = Array.from(rows?.keys()).map((colIndex) => + columnardata.map((row) => row[colIndex] || ""), + ); + return ( {headers && ( @@ -33,45 +61,14 @@ function createTable(headers: Array, data: Array>) { ); } -/** Given a schema (DblModel of ThSchema), a JSON output `rawdata` from Catlab, - and a particular object `obname` in the schema, create an HTML table with - the outgoing homs/attributes from that object. -*/ -function createACSetTable(model: DblModel, rawdata: Record, obId: string) { - // The primary key of this table is given by `rawdata[obname]` - const rows: Array = rawdata[obId] || []; - const obname = model.obGeneratorLabel(obId)?.join(".") || ""; - - // Get the homs and attrs with source `obId` - const outhoms = model.morGenerators().filter((morId) => { - const mor = model.morPresentation(morId); - return mor?.dom.tag === "Basic" && mor.dom.content === obId; - }); - - // Convert morgenerators to user-friendly names - const headers = [obname].concat( - outhoms.map((morId) => model.morGeneratorLabel(morId)?.join(".") ?? ""), - ); - - // Data for column from indexing rawdata - const columnardata: Array> = [obId] - .concat(outhoms) - .map((m) => rawdata[m as keyof typeof rawdata] || [""]); - - // Convert columnar data to row data - const data = Array.from(rows?.keys()).map((colIndex) => - columnardata.map((row) => row[colIndex] || ""), - ); - - return createTable(headers, data); -} - /** Stack tables on top of each other in a naive way, one per ob/attrtype */ -function createACSet(model: DblModel, rawdata: Record) { +function ACSetTableView(props: { model: DblModel; rawdata: Record }) { return (
- {(ob) => createACSetTable(model, rawdata, ob)} + + {(ob) => } +
); } @@ -126,7 +123,7 @@ export default function TabularView( {(data) => { const result = data(); - return
{createACSet(result.model, result.data)}
; + return ; }}
From 811bdfa85bf63645682ed40e8b13ad343da0d6d9 Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Tue, 17 Feb 2026 17:41:46 -0800 Subject: [PATCH 11/11] BUILD: Remove @jupyterlab/services, no longer used for Julia interop. --- packages/frontend/default.nix | 2 +- packages/frontend/package.json | 1 - packages/frontend/pnpm-lock.yaml | 375 ------------------ .../src/stdlib/analyses/decapodes.tsx | 82 +--- .../frontend/src/stdlib/analyses/jupyter.ts | 182 --------- 5 files changed, 17 insertions(+), 625 deletions(-) delete mode 100644 packages/frontend/src/stdlib/analyses/jupyter.ts diff --git a/packages/frontend/default.nix b/packages/frontend/default.nix index 321b7e73e..47516331d 100644 --- a/packages/frontend/default.nix +++ b/packages/frontend/default.nix @@ -36,7 +36,7 @@ let pnpmDeps = pkgs.fetchPnpmDeps { # see ../../dev-docs/fixing-hash-mismatches.md - hash = "sha256-S7k6oZHDBFCj4FsNuVoITB3nQdxABXAYRsZaK2Xbzvs="; + hash = "sha256-bId9YUkRZ0oPAl1Skj+sVaFQENUps1G1C6ifIK6lfm0="; pname = name; fetcherVersion = 2; # Only includes package.json and pnpm-lock.yaml files to ensure consistent hashing in different diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 52f93d553..53c5179ac 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -32,7 +32,6 @@ "@corvu/popover": "^0.2.0", "@corvu/resizable": "^0.2.5", "@corvu/tooltip": "^0.2.2", - "@jupyterlab/services": "^7.3.1", "@mdx-js/rollup": "^3.1.0", "@modular-forms/solid": "^0.24.1", "@qubit-rs/client": "^0.4.5", diff --git a/packages/frontend/pnpm-lock.yaml b/packages/frontend/pnpm-lock.yaml index aa8fff12c..d9b5981b7 100644 --- a/packages/frontend/pnpm-lock.yaml +++ b/packages/frontend/pnpm-lock.yaml @@ -47,9 +47,6 @@ importers: '@corvu/tooltip': specifier: ^0.2.2 version: 0.2.2(solid-js@1.9.10) - '@jupyterlab/services': - specifier: ^7.3.1 - version: 7.3.1(react@18.3.1) '@mdx-js/rollup': specifier: ^3.1.0 version: 3.1.0(acorn@8.12.1)(rollup@4.53.2) @@ -868,56 +865,6 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@jupyter/ydoc@3.0.1': - resolution: {integrity: sha512-zO6PEe/kNpb9oRPhxytLdnL4zclVDJVCIEavprIlIs/qCxGbgC/BvIoK6N/Ny525Ljrev8Ku9B+y6P2qFn3zqg==} - - '@jupyterlab/coreutils@6.3.1': - resolution: {integrity: sha512-72Lyg2XA0Fsyn+62FpVIf67TGrxQZ4CNvldDvmlkixyY/n63bB38AcC0zvvCFDRv7QwXQzp7DaA0xfvAPoQ3bw==} - - '@jupyterlab/nbformat@4.3.1': - resolution: {integrity: sha512-9dIcagn5xQMKijPiu08MGAnfWQzk5mkqHRltHUfYbydV33lWgTjFBEpugHncEZGIxIJz+iqw2H9KJ8HSb7aJqw==} - - '@jupyterlab/services@7.3.1': - resolution: {integrity: sha512-ZXRW2wDV7kIoFRj8M3nkbaSxC6pYn4QlRtwJJEz6Ewges9x+EJEKoN7V0AVQ2zDG1XSmMvRLAvv1YvLgEk4Bug==} - - '@jupyterlab/settingregistry@4.3.1': - resolution: {integrity: sha512-tlRYh+CouyyDY3nGsCcD9hQKftdYKMwkTSV4X09vHlIEZoMNrbXtkyADgErgQGaIMwx7gtaLU4qCWK2LLMGyDw==} - peerDependencies: - react: '>=16' - - '@jupyterlab/statedb@4.3.1': - resolution: {integrity: sha512-Uph0kEPgCZvI6XnRsf7Md4WWA+4WnJMzwubc7cxk7B2KjdRYOqJHVtQbdJk4ZUA2ARhyS8tBtit/BZb9e3wLZw==} - - '@lumino/algorithm@2.0.2': - resolution: {integrity: sha512-cI8yJ2+QK1yM5ZRU3Kuaw9fJ/64JEDZEwWWp7+U0cd/mvcZ44BGdJJ29w+tIet1QXxPAvnsUleWyQ5qm4qUouA==} - - '@lumino/commands@2.3.1': - resolution: {integrity: sha512-DpX1kkE4PhILpvK1T4ZnaFb6UP4+YTkdZifvN3nbiomD64O2CTd+wcWIBpZMgy6MMgbVgrE8dzHxHk1EsKxNxw==} - - '@lumino/coreutils@2.2.0': - resolution: {integrity: sha512-x5wnQ/GjWBayJ6vXVaUi6+Q6ETDdcUiH9eSfpRZFbgMQyyM6pi6baKqJBK2CHkCc/YbAEl6ipApTgm3KOJ/I3g==} - - '@lumino/disposable@2.1.3': - resolution: {integrity: sha512-k5KXy/+T3UItiWHY4WwQawnsJnGo3aNtP5CTRKqo4+tbTNuhc3rTSvygJlNKIbEfIZXW2EWYnwfFDozkYx95eA==} - - '@lumino/domutils@2.0.2': - resolution: {integrity: sha512-2Kp6YHaMNI1rKB0PrALvOsZBHPy2EvVVAvJLWjlCm8MpWOVETjFp0MA9QpMubT9I76aKbaI5s1o1NJyZ8Y99pQ==} - - '@lumino/keyboard@2.0.2': - resolution: {integrity: sha512-icRUpvswDaFjqmAJNbQRb/aTu6Iugo6Y2oC08TiIwhQtLS9W+Ee9VofdqvbPSvCm6DkyP+DCWMuA3KXZ4V4g4g==} - - '@lumino/polling@2.1.3': - resolution: {integrity: sha512-WEZk96ddK6eHEhdDkFUAAA40EOLit86QVbqQqnbPmhdGwFogek26Kq9b1U273LJeirv95zXCATOJAkjRyb7D+w==} - - '@lumino/properties@2.0.2': - resolution: {integrity: sha512-b312oA3Bh97WFK8efXejYmC3DVJmvzJk72LQB7H3fXhfqS5jUWvL7MSnNmgcQvGzl9fIhDWDWjhtSTi0KGYYBg==} - - '@lumino/signaling@2.1.3': - resolution: {integrity: sha512-9Wd4iMk8F1i6pYjy65bqKuPlzQMicyL9xy1/ccS20kovPcfD074waneL/7BVe+3M8i+fGa3x2qjbWrBzOdTdNw==} - - '@lumino/virtualdom@2.0.2': - resolution: {integrity: sha512-HYZThOtZSoknjdXA102xpy5CiXtTFCVz45EXdWeYLx3NhuEwuAIX93QBBIhupalmtFlRg1yhdDNV40HxJ4kcXg==} - '@mdx-js/mdx@2.3.0': resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} @@ -975,12 +922,6 @@ packages: '@qubit-rs/client@0.4.5': resolution: {integrity: sha512-L7pBAUs1sPWCkuoRq7rdwqXy1+iLOmOVhADxj+QoNY24yu4J1aiTUSlJJllK9rXRxfvkjRNEPSeUE5H+U3ncug==} - '@rjsf/utils@5.22.4': - resolution: {integrity: sha512-yQTdz5ryiYy258xCVthVPQ3DeaMzrRNrFcO8xvGHorp0/bLUxdTZ0iidXop49m3y8SaxxTZd398ZKWg2cqxiIA==} - engines: {node: '>=14'} - peerDependencies: - react: ^16.14.0 || >=17 - '@rollup/pluginutils@5.2.0': resolution: {integrity: sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==} engines: {node: '>=14.0.0'} @@ -1302,9 +1243,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1471,12 +1409,6 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} - compute-gcd@1.2.1: - resolution: {integrity: sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==} - - compute-lcm@1.1.2: - resolution: {integrity: sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1635,9 +1567,6 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-equals@5.2.2: resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==} engines: {node: '>=6.0.0'} @@ -1648,9 +1577,6 @@ packages: fast-sha256@1.3.0: resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==} - fast-uri@3.0.3: - resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} - faye-websocket@0.11.4: resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} engines: {node: '>=0.8.0'} @@ -1874,9 +1800,6 @@ packages: peerDependencies: ws: '*' - isomorphic.js@0.2.5: - resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} - jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -1899,25 +1822,11 @@ packages: engines: {node: '>=6'} hasBin: true - json-schema-compare@0.2.2: - resolution: {integrity: sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==} - - json-schema-merge-allof@0.8.1: - resolution: {integrity: sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==} - engines: {node: '>=12.0.0'} - - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true - jsonpointer@5.0.1: - resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} - engines: {node: '>=0.10.0'} - katex@0.16.22: resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==} hasBin: true @@ -1926,33 +1835,18 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} - lib0@0.2.98: - resolution: {integrity: sha512-XteTiNO0qEXqqweWx+b21p/fBnNHUA1NwAtJNJek1oPrewEZs2uiT4gWivHKr9GqCjDPAhchz0UQO8NwU3bBNA==} - engines: {node: '>=16'} - hasBin: true - linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - lodash-es@4.17.21: - resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} - lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -2227,9 +2121,6 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} @@ -2305,9 +2196,6 @@ packages: parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} - path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -2434,19 +2322,12 @@ packages: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} - querystringify@2.2.0: - resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - raf-schd@4.0.3: resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==} react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2503,13 +2384,6 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - - requires-port@1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -2787,9 +2661,6 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - url-parse@1.5.10: - resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -2817,21 +2688,6 @@ packages: validate-html-nesting@1.2.2: resolution: {integrity: sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg==} - validate.io-array@1.0.6: - resolution: {integrity: sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==} - - validate.io-function@1.0.2: - resolution: {integrity: sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==} - - validate.io-integer-array@1.0.0: - resolution: {integrity: sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==} - - validate.io-integer@1.0.5: - resolution: {integrity: sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==} - - validate.io-number@1.0.3: - resolution: {integrity: sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==} - vfile-location@5.0.3: resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} @@ -2986,18 +2842,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.18.3: resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} @@ -3013,12 +2857,6 @@ packages: xstate@5.20.1: resolution: {integrity: sha512-i9ZpNnm/XhCOMUxae1suT8PjYNTStZWbhmuKt4xeTPaYG5TS0Fz0i+Ka5yxoNPpaHW3VW6JIowrwFgSTZONxig==} - y-protocols@1.0.6: - resolution: {integrity: sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q==} - engines: {node: '>=16.0.0', npm: '>=8.0.0'} - peerDependencies: - yjs: ^13.0.0 - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -3042,10 +2880,6 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} - yjs@13.6.20: - resolution: {integrity: sha512-Z2YZI+SYqK7XdWlloI3lhMiKnCdFCVC4PchpdO+mCYwtiTwncjUbnRK9R1JmkNfdmHyDXuWN3ibJAt0wsqTbLQ==} - engines: {node: '>=16.0.0', npm: '>=8.0.0'} - zrender@5.6.0: resolution: {integrity: sha512-uzgraf4njmmHAbEUxMJ8Oxg+P3fT04O+9p7gY+wJRVxo8Ge+KmYv0WJev945EH4wFuc4OY2NLXz46FZrWS9xJg==} @@ -3827,108 +3661,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@jupyter/ydoc@3.0.1': - dependencies: - '@jupyterlab/nbformat': 4.3.1 - '@lumino/coreutils': 2.2.0 - '@lumino/disposable': 2.1.3 - '@lumino/signaling': 2.1.3 - y-protocols: 1.0.6(yjs@13.6.20) - yjs: 13.6.20 - - '@jupyterlab/coreutils@6.3.1': - dependencies: - '@lumino/coreutils': 2.2.0 - '@lumino/disposable': 2.1.3 - '@lumino/signaling': 2.1.3 - minimist: 1.2.8 - path-browserify: 1.0.1 - url-parse: 1.5.10 - - '@jupyterlab/nbformat@4.3.1': - dependencies: - '@lumino/coreutils': 2.2.0 - - '@jupyterlab/services@7.3.1(react@18.3.1)': - dependencies: - '@jupyter/ydoc': 3.0.1 - '@jupyterlab/coreutils': 6.3.1 - '@jupyterlab/nbformat': 4.3.1 - '@jupyterlab/settingregistry': 4.3.1(react@18.3.1) - '@jupyterlab/statedb': 4.3.1 - '@lumino/coreutils': 2.2.0 - '@lumino/disposable': 2.1.3 - '@lumino/polling': 2.1.3 - '@lumino/properties': 2.0.2 - '@lumino/signaling': 2.1.3 - ws: 8.18.0 - transitivePeerDependencies: - - bufferutil - - react - - utf-8-validate - - '@jupyterlab/settingregistry@4.3.1(react@18.3.1)': - dependencies: - '@jupyterlab/nbformat': 4.3.1 - '@jupyterlab/statedb': 4.3.1 - '@lumino/commands': 2.3.1 - '@lumino/coreutils': 2.2.0 - '@lumino/disposable': 2.1.3 - '@lumino/signaling': 2.1.3 - '@rjsf/utils': 5.22.4(react@18.3.1) - ajv: 8.17.1 - json5: 2.2.3 - react: 18.3.1 - - '@jupyterlab/statedb@4.3.1': - dependencies: - '@lumino/commands': 2.3.1 - '@lumino/coreutils': 2.2.0 - '@lumino/disposable': 2.1.3 - '@lumino/properties': 2.0.2 - '@lumino/signaling': 2.1.3 - - '@lumino/algorithm@2.0.2': {} - - '@lumino/commands@2.3.1': - dependencies: - '@lumino/algorithm': 2.0.2 - '@lumino/coreutils': 2.2.0 - '@lumino/disposable': 2.1.3 - '@lumino/domutils': 2.0.2 - '@lumino/keyboard': 2.0.2 - '@lumino/signaling': 2.1.3 - '@lumino/virtualdom': 2.0.2 - - '@lumino/coreutils@2.2.0': - dependencies: - '@lumino/algorithm': 2.0.2 - - '@lumino/disposable@2.1.3': - dependencies: - '@lumino/signaling': 2.1.3 - - '@lumino/domutils@2.0.2': {} - - '@lumino/keyboard@2.0.2': {} - - '@lumino/polling@2.1.3': - dependencies: - '@lumino/coreutils': 2.2.0 - '@lumino/disposable': 2.1.3 - '@lumino/signaling': 2.1.3 - - '@lumino/properties@2.0.2': {} - - '@lumino/signaling@2.1.3': - dependencies: - '@lumino/algorithm': 2.0.2 - '@lumino/coreutils': 2.2.0 - - '@lumino/virtualdom@2.0.2': - dependencies: - '@lumino/algorithm': 2.0.2 - '@mdx-js/mdx@2.3.0': dependencies: '@types/estree-jsx': 1.0.5 @@ -4029,15 +3761,6 @@ snapshots: '@qubit-rs/client@0.4.5': {} - '@rjsf/utils@5.22.4(react@18.3.1)': - dependencies: - json-schema-merge-allof: 0.8.1 - jsonpointer: 5.0.1 - lodash: 4.17.21 - lodash-es: 4.17.21 - react: 18.3.1 - react-is: 18.3.1 - '@rollup/pluginutils@5.2.0(rollup@4.53.2)': dependencies: '@types/estree': 1.0.6 @@ -4334,13 +4057,6 @@ snapshots: acorn@8.12.1: {} - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.0.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -4516,19 +4232,6 @@ snapshots: commander@8.3.0: {} - compute-gcd@1.2.1: - dependencies: - validate.io-array: 1.0.6 - validate.io-function: 1.0.2 - validate.io-integer-array: 1.0.0 - - compute-lcm@1.1.2: - dependencies: - compute-gcd: 1.2.1 - validate.io-array: 1.0.6 - validate.io-function: 1.0.2 - validate.io-integer-array: 1.0.0 - concat-map@0.0.1: {} convert-source-map@2.0.0: {} @@ -4705,16 +4408,12 @@ snapshots: extend@3.0.2: {} - fast-deep-equal@3.1.3: {} - fast-equals@5.2.2: {} fast-json-patch@3.1.1: {} fast-sha256@1.3.0: {} - fast-uri@3.0.3: {} - faye-websocket@0.11.4: dependencies: websocket-driver: 0.7.4 @@ -5049,8 +4748,6 @@ snapshots: dependencies: ws: 8.18.3 - isomorphic.js@0.2.5: {} - jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -5072,50 +4769,24 @@ snapshots: jsesc@3.0.2: {} - json-schema-compare@0.2.2: - dependencies: - lodash: 4.17.21 - - json-schema-merge-allof@0.8.1: - dependencies: - compute-lcm: 1.1.2 - json-schema-compare: 0.2.2 - lodash: 4.17.21 - - json-schema-traverse@1.0.0: {} - json5@2.2.3: {} - jsonpointer@5.0.1: {} - katex@0.16.22: dependencies: commander: 8.3.0 kleur@4.1.5: {} - lib0@0.2.98: - dependencies: - isomorphic.js: 0.2.5 - linkify-it@5.0.0: dependencies: uc.micro: 2.1.0 - lodash-es@4.17.21: {} - lodash.camelcase@4.3.0: {} - lodash@4.17.21: {} - long@5.2.3: {} longest-streak@3.1.0: {} - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - lru-cache@10.4.3: {} lru-cache@5.1.1: @@ -5793,8 +5464,6 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minimist@1.2.8: {} - minipass@3.3.6: dependencies: yallist: 4.0.0 @@ -5858,8 +5527,6 @@ snapshots: dependencies: entities: 4.5.0 - path-browserify@1.0.1: {} - path-is-absolute@1.0.1: {} path-key@3.1.1: {} @@ -6011,16 +5678,10 @@ snapshots: punycode.js@2.3.1: {} - querystringify@2.2.0: {} - raf-schd@4.0.3: {} react-is@18.3.1: {} - react@18.3.1: - dependencies: - loose-envify: 1.4.0 - readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -6140,10 +5801,6 @@ snapshots: require-directory@2.1.1: {} - require-from-string@2.0.2: {} - - requires-port@1.0.0: {} - rimraf@3.0.2: dependencies: glob: 7.2.3 @@ -6479,11 +6136,6 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.0 - url-parse@1.5.10: - dependencies: - querystringify: 2.2.0 - requires-port: 1.0.0 - util-deprecate@1.0.2: {} uuid@13.0.0: {} @@ -6503,21 +6155,6 @@ snapshots: validate-html-nesting@1.2.2: {} - validate.io-array@1.0.6: {} - - validate.io-function@1.0.2: {} - - validate.io-integer-array@1.0.0: - dependencies: - validate.io-array: 1.0.6 - validate.io-integer: 1.0.5 - - validate.io-integer@1.0.5: - dependencies: - validate.io-number: 1.0.3 - - validate.io-number@1.0.3: {} - vfile-location@5.0.3: dependencies: '@types/unist': 3.0.3 @@ -6661,17 +6298,10 @@ snapshots: wrappy@1.0.2: {} - ws@8.18.0: {} - ws@8.18.3: {} xstate@5.20.1: {} - y-protocols@1.0.6(yjs@13.6.20): - dependencies: - lib0: 0.2.98 - yjs: 13.6.20 - y18n@5.0.8: {} yallist@3.1.1: {} @@ -6692,13 +6322,8 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yjs@13.6.20: - dependencies: - lib0: 0.2.98 - zrender@5.6.0: dependencies: tslib: 2.3.0 zwitch@2.0.4: {} - \ No newline at end of file diff --git a/packages/frontend/src/stdlib/analyses/decapodes.tsx b/packages/frontend/src/stdlib/analyses/decapodes.tsx index 9e22ff324..612087941 100644 --- a/packages/frontend/src/stdlib/analyses/decapodes.tsx +++ b/packages/frontend/src/stdlib/analyses/decapodes.tsx @@ -1,6 +1,6 @@ import Loader from "lucide-solid/icons/loader"; import RotateCcw from "lucide-solid/icons/rotate-ccw"; -import { createMemo, For, Match, Show, Switch } from "solid-js"; +import { createMemo, createResource, For, Match, Show, Switch } from "solid-js"; import { BlockTitle, @@ -15,9 +15,7 @@ import { import type { ModelDiagramPresentation, ModelPresentation, QualifiedName } from "catlog-wasm"; import type { DiagramAnalysisProps } from "../../analysis"; import type { LiveDiagramDoc } from "../../diagram"; -import { uniqueIndexArray } from "../../util/indexing"; -import { PDEPlot2D, type PDEPlotData2D } from "../../visualization"; -import { createJuliaKernel, executeAndRetrieve } from "./jupyter"; +import { PDEPlot2D } from "../../visualization"; import type { DecapodesAnalysisContent } from "./simulator_types"; import "./decapodes.css"; @@ -26,37 +24,13 @@ import "./simulation.css"; /** Analyze a DEC diagram by performing a simulation using Decapodes.jl. */ export default function Decapodes(props: DiagramAnalysisProps) { // Step 1: Start the Julia kernel. - const [kernel, restartKernel] = createJuliaKernel({ - baseUrl: "http://127.0.0.1:8888", - token: "", - }); + const [kernel, { refetch: restartKernel }] = createResource(() => undefined); // Step 2: Run initialization code in the kernel. - const startedKernel = () => (kernel.error ? undefined : kernel()); - - const [options] = executeAndRetrieve( - startedKernel, - makeInitCode, - (options: SimulationOptions) => ({ - domains: uniqueIndexArray(options.domains, (domain) => domain.name), - }), - ); + const [options] = createResource(() => undefined); // Step 3: Run the simulation in the kernel! - const initedKernel = () => - kernel.error || options.error || options.loading ? undefined : kernel(); - - const [result, rerunSimulation] = executeAndRetrieve( - initedKernel, - () => { - const simulationData = makeSimulationData(props.liveDiagram, props.content); - if (!simulationData) { - return undefined; - } - return makeSimulationCode(simulationData); - }, - (data: PDEPlotData2D) => data, - ); + const [result, { refetch: rerunSimulation }] = createResource(() => undefined); const elaboratedModel = () => props.liveDiagram.liveModel.elaboratedModel(); const elaboratedDiagram = () => props.liveDiagram.elaboratedDiagram(); @@ -103,7 +77,8 @@ export default function Decapodes(props: DiagramAnalysisProps props.content.initialConditions[id] ?? null, setContent: (id, value) => @@ -170,7 +145,8 @@ export default function Decapodes(props: DiagramAnalysisProps - {(options) => DomainConfig(options().domains)} + + {(_options) => { + //DomainConfig(options().domains) + return DomainConfig(new Map()); + }} +
@@ -294,39 +275,8 @@ type SimulationData = { duration: number; }; -/** Julia code run after kernel is started. */ -const makeInitCode = () => - ` - for k in keys(Base.text_colors) - Base.text_colors[k] = "" - end - - import IJulia - import JSON3 - IJulia.register_jsonmime(MIME"application/json"()) - using CatColabInterop - - JsonValue(supported_decapodes_geometries()) - `; - -/** Julia code run to perform a simulation. */ -const makeSimulationCode = (data: SimulationData) => - ` - # needed for returning large amounts of data, should be paired with a similar setting on the jupyter server - IJulia.set_max_stdio(1_000_000_000) - - simulation = DecapodeSimulation(raw"""${JSON.stringify(data)}"""); - simulator = evalsim(simulation.pode); - - f = simulator(simulation.geometry.dualmesh, simulation.generate, DiagonalHodge()); - - result = run(f, simulation, ComponentArray(k=0.5,)) - - JSON3.write(stdout, result) - `; - /** Create data to send to the Julia kernel. */ -const makeSimulationData = ( +export const makeSimulationData = ( liveDiagram: LiveDiagramDoc, content: DecapodesAnalysisContent, ): SimulationData | undefined => { diff --git a/packages/frontend/src/stdlib/analyses/jupyter.ts b/packages/frontend/src/stdlib/analyses/jupyter.ts deleted file mode 100644 index 446607a6c..000000000 --- a/packages/frontend/src/stdlib/analyses/jupyter.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { type ServerConnection, SessionManager } from "@jupyterlab/services"; -import type { IKernelConnection, IKernelOptions } from "@jupyterlab/services/lib/kernel/kernel"; -import type { ISessionConnection } from "@jupyterlab/services/lib/session/session"; -import { - type Accessor, - createResource, - onCleanup, - type Resource, - type ResourceReturn, -} from "solid-js"; - -type ResourceRefetch = ResourceReturn[1]["refetch"]; - -type ServerSettings = Parameters[0]; - -/** Create a Jupyter kernel in a reactive context. - -Returns a kernel as a Solid.js resource and a callback to restart the kernel. -The kernel is automatically shut down when the component is unmounted. - */ -export function createKernel( - serverOptions: ServerSettings, - kernelOptions: IKernelOptions, -): [Resource, ResourceRefetch] { - let session: ISessionConnection | undefined; - - const [kernel, { refetch: restartKernel }] = createResource(async () => { - const jupyter = await import("@jupyterlab/services"); - - const serverSettings = jupyter.ServerConnection.makeSettings(serverOptions); - - const kernelManager = new jupyter.KernelManager({ serverSettings }); - const sessionManager = new SessionManager({ - serverSettings, - kernelManager, - }); - - session = await sessionManager.startNew({ - name: "remote-api", - path: "remote-api.ipynb", - type: "notebook", - kernel: kernelOptions, - }); - - if (!session.kernel) { - throw new Error("session has not kernel?"); - } - - const kernel = session.kernel; - - // Useful for debugging jupyter stuff - // const t0 = Date.now(); - // kernel.anyMessage.connect((_, msg) => { - // console.log( - // "[Jupyter message]", - // (Date.now() - t0) / 1000, - // msg.direction, - // msg.msg.header.msg_type, - // ); - // }); - - return kernel; - }); - - onCleanup(() => { - if (session) { - session.shutdown(); - } - }); - - return [kernel, restartKernel]; -} - -/** Create a Julia kernel in a reactive context. */ -export function createJuliaKernel(serverOptions: ServerSettings) { - // XXX: How do we know... - // - which Julia version to use? - // - whether to use the standard kernel or one with our custom sys image? - // For now, we are omitting the kernel name completely and thus assuming - // that the correct default kernel has been set on the Jupyter server. - // Obviously this approach will not extend to multiple languages. - return createKernel(serverOptions, { - //name: "julia-1.11", - }); -} - -/** Execute code in a Jupyter kernel and retrieve JSON data reactively. - -Assumes that the computation will return JSON data using the "application/json" -MIME type in Jupyter. Returns the post-processed data as a Solid.js resource and -a callback to rerun the computation. - -The resource depends reactively on the kernel: if the kernel changes, the code -will be automatically re-executed. It does *not* depend reactively on the code. -If the code changes, it must be rerun manually. - */ -export function executeAndRetrieve( - kernel: Accessor, - executeCode: Accessor, - postprocess: (data: S) => T, -): [Resource, ResourceRefetch] { - const [data, { refetch: reexecute }] = createResource(kernel, async (kernel) => { - // Request that kernel execute code, if defined. - const code = executeCode(); - if (code === undefined) { - return undefined; - } - - const future = kernel.requestExecute({ code }); - - // Set up handler for result from kernel. - // XXX: we are abusing message types to exfiltrate data - let result: { data: S } | undefined; - let streamedResult = ""; - const error: string | undefined = undefined; - future.onIOPub = (msg) => { - if (msg.parent_header.msg_id !== future.msg.header.msg_id) { - return; - } - - // this catches any print statements, which may be broken up into an arbitrary number of - // messages. To return large data stringify the JSON result and `println` it. If this method is used, - // ensure that no other `print` statements are used, as they will also be collected here. - if (msg.header.msg_type === "stream") { - // biome-ignore lint/suspicious/noExplicitAny: this should type narrow, but doesn't - const text = (msg.content as any).text; - if (text) { - streamedResult += text; - } - } - - // In this case msg_type "stream" will be collected but not used. This only works for - // relatively small amounts of data, it could be the case that nothing should be returned - // like this. The json serialization done by IJulia appears to be cripplingly slow for - // unknown reasons. - // - // This allows returning something while still being able to inspect print statements from - // the client. - if (msg.header.msg_type === "execute_result") { - const content = msg.content as JsonDataContent; - const data = content["data"]?.["application/json"]; - if (data) { - result = { data }; - } - } - }; - - // Wait for execution to finish and process result. - const reply = await future.done; - - if (error) { - throw new Error(error); - } - - if (reply.content.status === "abort") { - throw new Error("Execution was aborted"); - } - if (reply.content.status === "error") { - // Trackback list already includes `reply.content.evalue`. - const msg = reply.content.traceback.join("\n"); - throw new Error(msg); - } - - if (!result && streamedResult) { - result = { data: JSON.parse(streamedResult) }; - } - - if (result === undefined) { - throw new Error("Data was not received from the kernel"); - } - return postprocess(result.data); - }); - - return [data, reexecute]; -} - -/** JSON data returned from a Jupyter kernel. */ -type JsonDataContent = { - data?: { - "application/json"?: T; - }; -};