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..dd37a4707 100644 --- a/packages/algjulia-interop/README.md +++ b/packages/algjulia-interop/README.md @@ -1,47 +1,39 @@ # 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 `]` (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: -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..34fe01fde --- /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, ids::Dict{String, Symbol}, names::Dict{Symbol, Vector{String}} + )::AbstractDict + 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 + +""" +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, 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, ids, 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..115a0e018 --- /dev/null +++ b/packages/algjulia-interop/scripts/endpoint.jl @@ -0,0 +1,50 @@ + +# 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) + r.headers = CORS_HEADERS + 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/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 450cac1b6..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,10 +6322,6 @@ 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 diff --git a/packages/frontend/src/stdlib/analyses.tsx b/packages/frontend/src/stdlib/analyses.tsx index 33d9b37fa..5bbdf5ddc 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: () => ({}), +}); + +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..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) - - system = Analysis(ThDecapode(), raw"""${JSON.stringify(data)}"""); - simulator = evalsim(system.pode); - - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()); - - soln = run_sim(f, system.init, system.duration, ComponentArray(k=0.5,)); - - JSON3.write(stdout, SimResult(soln, system)) - `; - /** 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; - }; -}; 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..17f64090f --- /dev/null +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -0,0 +1,131 @@ +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 "./tabular_view.css"; + +/** 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 && ( + + + + {(header) => } + + + + )} + + + {(row) => ( + + + {(cell) => } + + + )} + + +
{header}
{cell}
+ ); +} + +/** Stack tables on top of each other in a naive way, one per ob/attrtype */ +function ACSetTableView(props: { model: DblModel; rawdata: Record }) { + return ( +
+ + + {(ob) => } + +
+ ); +} + +/** 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. + */ +export default function TabularView( + props: DiagramAnalysisProps> & { + title?: string; + }, +) { + const [res] = createResource( + () => { + const model = props.liveDiagram.liveModel.elaboratedModel(); + const diagram = props.liveDiagram.elaboratedDiagram(); + if (model && diagram) { + return { model, diagram }; + } + }, + + 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: model.presentation(), + diagram: diagram.presentation(), + }), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return { model, data: await response.json() }; + }, + ); + return ( + + + +
⏳ Loading model...
+
+ +
❌ Error loading model: {res.error?.message || "Unknown error"}
+
+ + {(data) => { + const result = data(); + return ; + }} + +
+ ); +} diff --git a/packages/frontend/src/stdlib/theories/simple-schema.ts b/packages/frontend/src/stdlib/theories/simple-schema.ts index 4bf73401c..4897f4be6 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 { 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,7 +7,25 @@ import textStyles from "../text_styles.module.css"; export default function createSchemaTheory(theoryMeta: TheoryMeta): Theory { const thSchema = new ThSchema(); + const diagramAnalyses: DiagramAnalysisMeta[] = [ + 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,13 +133,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", - }), - ], + diagramAnalyses: diagramAnalyses, }); }