Fast, general-purpose interactive applications for dynamical systems of all kinds, including ODEs, maps, billiards, agent-based-models.
All information is present in the docs.
Fast, general-purpose interactive applications for complex systems
Home Page: https://juliadynamics.github.io/InteractiveDynamics.jl/dev/
License: MIT License
The Maze-Runner has an off-by one issue in its plotting.
Here's the discrepancy:
heatmap!(ax, walkmap(model); colormap=:grays)
ax.limits
#Observable{GeometryBasics.HyperRectangle{2, Float32}} with 4 listeners. Value:
#GeometryBasics.HyperRectangle{2, Float32}(Float32[0.0, 0.0], Float32[41.0, 41.0])
o, e = modellims(model)
#((0, 0), (42, 42))
modellims
adds one to the bounding box. I believe we do this so that the markers have some breathing room: (0,0) also will not have any markers in it.
Should we do something about this margin when static_preplot! !== nothing
, or just get the user to resize limits to their liking?
Here's a MWE pulled almost entirely from the AgentsZoo example page.
According to this page https://juliadynamics.github.io/InteractiveDynamics.jl/dev/agents/#InteractiveDynamics.abmexploration
"Clicking the "reset" button will add a red vertical line to the data plots for visual guidance." But this doesn't happen for me.
I'm running InteractiveDynamics v0.21.11, Agents v5.4.3.
using InteractiveDynamics, Agents
using GLMakie
daisypath = joinpath(dirname(pathof(InteractiveDynamics)), "agents", "daisyworld_def.jl")
include(daisypath)
model, daisy_step!, daisyworld_step! = daisyworld(;
solar_luminosity = 1.0, solar_change = 0.0, scenario = :change
)
daisycolor(a::Daisy) = a.breed # color of agents
as = 20 # size of agents
am = '✿' # marker of agents
params = Dict(
:surface_albedo => 0:0.01:1,
:solar_change => -0.1:0.01:0.1,
)
heatarray = :temperature
heatkwargs = (colorrange = (-20, 60), colormap = :thermal)
plotkwargs = (;
ac = daisycolor, as, am,
scatterkwargs = (strokewidth = 1.0,),
heatarray, heatkwargs
)
using Statistics: mean
black(a) = a.breed == :black
white(a) = a.breed == :white
adata = [(black, count), (white, count)]
temperature(model) = mean(model.temperature)
mdata = [temperature, :solar_luminosity]
fig, abmobs = abmexploration(model;
agent_step! = daisy_step!, model_step! = daisyworld_step!, params, plotkwargs...,
adata, alabels = ["Black daisys", "White daisys"], mdata, mlabels = ["T", "L"]
)
display(fig)
if !isinteractive()
println("Keeping process alive so that the Makie window doesn't close... Press ENTER to kill...")
readline()
end
Hi,
First, thx for this amazing package! I have started to use quite a bit for my nonlinear dynamics class. I recently installed Julia and all the packages of my new laptop and I'm running into a small problem whenever using interactive_orbitdiagram
. Here is a minimal example:
# --> Sets up the parameters.
i = p_index = 1
ds, r_min, r_max, parname = Systems.logistic(), 1, 4, "μ"
title = "Orbit diagram"
# --> Plot the orbit diagram
interactive_orbitdiagram(ds, p_index, r_min, r_max, i ; parname=parname, title=title)
Whenever I run it, I get the following error:
ERROR: UndefVarError: hbox! not defined
Stacktrace:
[1] add_controls!(controllayout::GridLayout, scene::Scene, D::Int64, parname::String, i0::Int64)
@ InteractiveChaos ~/.julia/packages/InteractiveChaos/JO3KW/src/chaos/orbitdiagram.jl:311
[2] interactive_orbitdiagram(ds::DiscreteDynamicalSystem{false, Float64, 1, typeof(DynamicalSystemsBase.Systems.logistic_rule), Vector{Float64}, typeof(DynamicalSystemsBase.Systems.logistic_jacob), Float64, false}, p_index::Int64, p_min::Int64, p_max::Int64, i0::Int64; u0::Float64, parname::String, title::String)
@ InteractiveChaos ~/.julia/packages/InteractiveChaos/JO3KW/src/chaos/orbitdiagram.jl:64
[3] top-level scope
@ REPL[5]:1
The Makie
window opens up correctly but the buttons are all messed up and nothing is plotted.
For info, I am using Julia 1.8.4
along with
DynamicalSystems v2.3.2
GLMakie v0.1.30
InteractiveChaos v0.12.3
I'm not sure what the problem is. It seems to me that, whenever I install InteractiveChaos
, GLMakie
is downdated to 0.1.30 even though it was initially v0.8 or something. Note however that I have no problem when running interactive_cobweb
for instance.
While exploring my ABMs, I often find myself updating parameters and resetting the model over and over again. Because of this, I'd like an ability to reset the whole view of the interactive app, i.e. having completely "blank" plots and a fresh view of the space and so on.
This could be done either via a new clear
button or by extending the functionality of the existing reset
button. Currently reset
resets the underlying model to its initial state and draws a red vertical line in the plots after which the new series are drawn. Was this just a temporary workaround or was it a deliberate design decision to never completely clear the plots? Which option would you prefer - a new button or changing how the existing one works? Would love to hear your thoughts on this.
https://juliadynamics.github.io/Agents.jl/stable/examples/predator_prey_fast/
Offsets are not considered at all currently, so plots end up looking cut off, e.g.:
I have this code
using DifferentialEquations, DynamicalSystems, InteractiveDynamics, GLMakie
ds = Systems.lorenz()
u1 = [10,20,40.0]
u2 = [10,20,40.0 + 1e-3]
u3 = [20,10,40.0]
u0s = [u1, u2, u3]
idxs = (1, 2, 3)
diffeq = (alg = Tsit5(), dtmax = 0.01)
figure, obs = interactive_evolution_timeseries(
ds, u0s; idxs, tail=1000, diffeq
)
Yesterday it worked fine, however today, from the last update to 0.117, it doesn't work. The error thrown says:
ERROR: LoadError: UndefVarError: ax not defined
Stacktrace:
[1] init_main_trajectory_plot(ds::ContinuousDynamicalSystem{false, SVector{3, Float64}, 3, typeof(DynamicalSystemsBase.Systems.loop), Vector{Float64}, typeof(DynamicalSystemsBase.Systems.loop_jac), SMatrix{3, 3, Float64, 9}, false}, fig::Figure, idxs::SVector{3, Int64}, lims::Tuple{Tuple{Float64, Float64}, Tuple{Float64, Float64}, Tuple{Float64, Float64}}, pinteg::OrdinaryDiffEq.ODEIntegrator{Tsit5, true, Vector{SVector{3, Float64}}, Nothing, Float64, Vector{Float64}, Float64, Float64, Float64, Float64, Vector{Vector{SVector{3, Float64}}}, ODESolution{SVector{3, Float64}, 2, Vector{Vector{SVector{3, Float64}}}, Nothing, Nothing, Vector{Float64}, Vector{Vector{Vector{SVector{3, Float64}}}}, ODEProblem{Vector{SVector{3, Float64}}, Tuple{Float64, Float64}, true, Vector{Float64}, ODEFunction{true, DynamicalSystemsBase.var"#29#30"{ContinuousDynamicalSystem{false, SVector{3, Float64}, 3, typeof(DynamicalSystemsBase.Systems.loop), Vector{Float64}, typeof(DynamicalSystemsBase.Systems.loop_jac), SMatrix{3, 3, Float64, 9}, false}, Int64}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, SciMLBase.StandardODEProblem}, Tsit5, OrdinaryDiffEq.InterpolationData{ODEFunction{true, DynamicalSystemsBase.var"#29#30"{ContinuousDynamicalSystem{false, SVector{3, Float64}, 3, typeof(DynamicalSystemsBase.Systems.loop), Vector{Float64}, typeof(DynamicalSystemsBase.Systems.loop_jac), SMatrix{3, 3, Float64, 9}, false}, Int64}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, Vector{Vector{SVector{3, Float64}}}, Vector{Float64}, Vector{Vector{Vector{SVector{3, Float64}}}}, OrdinaryDiffEq.Tsit5Cache{Vector{SVector{3, Float64}}, Vector{SVector{3, Float64}}, Vector{SVector{3, Float64}}, OrdinaryDiffEq.Tsit5ConstantCache{Float64, Float64}}}, DiffEqBase.DEStats}, ODEFunction{true, DynamicalSystemsBase.var"#29#30"{ContinuousDynamicalSystem{false, SVector{3, Float64}, 3, typeof(DynamicalSystemsBase.Systems.loop), Vector{Float64}, typeof(DynamicalSystemsBase.Systems.loop_jac), SMatrix{3, 3, Float64, 9}, false}, Int64}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, OrdinaryDiffEq.Tsit5Cache{Vector{SVector{3, Float64}}, Vector{SVector{3, Float64}}, Vector{SVector{3, Float64}}, OrdinaryDiffEq.Tsit5ConstantCache{Float64, Float64}}, OrdinaryDiffEq.DEOptions{Float64, Float64, Float64, Float64, PIController{Rational{Int64}}, typeof(DynamicalSystemsBase._parallelnorm), typeof(LinearAlgebra.opnorm), Nothing, CallbackSet{Tuple{}, Tuple{}}, typeof(DiffEqBase.ODE_DEFAULT_ISOUTOFDOMAIN), typeof(DiffEqBase.ODE_DEFAULT_PROG_MESSAGE), typeof(DiffEqBase.ODE_DEFAULT_UNSTABLE_CHECK), DataStructures.BinaryMinHeap{Float64}, DataStructures.BinaryMinHeap{Float64}, Nothing, Nothing, Int64, Tuple{}, Tuple{}, Tuple{}}, Vector{SVector{3, Float64}}, Float64, Nothing, OrdinaryDiffEq.DefaultInit}, colors::Vector{ColorTypes.RGBA{Float32}}, obs::Vector{Observable}, plotkwargs::NamedTuple{(), Tuple{}}, finalpoints::Observable{Vector{Point{3, Float32}}}, m::Float64)
@ InteractiveDynamics ~/.julia/packages/InteractiveDynamics/SoHDO/src/chaos/trajanim.jl:130
[2] interactive_evolution_timeseries(ds::ContinuousDynamicalSystem{false, SVector{3, Float64}, 3, typeof(DynamicalSystemsBase.Systems.loop), Vector{Float64}, typeof(DynamicalSystemsBase.Systems.loop_jac), SMatrix{3, 3, Float64, 9}, false}, u0s::Vector{Vector{Float64}}, ps::Nothing; transform::typeof(identity), idxs::Tuple{Int64, Int64, Int64}, colors::Vector{ColorTypes.RGBA{Float32}}, tail::Int64, diffeq::NamedTuple{(:alg, :dtmax), Tuple{Tsit5, Float64}}, plotkwargs::NamedTuple{(), Tuple{}}, m::Float64, lims::Tuple{Tuple{Float64, Float64}, Tuple{Float64, Float64}, Tuple{Float64, Float64}}, total_span::Int64, linekwargs::NamedTuple{(:linewidth,), Tuple{Int64}}, pnames::Nothing)
@ InteractiveDynamics ~/.julia/packages/InteractiveDynamics/SoHDO/src/chaos/trajanim.jl:209
[3] top-level scope
@ /media/data/documents/code/Julia/testing_glmakie.jl:15
in expression starting at /media/data/documents/code/Julia/testing_glmakie.jl:15
The version of the involved packages is
DynamicalSystems v2.0.1
GLMakie v0.4.4
InteractiveDynamics v0.17.0
We now have uniform look for 2D and 3D: http://makie.juliaplots.org/stable/makielayout/axis3.html
Would be nice to update examples that use 3D into the new feel. Will probably also simplify source code.
I am testing the package with a ContinuousSpace model and want to plot some data in the interactive widget.
So I define the following model which I've simplified a bit:
mutable struct MyAgent <: AbstractAgent
id::Int
pos::Tuple{Float64, Float64}
vel::Tuple{Float64, Float64}
money::Float64
transfer::Float64
end
# model, stepping functions and definitions of ac and am go here
adata = [(:money, sum), (:transfer, sum)]
alabels = ["Aggregate money", "Aggregate transfers"]
interactive_abm(
model, agent_step!, dummystep, params;
ac = ac, as = 0.02, am = am,
adata = adata, alabels = alabels
)
When I execute this, I get the following error message:
ERROR: LoadError: MethodError: no method matching (::Colon)(::Nothing, ::Int64, ::Int64)
What exactly went wrong here?
There's a very long stacktrace which I'm so far unable to see through.
The interactive_abm function starts perfectly fine when I don't define adata
and alabels
so I don't expect it to be a problem with the model itself.
In case of using GLMakie
, function abmvideo
used to show live video of the simulation while recording it to a file. However after getting the latest version of the InteractiveDynamics, the live animation doesn't appear. Is there any setting to tune to get back the live video?
Maybe related: before the last version, abmplot
used to show the plot by default but now I need to call the first value of its returned tuple, which is the desired figure.
Hi, after I load InteractiveChaos
, I have no access to the function interactive_abm
, does anyone know why this happens?
I’m trying to duplicate the first example of trajectory evolution in the docs for the InteractiveDynamcis package (https://juliadynamics.github.io/InteractiveDynamics.jl/dev/trajectory/).
I’ve already created an environment into which I’ve added InteractiveDynamics
, DynamicalSystems
, GLMakie
, and OrdinaryDiffEq
.
In that environment, I executed:
using InteractiveDynamics
using DynamicalSystems, GLMakie
using OrdinaryDiffEq
But when I try to execute next…
ds = Systems.henonheiles()
… I get error:
ERROR: UndefVarError: Systems not defined
Stacktrace:
[1] top-level scope
What is Systems
?
I tried to add a package named Systems
but no such package was found.
I think the below as(a)
in the docstring of abm_plot function in /src/agents/plots_video.jl should be am(a)
because it sets markers' shape. As a newbie user, it was confusing slightly.
Before
# ac = "#338c54"
ac(a) = a.status == :S ? "#2b2b33" : a.status == :I ? "#bf2642" : "#338c54"
# as = 10
as(a) = 10*randn() + 1
# as = :diamond
as(a) = a.status == :S ? :circle : a.status == :I ? :diamond : :rect
After
# ac = "#338c54"
ac(a) = a.status == :S ? "#2b2b33" : a.status == :I ? "#bf2642" : "#338c54"
# as = 10
as(a) = 10*randn() + 1
# am = :diamond
am(a) = a.status == :S ? :circle : a.status == :I ? :diamond : :rect
Would be nice to extend this function to accept multiple input datasets, all of which are plotted at the same time but with different color, and the poincare section of all of which is also plotted with different colors (but all from the same plane).
This is easy to do.
At the moment this package is not really tested. Problem is, I don't even know how to test it on CI. I've been advised to copy Makie tests, but I'm not sure what to do!
JuliaDynamics/Agents.jl#502 identified a reproducibility issue in the data collection system, now that that is fixed there is also one in plotting.
If Scheduler.randomly
is used to plot things, we alter the internal state of the model and therefore mutate the models expected output too.
Problem is this call to the scheduler.
A default colorscheme, that uses current colormap of JuliaDynamics should be implemented and used where most random colors are used now.
Right now the adata
keyword in abm_data_exploration
requires an aggregating function. I'm interested in how to visualize unaggregated agent data per step, as done for instance in the HK example. More specifically, I'm interested in when collecting the agent-wise data applying a function and plot the evolution of the output of that function for each agent (so it is not only capturing a field value, but also doing some transformation on it and then visualizing it). I suppose I could do so in a custom plot, but I haven't been able to come up with such a code (and this may then be actually a Makie question).
The documentation of Agents.jl states that interactive applications of Agents.jl work for any agent based model
. So I went ahead and tried it with two different GraphSpace()
models and found out that this doesn't work.
interactive_abm()
throws the following error in both cases:
MethodError: no method matching size(::GraphSpace{SimpleDiGraph{Int64}})
Closest candidates are:
size(!Matched::BitArray{1}) at bitarray.jl:99
size(!Matched::BitArray{1}, !Matched::Integer) at bitarray.jl:103
size(!Matched::Core.Compiler.StmtRange) at show.jl:1849
...
What could be done to make this work? Do you need any more information to understand the case?
Thanks in advance!
I plan to create a simple function called bdstep!(special_structure, bd, dt)
that steps all plotted particles for amount of time dt
in the billiard. This would make making any kind custom user animations trivial. Similarly with how animating works for Agents.jl , this special_structure
will contain both the particles, their observables, as well as plotted elements, and will simplify low-level interface dramatically. So one would do something as trivial as
special_strucutre = init_particle_obs(ps, bd, plotting arguments...)
bdstep!(specialstrucutre, bd, dt) # takes care of literally everything
using InteractiveChaos, Makie
i = 1
p_index = 1
systems = [(Systems.logistic(), 3.0, 4.0, "r"),
(Systems.henon(), 0.8, 1.4, "a"),
(Systems.standardmap(), 0.6, 1.2, "k")]
ds, p_min, p_max, parname = systems[1]
oddata = interactive_orbitdiagram(
ds, i, p_index, p_min, p_max;
parname = parname
)
Then I zoomed really deep, and then suddenly the orbit diagram window closed. The control window is still up. The error message in the terminal is:
┌ Error: Error in renderloop!
│ exception = GLFWError (PLATFORM_ERROR): WGL: Failed to make context current: The handle is invalid.
└ @ GLMakie C:\Users\DeadScholar\.julia\packages\GLMakie\XqcM3\src\rendering.jl:19
┌ Error: Error in renderloop!
│ exception = GLFWError (PLATFORM_ERROR): WGL: Failed to make context current: The handle is invalid.
└ @ GLMakie C:\Users\DeadScholar\.julia\packages\GLMakie\XqcM3\src\rendering.jl:24
I'm using this on Windows 10, Julia 1.3.1, and packages
[c52e3926] Atom v0.11.3
[ecbce9bc] BenchmarkProfiles v0.3.0
[6e4b80f9] BenchmarkTools v0.4.3
[ad839575] Blink v0.12.1
[336ed68f] CSV v0.5.21
[608a59af] ChaosTools v1.8.3
[3da002f7] ColorTypes v0.9.0
[5ae59095] Colors v0.11.1
[a81c6b42] Compose v0.7.3
[8f4d0f93] Conda v1.3.0
[a93c6f00] DataFrames v0.20.0
[31a5f54b] Debugger v0.6.2
[5732040d] DelayEmbeddings v1.3.0
[2b5f629d] DiffEqBase v6.10.0
[0c46a032] DifferentialEquations v6.9.0
[31c24e10] Distributions v0.21.12
[61744808] DynamicalSystems v1.3.0
[6e36e845] DynamicalSystemsBase v1.5.0
[7876af07] Example v0.5.3
[7a1cc6ca] FFTW v1.2.0
[587475ba] Flux v0.8.3
[f6369f11] ForwardDiff v0.10.8
[cd3eb016] HTTP v0.8.8
[0e44f5e4] Hwloc v1.0.3
[7073ff75] IJulia v1.20.2
[6218d12a] ImageMagick v1.1.1
[916415d5] Images v0.20.0
[c601a237] Interact v0.10.3
[81850811] InteractiveChaos v0.3.2
[4076af6c] JuMP v0.20.1
[e5e0dc1b] Juno v0.7.2
[1902f260] Knet v1.3.2
[b964fa9f] LaTeXStrings v1.0.3
[2ee39098] LabelledArrays v1.0.0
[ee78f7c6] Makie v0.9.5
[66fc600b] ModernGL v1.1.2
[47be7bcc] ORCA v0.3.1
[510215fc] Observables v0.2.3
[5fb14364] OhMyREPL v0.5.3
[1dea7af3] OrdinaryDiffEq v5.26.7
[149e707d] PkgDev v1.2.0
[f0f68f2c] PlotlyJS v0.13.0
[91a5bcdd] Plots v0.28.4
[c46f51b8] ProfileView v0.5.2
[92933f4c] ProgressMeter v1.2.0
[438e738f] PyCall v1.91.2
[d330b81b] PyPlot v2.8.2
[ce6b1742] RDatasets v0.6.6
[639c3291] RecurrenceAnalysis v1.0.3
[295af30f] Revise v2.5.0
[05bca326] SimpleDiffEq v1.0.2
[90137ffa] StaticArrays v0.12.1
[2913bbd2] StatsBase v0.32.0
[24249f21] SymPy v1.0.10
[fce5fe82] Turing v0.7.4
[b8865327] UnicodePlots v1.1.0
[0f1e0344] WebIO v0.8.13
[e88e6eb3] Zygote v0.4.3
[3fa0cd96] REPL
https://discourse.julialang.org/t/ann-makie-v-0-13/61522
TODOs:
AbstractPlotting
with Makie
heatmap
doesn't give us any off-by-one issuesUnsure if we should allow this or not, but the Agents.jl Opinion Spread example uses its rununtil
stopping function to break the animation loop. Can/should we allow this? Or is there a way to do this with a custom scheduler
perhaps?
Hej,
My bad for my previous issue with the old package name! I have now updated to InteractiveDynamics.jl v0.21.12
but I run into a different error. Whenever running the orbitdiagram.jl
script from the folder example, it fails with the following error
ERROR: LoadError: Circle{Float32}(Float32[0.0, 0.0], 1.0f0) is not a valid scatter marker shape.
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:35
[2] marker_to_sdf_shape(x::Circle{Float32})
@ Makie ~/.julia/packages/Makie/gAmAB/src/utilities/texture_atlas.jl:416
[3] (::GLMakie.var"#185#192")(m::Circle{Float32})
@ GLMakie ~/.julia/packages/GLMakie/N16Fq/src/drawing_primitives.jl:219
[4] #map#13
@ ~/.julia/packages/Observables/PHGQ8/src/Observables.jl:564 [inlined]
[5] map(::GLMakie.var"#185#192", ::Observable{Circle{Float32}})
@ Observables ~/.julia/packages/Observables/PHGQ8/src/Observables.jl:562
[6] (::GLMakie.var"#182#189"{GLMakie.Screen{GLFW.Window}, Scene, Scatter{Tuple{Vector{Point{2, Float32}}}}})(gl_attributes::Dict{Symbol, Any})
@ GLMakie ~/.julia/packages/GLMakie/N16Fq/src/drawing_primitives.jl:219
[7] (::GLMakie.var"#168#171"{GLMakie.var"#182#189"{GLMakie.Screen{GLFW.Window}, Scene, Scatter{Tuple{Vector{Point{2, Float32}}}}}, GLMakie.Screen{GLFW.Window}, Scene, Scatter{Tuple{Vector{Point{2, Float32}}}}})()
@ GLMakie ~/.julia/packages/GLMakie/N16Fq/src/drawing_primitives.jl:111
[8] get!(default::GLMakie.var"#168#171"{GLMakie.var"#182#189"{GLMakie.Screen{GLFW.Window}, Scene, Scatter{Tuple{Vector{Point{2, Float32}}}}}, GLMakie.Screen{GLFW.Window}, Scene, Scatter{Tuple{Vector{Point{2, Float32}}}}}, h::Dict{UInt64, GLMakie.GLAbstraction.RenderObject}, key::UInt64)
@ Base ./dict.jl:481
[9] cached_robj!(robj_func::GLMakie.var"#182#189"{GLMakie.Screen{GLFW.Window}, Scene, Scatter{Tuple{Vector{Point{2, Float32}}}}}, screen::GLMakie.Screen{GLFW.Window}, scene::Scene, x::Scatter{Tuple{Vector{Point{2, Float32}}}})
@ GLMakie ~/.julia/packages/GLMakie/N16Fq/src/drawing_primitives.jl:84
[10] draw_atomic
@ ~/.julia/packages/GLMakie/N16Fq/src/drawing_primitives.jl:198 [inlined]
[11] insert!(screen::GLMakie.Screen{GLFW.Window}, scene::Scene, x::Scatter{Tuple{Vector{Point{2, Float32}}}})
@ GLMakie ~/.julia/packages/GLMakie/N16Fq/src/drawing_primitives.jl:126
[12] push!(scene::Scene, plot::Scatter{Tuple{Vector{Point{2, Float32}}}})
@ Makie ~/.julia/packages/Makie/gAmAB/src/scenes.jl:413
[13] plot!(scene::Scene, P::Type{Scatter{Tuple{Vector{Point{2, Float32}}}}}, attributes::Attributes, input::Tuple{Observable{Vector{Point{2, Float32}}}}, args::Observable{Tuple{Vector{Point{2, Float32}}}})
@ Makie ~/.julia/packages/Makie/gAmAB/src/interfaces.jl:414
[14] plot!(scene::Scene, P::Type{Scatter}, attributes::Attributes, args::Observable{Vector{Point{2, Float32}}}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ Makie ~/.julia/packages/Makie/gAmAB/src/interfaces.jl:328
[15] plot!
@ ~/.julia/packages/Makie/gAmAB/src/interfaces.jl:295 [inlined]
[16] plot!(la::Axis, P::Type{Scatter}, attributes::Attributes, args::Observable{Vector{Point{2, Float32}}}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ Makie ~/.julia/packages/Makie/gAmAB/src/makielayout/blocks/axis.jl:778
[17] plot!
@ ~/.julia/packages/Makie/gAmAB/src/makielayout/blocks/axis.jl:765 [inlined]
[18] #plot!#1374
@ ~/.julia/packages/Makie/gAmAB/src/makielayout/blocks/axis.jl:795 [inlined]
[19] scatter!(::Axis, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Any, NTuple{4, Symbol}, NamedTuple{(:marker, :markersize, :color, :strokewidth), Tuple{Circle{Float32}, Pixel{Int64}, Observable{ColorTypes.RGBA{Float32}}, Float64}}})
@ MakieCore ~/.julia/packages/MakieCore/LOKNz/src/recipes.jl:38
[20] interactive_orbitdiagram(ds::DiscreteDynamicalSystem{false, SVector{2, Float64}, 2, typeof(DynamicalSystemsBase.Systems.hoop), Vector{Float64}, typeof(DynamicalSystemsBase.Systems.hoop_jac), SMatrix{2, 2, Float64, 4}, false}, p_index::Int64, p_min::Float64, p_max::Float64, i0::Int64; u0::SVector{2, Float64}, parname::String, title::String)
@ InteractiveDynamics ~/.julia/packages/InteractiveDynamics/x2wQQ/src/chaos/orbitdiagram.jl:81
[21] top-level scope
@ ~/Downloads/InteractiveDynamics.jl-main/examples/dynamicalsystems/orbitdiagram.jl:14
[22] include(fname::String)
@ Base.MainInclude ./client.jl:476
[23] top-level scope
@ REPL[1]:1
It seems to me that it comes from the definition const MARKER = Circle(Point2f(0, 0), Float32(1))
in colors.jl
but I am not yet familiar with the whole Julia / Makie to be 100% (I'm a Fortran person).
For info, I have installed everything in a dedicated env. Here are the only packages I have:
DynamicalSystems v.2.3.2
GLMakie v0.8.2
InteractiveDynamics v0.21.12
OrdinaryDiffEq v6.42.0
In the last version of the package, when trying to run the Lorenz example from documentation I get the error:
interactive_evolution(::DynamicalSystem, ::Any; transform, idxs, tsidxs, colors, tail, lims, Δt, plotkwargs, m, total_span, linekwargs, ps, pnames, add_controls, steps_per_update, figure, axis, fade) at C:\Users\halan.julia\packages\InteractiveDynamics\Q6bq5\src\chaos\trajanim.jl:108 got unsupported keyword argument "diffeq"
After removing the diffeq keyword I get another error:
interactive_evolution(::DynamicalSystem, ::Any; transform, idxs, tsidxs, colors, tail, lims, Δt, plotkwargs, m, total_span, linekwargs, ps, pnames, add_controls, steps_per_update, figure, axis, fade) at C:\Users\halan.julia\packages\InteractiveDynamics\Q6bq5\src\chaos\trajanim.jl:108 got unsupported keyword argument "diffeq"
Julia version : 1.8.5
OS version: Windows 11
When using interactive_evolution
(and possibly other function that support idxs
; I haven't tested them), the idxs
parameter doesn't seem to behave correctly. When using DynamicalSystem's double pendulum system (param order is [θ₁,ω₁,θ₂,ω₂]
) and attempting to graph both theta values, this is what I get:
julia> using GLMakie, DynamicalSystems, InteractiveDynamics
julia> ds = Systems.double_pendulum()
4-dimensional continuous dynamical system
state: [1.5708, 0.0, 0.0, 0.5]
rule f: doublependulum_rule
in-place? false
jacobian: ForwardDiff
parameters: [10.0, 1.0, 1.0, 1.0, 1.0]
julia> interactive_evolution(ds; idxs = [1, 3]);
juila> # Click "Step" ("run" does nothing):
Error in callback:
BoundsError: attempt to access Tuple{Float64, Float64} at index [3]
Stacktrace:
[1] getindex
@ ./tuple.jl:29 [inlined]
[2] getindex
@ ~/.julia/packages/StaticArrays/6D1fn/src/SArray.jl:94 [inlined]
[3] (::InteractiveDynamics.var"#69#77"{typeof(identity), SVector{2, Int64}, Vector{Int64}, Int64, Observable{Vector{Point{2, Float32}}}, Vector{Observable}, SimpleDiffEq.SimpleATsit5Integrator{true, Vector{SVector{4, Float64}}, Float64, Vector{Float64}, SciMLBase.ODEFunction{true, DynamicalSystemsBase.var"#30#32"{ContinuousDynamicalSystem{false, SVector{4, Float64}, 4, typeof(DynamicalSystemsBase.Systems.doublependulum_rule), Vector{Float64}, DynamicalSystemsBase.var"#9#15"{typeof(DynamicalSystemsBase.Systems.doublependulum_rule)}, SMatrix{4, 4, Float64, 16}, true}, Int64}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, typeof(DynamicalSystemsBase._parallelnorm)}, Int64})(clicks::Int64)
@ InteractiveDynamics ~/.julia/packages/InteractiveDynamics/NHT8Y/src/chaos/trajanim.jl:175
[4] #invokelatest#2
@ ./essentials.jl:716 [inlined]
[5] invokelatest
@ ./essentials.jl:714 [inlined]
[6] notify
@ ~/.julia/packages/Observables/OFj0u/src/Observables.jl:88 [inlined]
[7] setindex!(observable::Observable{Any}, val::Int64)
@ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:248
[8] (::Makie.MakieLayout.var"#615#625"{Observable{Symbol}, Observable{Any}})(#unused#::MouseEvent)
@ Makie.MakieLayout ~/.julia/packages/Makie/lgPZh/src/makielayout/layoutables/button.jl:87
[9] (::Makie.MakieLayout.var"#30#31"{Makie.MakieLayout.var"#615#625"{Observable{Symbol}, Observable{Any}}})(event::MouseEvent)
@ Makie.MakieLayout ~/.julia/packages/Makie/lgPZh/src/makielayout/mousestatemachine.jl:86
[10] #invokelatest#2
@ ./essentials.jl:716 [inlined]
[11] invokelatest
@ ./essentials.jl:714 [inlined]
[12] (::Makie.PrioCallback)(val::MouseEvent)
@ Makie ~/.julia/packages/Makie/lgPZh/src/interaction/PriorityObservable.jl:16
[13] #invokelatest#2
@ ./essentials.jl:716 [inlined]
[14] invokelatest
@ ./essentials.jl:714 [inlined]
[15] notify(observable::Makie.PriorityObservable{MouseEvent})
@ Makie ~/.julia/packages/Makie/lgPZh/src/interaction/PriorityObservable.jl:84
[16] setindex!
@ ~/.julia/packages/Makie/lgPZh/src/interaction/PriorityObservable.jl:78 [inlined]
[17] (::Makie.MakieLayout.var"#100#102"{Scene, Base.RefValue{Bool}, Base.RefValue{Union{Nothing, Makie.Mouse.Button}}, Base.RefValue{Float64}, Base.RefValue{Float64}, Base.RefValue{Bool}, Base.RefValue{Bool}, Base.RefValue{Union{Nothing, Makie.Mouse.Button}}, Base.RefValue{Bool}, Base.RefValue{Point{2, Float32}}, Base.RefValue{Point{2, Float32}}, Base.RefValue{Makie.Mouse.Action}, Makie.PriorityObservable{MouseEvent}, Float64, Module})(event::Makie.MouseButtonEvent)
@ Makie.MakieLayout ~/.julia/packages/Makie/lgPZh/src/makielayout/mousestatemachine.jl:259
[18] #invokelatest#2
@ ./essentials.jl:716 [inlined]
[19] invokelatest
@ ./essentials.jl:714 [inlined]
[20] (::Makie.PrioCallback)(val::Makie.MouseButtonEvent)
@ Makie ~/.julia/packages/Makie/lgPZh/src/interaction/PriorityObservable.jl:16
[21] #invokelatest#2
@ ./essentials.jl:716 [inlined]
[22] invokelatest
@ ./essentials.jl:714 [inlined]
[23] notify(observable::Makie.PriorityObservable{Makie.MouseButtonEvent})
@ Makie ~/.julia/packages/Makie/lgPZh/src/interaction/PriorityObservable.jl:84
[24] setindex!
@ ~/.julia/packages/Makie/lgPZh/src/interaction/PriorityObservable.jl:78 [inlined]
[25] (::GLMakie.var"#mousebuttons#78"{Makie.PriorityObservable{Makie.MouseButtonEvent}})(window::GLFW.Window, button::GLFW.MouseButton, action::GLFW.Action, mods::Int32)
@ GLMakie ~/.julia/packages/GLMakie/TfSB1/src/events.jl:89
[26] _MouseButtonCallbackWrapper(window::GLFW.Window, button::GLFW.MouseButton, action::GLFW.Action, mods::Int32)
@ GLFW ~/.julia/packages/GLFW/BWxfF/src/callback.jl:43
[27] PollEvents
@ ~/.julia/packages/GLFW/BWxfF/src/glfw3.jl:620 [inlined]
[28] pollevents
@ ~/.julia/packages/GLMakie/TfSB1/src/screen.jl:545 [inlined]
[29] fps_renderloop(screen::GLMakie.Screen, framerate::Float64)
@ GLMakie ~/.julia/packages/GLMakie/TfSB1/src/rendering.jl:21
[30] renderloop(screen::GLMakie.Screen; framerate::Float64)
@ GLMakie ~/.julia/packages/GLMakie/TfSB1/src/rendering.jl:48
[31] renderloop(screen::GLMakie.Screen)
@ GLMakie ~/.julia/packages/GLMakie/TfSB1/src/rendering.jl:41
[32] (::GLMakie.var"#56#58"{GLMakie.Screen})()
@ GLMakie ./task.jl:429
If I attempt to use a tuple for idxs instead, as sometimes suggested by the documentation (I assume either an Array or a Tuple is supposed to be fine), I get this type error:
julia> interactive_evolution(ds; idxs = (1, 3))
ERROR: ArgumentError: invalid index: (1, 3) of type Tuple{Int64, Int64}
Stacktrace:
[1] to_index(i::Tuple{Int64, Int64})
@ Base ./indices.jl:300
[2] to_index(A::SVector{4, Float64}, i::Tuple{Int64, Int64})
@ Base ./indices.jl:277
[3] to_indices
@ ./indices.jl:333 [inlined]
[4] to_indices
@ ./indices.jl:325 [inlined]
[5] getindex
@ ./abstractarray.jl:1218 [inlined]
[6] _init_timeseries_plots!(layout::GridLayout, pinteg::SimpleDiffEq.SimpleATsit5Integrator{true, Vector{SVector{4, Float64}}, Float64, Vector{Float64}, SciMLBase.ODEFunction{true, DynamicalSystemsBase.var"#30#32"{ContinuousDynamicalSystem{false, SVector{4, Float64}, 4, typeof(DynamicalSystemsBase.Systems.doublependulum_rule), Vector{Float64}, DynamicalSystemsBase.var"#9#15"{typeof(DynamicalSystemsBase.Systems.doublependulum_rule)}, SMatrix{4, 4, Float64, 16}, true}, Int64}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, typeof(DynamicalSystemsBase._parallelnorm)}, idxs::Tuple{Int64, Int64}, colors::Vector{ColorTypes.RGBA{Float32}}, linekwargs::NamedTuple{(:linewidth,), Tuple{Int64}}, transform::typeof(identity), tail::Int64, lims::Tuple{Tuple{Float64, Float64}, Tuple{Float64, Float64}})
@ InteractiveDynamics ~/.julia/packages/InteractiveDynamics/NHT8Y/src/chaos/trajanim.jl:283
[7] interactive_evolution(ds::ContinuousDynamicalSystem{false, SVector{4, Float64}, 4, typeof(DynamicalSystemsBase.Systems.doublependulum_rule), Vector{Float64}, DynamicalSystemsBase.var"#9#15"{typeof(DynamicalSystemsBase.Systems.doublependulum_rule)}, SMatrix{4, 4, Float64, 16}, true}, u0s::Vector{SVector{4, Float64}}; transform::typeof(identity), idxs::Tuple{Int64, Int64}, tsidxs::Tuple{Int64, Int64}, colors::Vector{ColorTypes.RGBA{Float32}}, tail::Int64, lims::Nothing, diffeq::NamedTuple{(), Tuple{}}, plotkwargs::NamedTuple{(), Tuple{}}, m::Float64, total_span::Int64, linekwargs::NamedTuple{(:linewidth,), Tuple{Int64}}, ps::Nothing, pnames::Nothing, add_controls::Bool, steps_per_update::Int64, figure::NamedTuple{(:resolution,), Tuple{Tuple{Int64, Int64}}}, axis::NamedTuple{(), Tuple{}}, fade::Bool)
@ InteractiveDynamics ~/.julia/packages/InteractiveDynamics/NHT8Y/src/chaos/trajanim.jl:134
[8] top-level scope
@ REPL[9]:1
Versions:
[61744808] DynamicalSystems v2.3.0
[e9467ef8] GLMakie v0.5.5
[ec714cd0] InteractiveDynamics v0.21.3
This issue is used to trigger TagBot; feel free to unsubscribe.
If you haven't already, you should update your TagBot.yml
to include issue comment triggers.
Please see this post on Discourse for instructions and more details.
It would be nice to be able to send at least a few kwargs to the main axis in abm_plot
and abm_video
(at least).
Similar to scatterkwargs, can we supply an axiskwargs tuple in the future?
For example, if I don't want to have xticks visible, or I want to change their value in some way, at present the only way to do this is a completely custom plot.
Hi, I encountered a MethodError, when using Rodas5 to compute the timeseries of a 3D dynamical system. It works fine with other solvers such as Vern9.
The example code reads
using GLMakie
using OrdinaryDiffEq
using DynamicalSystems
using InteractiveDynamics
function my_system(x, p, t)
@unpack a, b, c = p
dx = exp(x[2] - 0.5) * (1.0 - x[1]) - a * tanh(10.0 * (x[1] - 0.5)) - a
dy = a * tanh(10.0 * (x[1] - 0.5)) + a - exp(x[2] - 0.5) + (x[3] - x[2]) * 2.0
dz = 3.0 - exp(x[3] - 0.5) - (x[3] - x[2]) * 0.5
return SVector(dx, dy, dz)
end
p = Dict(
:a => 2.0,
:b => 70.0,
:c => 4.0e8,
)
ps = Dict(
:a => 1.9:0.01:2.1
)
x0 = [0.3, 0.5, 0.4]
ds = ContinuousDynamicalSystem(my_system, x0, p)
diffeq = (alg = Rodas5(), adaptive = false, dt = 0.001, reltol = 1e-8, abstol = 1e-8)
tr = trajectory(ds, 100; diffeq...)
u0s = [ds.u0]
fig, obs = interactive_evolution_timeseries(
ds, u0s, ps; tail = 10000, diffeq, idxs = (1, 2, 3),
lims =((0.0,1.0), (0.0, 2.0), (0.0, 2.0))
)
The error message reads:
ERROR: MethodError: Cannot `convert` an object of type Bool to an object of type SVector{3, Float64}
Closest candidates are:
convert(::Type{T}, ::Intervals.AnchoredInterval{P, T, L, R} where {L<:Intervals.Bounded, R<:Intervals.Bounded}) where {P, T} at /Users/luca/.julia/packages/Intervals/ua9cq/src/anchoredinterval.jl:181
convert(::Type{T}, ::Intervals.Interval{T, L, R} where {L<:Intervals.Bound, R<:Intervals.Bound}) where T at /Users/luca/.julia/packages/Intervals/ua9cq/src/interval.jl:253
convert(::Type{SVector{N, T}}, ::CartesianIndex{N}) where {N, T} at /Users/luca/.julia/packages/StaticArrays/OWJK7/src/SVector.jl:46
I don't think, DynamicalSystems.jl is the problem because the trajectory (tr) is computed correctly. The programme only fails when interactive_evolution_timeseries()
is used.
I can provide the stacktrace on request.
I am trying to do plots and videos of an agents.jl simulation that show the underlying geometry (a square lattice). For this I'm trying to plot the minorgrid, and looking at the documentation it seems as if I should be using scatterkwargs. However, when I try the following there is no change (I only see the major grid):
abm_video(
"test.mp4", model, agent_step!, model_step!;
framerate = 20, frames = 100,
scatterkwargs = (minorgrid = true, ),
title = ("Test")
)
What am I doing wrong? Thanks a lot!
Hello,
I'm exploring the plotting in ABMs described here: https://juliadynamics.github.io/Agents.jl/stable/agents_visualizations/
and the following code (right at the beginning) doesn't work.
using InteractiveDynamics, Agents
using CairoMakie
daisypath = joinpath(dirname(pathof(InteractiveDynamics)), "agents", "daisyworld_def.jl")
include(daisypath)
model, daisy_step!, daisyworld_step! = daisyworld(;
solar_luminosity = 1.0, solar_change = 0.0, scenario = :change
)
My dependencies:
Julia 1.7.2
Agents v5.4.0
CairoMakie v0.8.8
The error is:
MethodError: no method matching ids_in_position(::Tuple{Int64, Int64}, ::AgentBasedModel{GridSpaceSingle{2, true}, Daisy, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, MersenneTwister})
Closest candidates are:
ids_in_position(::Union{Int64, Tuple{Int64, Int64, Float64}, Tuple{Vararg{Int64, N}}, Tuple{Vararg{var"#s3", M}} where var"#s3"<:AbstractFloat} where {N, M}, ::AgentBasedModel{<:GridSpace}) at ~/Agents.jl/src/spaces/grid_multi.jl:243
ids_in_position(::Union{Int64, Tuple{Int64, Int64, Float64}, Tuple{Vararg{Int64, N}}, Tuple{Vararg{var"#s3", M}} where var"#s3"<:AbstractFloat} where {N, M}, ::GridSpace) at ~/Agents.jl/src/spaces/grid_multi.jl:244
ids_in_position(::A, ::Any) where A<:AbstractAgent at ~/Agents.jl/src/spaces/discrete.jl:49
Stacktrace:
[1] update_surface_temperature!(pos::Tuple{Int64, Int64}, model::AgentBasedModel{GridSpaceSingle{2, true}, Daisy, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, MersenneTwister})
@ Main ~/.julia/packages/InteractiveDynamics/NBLxn/src/agents/daisyworld_def.jl:16
[2] daisyworld(; griddims::Tuple{Int64, Int64}, max_age::Int64, init_white::Float64, init_black::Float64, albedo_white::Float64, albedo_black::Float64, surface_albedo::Float64, solar_change::Float64, solar_luminosity::Float64, scenario::Symbol, seed::Int64)
@ Main ~/.julia/packages/InteractiveDynamics/NBLxn/src/agents/daisyworld_def.jl:136
[3] top-level scope
@ ~/Agents.jl/examples/interactivity-test.jl:27
Thanks!
I've noticed now that I want to do some advanced usage of interactive_evolution_timeseries
. I want to plot additional elements into the plot(s), whose location and/or color depend on the values of the sliders.
I think it is easy to resolve this. We return an observable that contains a dictionary that maps slider names to current values. Whenever we hit the update button, this observable is updated. The user can use this observable and lift
it to create their own auto-updatable plots.
Now that Makie.jl has support for text input boxes,
we should use those to replace the current boxes that just state the
values of the limits (so that users can choose exact limits)
https://makie.juliaplots.org/stable/examples/layoutables/textbox/
... but it looks like that method has been removed recently.
This is the error that I keep getting while trying to run the example in interactive trajectory evolution.
julia> include("lorenz.jl")
ERROR: LoadError: MethodError: no method matching interactive_evolution(::ContinuousDynamicalSystem{false, SVector{3, Float64}, 3, typeof(DynamicalSystemsBase.Systems.loop), Vector{Float64}, typeof(DynamicalSystemsBase.Systems.loop_jac), SMatrix{3, 3, Float64, 9}, false}, ::Vector{Vector{Float64}}; ps=Dict{Int64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}(2 => 10.0:0.1:50.0, 3 => 1.0:0.01:10.0, 1 => 1.0:0.1:30.0), idxs=(1, 2, 3), tail=1000, diffeq=(alg = Tsit5(stage_limiter! = trivial_limiter!, step_limiter! = trivial_limiter!, thread = static(false)), dt = 0.01, adaptive = false), pnames=Dict(2 => "ρ", 3 => "β", 1 => "σ"), lims=((-30, 30), (-30, 30), (0, 100)))
Closest candidates are:
interactive_evolution(::DynamicalSystem{IIP}, ::Any; transform, idxs, colors, tail, diffeq, plotkwargs, m, lims) where IIP at C:\Users\subha\.julia\packages\InteractiveDynamics\Xw3Ei\src\chaos\trajanim.jl:42 got unsupported keyword arguments "ps", "pnames"
Stacktrace:
[1] kwerr(::NamedTuple{(:ps, :idxs, :tail, :diffeq, :pnames, :lims), Tuple{Dict{Int64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}, Tuple{Int64, Int64, Int64}, Int64, NamedTuple{(:alg, :dt, :adaptive), Tuple{Tsit5{typeof(OrdinaryDiffEq.trivial_limiter!), typeof(OrdinaryDiffEq.trivial_limiter!), Static.False}, Float64, Bool}}, Dict{Int64, String}, Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}, Tuple{Int64, Int64}}}}, ::Function, ::ContinuousDynamicalSystem{false, SVector{3, Float64}, 3, typeof(DynamicalSystemsBase.Systems.loop), Vector{Float64}, typeof(DynamicalSystemsBase.Systems.loop_jac), SMatrix{3, 3, Float64, 9}, false}, ::Vector{Vector{Float64}})
@ Base .\error.jl:165
[2] top-level scope
@ C:\Users\subha\OneDrive\Desktop\Code\julia\Lorenz\lorenz.jl:28
[3] include(fname::String)
@ Base.MainInclude .\client.jl:476
[4] top-level scope
@ REPL[7]:1
in expression starting at C:\Users\subha\OneDrive\Desktop\Code\julia\Lorenz\lorenz.jl:28
I can't quite figure out whether there is something that I'm doing wrong. Any help is much appreciated.
I've just posted on discourse about getting GLMakie v0.4 and InteractiveDynamics v0.15 to play nice together. Perhaps you know what's happening here already though @Datseris?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.