juliageometry / contour.jl Goto Github PK
View Code? Open in Web Editor NEWCalculating contour curves for 2D scalar fields in Julia
License: Other
Calculating contour curves for 2D scalar fields in Julia
License: Other
The URL of this package does not match that stored in METADATA.jl.
cc: @KristofferC
I ran Pkg.update()
, and this is what I got.
julia> Pkg.update()
INFO: Updating METADATA...
INFO: Computing changes...
INFO: Upgrading ArrayViews: v0.4.6 => v0.4.8
INFO: Installing Calculus v0.1.5
INFO: Upgrading Codecs: v0.1.2 => v0.1.3
INFO: Upgrading Color: v0.3.8 => v0.3.15
INFO: Installing Compat v0.2.10
INFO: Upgrading Compose: v0.3.9 => v0.3.10
INFO: Upgrading Contour: v0.0.4 => v0.0.6
INFO: Rolling back Compose from v0.3.10 to v0.3.9
INFO: Rolling back install of Compat
INFO: Rolling back Color from v0.3.15 to v0.3.8
INFO: Rolling back Codecs from v0.1.3 to v0.1.2
INFO: Rolling back install of Calculus
INFO: Rolling back ArrayViews from v0.4.8 to v0.4.6
ERROR: Contour: fetch failed to get commit 7bded64ef5, please file an issue at https://github.com/tlycken/Contour.jl/issues
in error at error.jl:21
in fetch at pkg/write.jl:19
in update at pkg/write.jl:41
in resolve at /opt/homebrew-cask/Caskroom/julia/0.3.5/Julia-0.3.5.app/Contents/Resources/julia/lib/julia/sys.dylib
in update at /opt/homebrew-cask/Caskroom/julia/0.3.5/Julia-0.3.5.app/Contents/Resources/julia/lib/julia/sys.dylib
in anonymous at pkg/dir.jl:28
in cd at /opt/homebrew-cask/Caskroom/julia/0.3.5/Julia-0.3.5.app/Contents/Resources/julia/lib/julia/sys.dylib
in __cd#227__ at /opt/homebrew-cask/Caskroom/julia/0.3.5/Julia-0.3.5.app/Contents/Resources/julia/lib/julia/sys.dylib
in update at /opt/homebrew-cask/Caskroom/julia/0.3.5/Julia-0.3.5.app/Contents/Resources/julia/lib/julia/sys.dylib
I've noticed that the CI builds take quite a long time to finish, although the test suite is pretty quick, due to long queue times before the OSX builds even start. Here are a couple of recent examples:
The total build time was 12 minutes, even though the longest build actually only ran for 4.5 minutes, and the Ubuntu builds finished in under 3.
This build has been queued for 10 minutes without even starting.
Since we're not doing any C interop, no file system operations and nothing else that should possibly be platform dependent (unless there's a bug in Julia itself), is it really worth the extra turnback-time to test on multiple OS'es? What do we gain from building on OSX too?
CC: @SimonDanisch, who activated it :)
This is from: GiovineItalia/Gadfly.jl#420. In this example, contours(x, y, z, n)
will give a “key not found” error if n >= 7
. Maybe an error is appropriate, I'm not sure, but a descriptive error would be good.
Gist to reproduce this: https://gist.github.com/dcjones/c56d09f7934202bca54e
While working on #51 I realized that there is quite a bit of memory/performance tradeoff, similar to what happens in Meshing.jl. In Meshing.jl we have three algorithms with different performance and output characteristics to give the user some control based on requirements. I realize in Contour there is a similar balance, but no analogous control.
In Meshing.jl we have MarchingCubes which traverses the array and gives triangles without connectivity. There is also MarchingTetrahedra which gives connectivity but is ~4x slower.
My proposal is to implement a similar system for specifying an algorithm and output to contour.
BigMemoryConnected
(name TBD) algorithm like #51EdgeSoupUnconnected
(name TBD) algorithm which just generated edge pairs, without polygon loopsThe benefit of BigMemoryConnected
is that it is faster than the default and will still give the same output to the algorithm in place now. Downsides are that the memory requirement is large ~1/8 the z
grid size.
EdgeSoupUnconnected
should have almost not allocations outside the allocation of the output, and will be the fastest. However it will not generate polygons/polylines, but rather edge pairs. This means the output size will be larger, but the actual processing done in Contour should be orders of magnitude faster, and overall memory should be much smaller.
Bonus round
Direct function sampling. In this case, contours can be generated without allocating a z-grid. For simple analytic functions, this can yield overall good performance improvements.
When a contour consist of several disconnected branches, only one branch is found.
The following example illustrates the problem:
using PyPlot, Contour
x = -3:0.01:3
y = -3:0.01:3
z = [Float64((xi^2 - yi^2)) for xi in x, yi in y];
h = 2
c = Contour.contour(x, y, z, h); # both Contour and PyPlot have contour()
xs, ys = coordinates(c.lines[1]);
plot(xs, ys)
The result is one branch, whereas there must be two disconnected ones
The version of Contour from github was used on Julia 0.4.3
versioninfo()
Julia Version 0.4.3
Commit a2f713d* (2016-01-12 21:37 UTC)
Platform Info:
System: Linux (x86_64-redhat-linux)
CPU: Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
WORD_SIZE: 64
BLAS: libopenblas (DYNAMIC_ARCH NO_AFFINITY Sandybridge)
LAPACK: libopenblasp.so.0
LIBM: libopenlibm
LLVM: libLLVM-3.3
The tests for this package fails on Julia nightly and after some poking around I believe that the tests here
Contour.jl/test/verify_vertices.jl
Lines 235 to 248 in 7e1d4ea
are sensitive to the exact order the entries in the Dict
that is returned from get_level_cells
. The hashing has changed on Julia nightly so the tests now fail.
contours
does not accept a z
of Int
s. A use case is count data:
using Contour
using StatsBase
N = 10000
x = randn(N)
y = randn(N)
H = fit(Histogram, (x, y), closed = :left)
contours(midpoints.(H.edges)..., H.weights) # fails
contours(midpoints.(H.edges)..., Float64.(H.weights)) # works
The error message for the failing one is
julia> contours(midpoints.(H.edges)..., H.weights)
ERROR: MethodError: no method matching interpolate(::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Array{Int64,2}, ::Float64, ::Int64, ::Int64, ::UInt8)
Closest candidates are:
interpolate(::Any, ::Any, ::Array{T<:AbstractFloat,2}, ::Number, ::Int64, ::Int64, ::UInt8) where T<:AbstractFloat at /home/tamas/.julia/v0.6/Contour/src/Contour.jl:232
Stacktrace:
[1] trace_contour(::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Array{Int64,2}, ::Float64, ::Dict{Tuple{Int64,Int64},Contour.Cell}) at /home/tamas/.julia/v0.6/Contour/src/Contour.jl:328
[2] collect(::Base.Generator{StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Contour.##1#2{StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Array{Int64,2}}}) at ./array.jl:475
[3] contours at /home/tamas/.julia/v0.6/Contour/src/Contour.jl:81 [inlined]
[4] contours at /home/tamas/.julia/v0.6/Contour/src/Contour.jl:88 [inlined]
[5] contours(::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Array{Int64,2}) at /home/tamas/.julia/v0.6/Contour/src/Contour.jl:94
Current master drops load times substantially, but needs some doc updates before a release. Ideally instructions for down streams for updating in case they depend on StaticArrays.
There's a bunch of ambiguity warnings on 0.4 that's kind of annoying and should be easy to fix.
s/uint8\((\d)\)/$1 % UInt8/
[...]
. The ambiguity warnings suggest using [...;]
, but I think we could get away with using tuples instead, i.e. (...)
, and save some memory in the process.I'll submit a PR when I get to it, but I figured I'd put this up here to remind myself (and to avoid others bumping into them thinking I haven't noticed).
I got thinking about this when the lack of documentation was pointed out in #28. Currently, I think the way to e.g. plot all contour lines for a given surface xs,ys,zs
is to do the following:
levels = contour(xs, ys, zs)
for level in levels
for line in level.lines
x,y = coordinates(line)
# do something with the lists x and y, e.g. plot(x,y)
end
end
I'd like this to become a little less dependent on the types we return; it would make the API a little more coherent, and it would make it easier to switch those types for something else, if we e.g. want to support higher dimensions. A suggestion for an API would be
c = contour(xs, ys, zs) # returns an object, not a list. Not necessary, but nice, IMO
for lvl in levels(c)
for line in lines(lvl)
x,y = coordinates(line)
# plot(x,y) or whatever
end
end
There are two changes here:
lines
which is basically lines(lvl) = lvl.lines
. This should be uncontroversial.contour
to some type on which you can call levels
and get todays result of contour
. The natural name for such a type would be Contour
, but that would require a rename (i.e. deprecation-and-replace) of this package. Although I think such a rename would be a good idea in the long run anyway, to adhere to Julia's package naming guidelines (see especially point 3.), it's no doubt a pretty disruptive change.Thoughts?
cc: @darwindarak
before:
julia> collect(())
0-element Array{Union{},1}
after using Contour:
julia> using Contour
julia> collect(())
Error showing value of type Array{Union{},1}:
ERROR: MethodError: no method matching display(::Array{Union{},1})
Closest candidates are:
display(::Any) at multimedia.jl:320
display(::AbstractDisplay, ::AbstractString, ::Any) at multimedia.jl:214
display(::AbstractString, ::Any) at multimedia.jl:215
...
Stacktrace:
[1] display(::Any) at ./multimedia.jl:330
[2] #invokelatest#1 at ./essentials.jl:712 [inlined]
[3] invokelatest at ./essentials.jl:711 [inlined]
[4] print_response(::IO, ::Any, ::Bool, ::Bool, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:161
[5] print_response(::REPL.AbstractREPL, ::Any, ::Bool, ::Bool) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:146
[6] (::REPL.var"#do_respond#38"{Bool,REPL.var"#48#57"{REPL.LineEditREPL,REPL.REPLHistoryProvider},REPL.LineEditREPL,REPL.LineEdit.Prompt})(::Any, ::Any, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:729
[7] #invokelatest#1 at ./essentials.jl:712 [inlined]
[8] invokelatest at ./essentials.jl:711 [inlined]
[9] run_interface(::REPL.Terminals.TextTerminal, ::REPL.LineEdit.ModalInterface, ::REPL.LineEdit.MIState) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/LineEdit.jl:2354
[10] run_frontend(::REPL.LineEditREPL, ::REPL.REPLBackendRef) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:1055
[11] run_repl(::REPL.AbstractREPL, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:206
[12] (::Base.var"#764#766"{Bool,Bool,Bool,Bool})(::Module) at ./client.jl:383
[13] #invokelatest#1 at ./essentials.jl:712 [inlined]
[14] invokelatest at ./essentials.jl:711 [inlined]
[15] run_main_repl(::Bool, ::Bool, ::Bool, ::Bool, ::Bool) at ./client.jl:367
[16] exec_options(::Base.JLOptions) at ./client.jl:305
[17] _start() at ./client.jl:484
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.
julia> begin
Σy = 1.1
Σx = 0.7
X0 = 2
Y0 = 3
z(x,y) = exp(-(x-X0)^2/2Σx^2 - (y-Y0)^2/2Σy^2)
end
julia> using Contour
julia> contours(Float64[1:5], Float64[1:5], Float64[z(x,y) for x in 1:5, y in 1:5])
ERROR: MethodError: `convert` has no method matching convert(::Type{ImmutableArrays.Vector2{Float64}})
This may have arisen from a call to the constructor ImmutableArrays.Vector2{Float64}(...),
since type constructors fall back to convert methods.
Closest candidates are:
convert{T}(::Type{ImmutableArrays.Vector2{T}}, ::ImmutableArrays.Vector2{T})
convert{T}(::Type{ImmutableArrays.Vector2{T}}, ::AbstractArray{T,1})
convert{T}(::Type{T}, ::T)
...
in push! at array.jl:533
in add_vertex! at C:\Users\Tomas Lycken\.julia\v0.4\Contour\src\Contour.jl:147
in trace_contour at C:\Users\Tomas Lycken\.julia\v0.4\Contour\src\Contour.jl:253
in contours at C:\Users\Tomas Lycken\.julia\v0.4\Contour\src\Contour.jl:23
in anonymous at no file
I've tried to take a look at this, but I can't figure out why the conversion doesn't work. The stack trace seems accurate enough, though, so it should be a good starting point, but from what I can tell with println
debugging, there is never a call to convert
, or to a constructor of Vector2{Float64}
, with no other arguments.
Consider the following map with discontinuities on the y-axis. The black lines are the contours with value 0. They clearly are wrong at the discontinuity on the y-axis. Expected would be a horizontal line at y=0. Is this a general drawback of the algorithm are is this an edge case, which is not dealt with yet?
xs = range(-6, 6, length=200)
ys = range(-6, 6, length=200)
zs = [angle((x+im*y)^2) for x in xs, y in ys]
heatmap(xs, ys, zs'; cmap=:autumn1)
cl = Contour.contour(xs,ys,zs, 0.)
xs, ys = coordinates(lines(cl)[1])
plot!(xs, ys; color=:black,lw=5)
Hi!
Is it possible to access the contour line from (for?!) a specific point?
I mean, one could calculate the level of that point and then obtain the contour lines for that level. However, then one may get multiple lines (with the same level) and still needs to sort out which line actually intersects with the initially given point (and that might fail due to numerical inaccuracies...).
Thanks in advance!
I'm starting to look at incorporating generalized contours into my package Plots.jl, but I'm a little unsure if I can do what I want:
Lets suppose I have 3 vectors:
x = rand(n)
y = rand(n)
z = x .* y
Is is possible (with Contour.jl) to extract contour coordinates for the contour lines directly from these vectors? Or do I need to preprocess the data onto some regular grid and pass a dense matrix with the heights?
I spent just a couple minutes googling, and it seems reasonable to implement something like distance-weighted least squares to preprocess the data into a mesh. If this doesn't exist, and I implement it, would you like me to submit a PR?
When I started this project, in close collaboration with @darwindarak, I had the opportunity to spend a lot of my coding time with Julia, as I was actively using it myself. For quite some time now, this is no longer the case, and Julia programming has been pushed back on my priority list to the place of "hobbies I can't quite find the time for".
This was fine as long as the packages I maintained were relatively stable, with little activity in issues and pull requests, but lately I've felt that there is more and more going on that I'm unable to keep up with. Thus, I feel I'm no longer doing as well as I'd like as a maintainer, and I think it's time to pass the baton to someone else.
I'm opening this issue as a call for a discussion on where this package should live. Would you like to assume ownership? Do you know of an organization that would?
I've hooked this repo up to Travis CI and Coveralls.io now, so everything is formally in place to release this to METADATA and announce it on the users list.
However, I think there are a couple of things we should do before we release it:
Regarding the last point: What is a good way to test the functionality here? Should we just give the routine a well-known test function (or a few different ones) and make sure all the vertices are in the correct places, or is there something more trivial we can do?
I'm trying to compute multiple contour levels for the same dataset.
Some levels work just fine but others give me the following error:
ERROR: key not found: (313,58)
in chase at ~/.julia/v0.3/Contour/src/Contour.jl:150
in trace_contour at ~/.julia/v0.3/Contour/src/Contour.jl:218
in contours at ~/.julia/v0.3/Contour/src/Contour.jl:23
in include at ./boot.jl:245
in include_from_node1 at ./loading.jl:128
while loading .../foo.jl, in expression starting on line 32
The error can be reproduced with the dataset (x,y,z) that I've uploaded to http://dev.exherbo.org/~pipping/broken/ and the following script:
using Contour
z = readdlm("broken/z")
y = readdlm("broken/x")
x = readdlm("broken/y")
hs = [-20e-6, -10e-6, 0]
println(size(z))
println(size(x))
println(size(y))
println("Me: Dear data set, tell me a bit about yourself")
for h in hs
c = contour(x, y, z, h);
println("Dataset: <<= Here's my level $h. =>>")
clines = c.lines
for (i,cline) in enumerate(clines)
xs, ys = coordinates(cline);
println("Dataset: Here's my line #$i")
println("Dataset: my min/max x values are: $(minimum(xs)), $(maximum(xs))")
println("Dataset: my min/max y values are: $(minimum(ys)), $(maximum(ys))")
println("Dataset: I contain $(length(xs)) points.")
end
end
The error occurs for the zero-level.
System info: julia version 0.3.1-pre+50,
When supplying the data to the contouring functions, there are two possible conventions, both of which are already in use in different places. When calling contours(x,y,z,levels)
one could mean either one of these two:
z
represent the values for a constant x
-value, i.e. the orientation of the matrix is the same as the physical one. This means one has to access the matrix as z[yi,xi]
where xi
and yi
are indices to the corresponding x
and y
values. This is the convention currently used by e.g. contour
in MATLAB and Python's matplotlib.z
represent the values for a constant y
value, i.e. the orientation of the matrix is such that you can index it z[xi,yi]
. This also means that moving along the first coordinate direction x
traverses the matrix in the most cache-friendly way, since Julia is column major. This is the convention used in e.g. Grid.jl.Not choosing the first convention might be confusing at first to users coming from MATLAB or Python (or other systems that use the same convention - for example, I don't know what R does). Despite this, I prefer the second - and parts of MATLAB agrees with me, since e.g. imagesc
does follow the second... My main argument is that it is much more natural to index a matrix as z[x,y]
, especially when we have other, matrix-like objects (e.g. grid interpolants) which are indexed that way. And in MATLAB I usually have to transpose my matrices to get the contour plots to look the way I want anyway - we could avoid that mistake.
Whichever convention we choose to go with, we should make sure that the contouring algorithm traverses the matrix in a cache-friendly order.
Let's take the sample code from the documentation
for cl in levels(contours(x,y,z))
lvl = level(cl) # the z-value of this contour level
for line in lines(cl)
xs, ys = coordinates(line) # coordinates of this line segment
end
end
I need the indices of xs
and ys
in x
and y
, i.e.in a simple world this would be:
ix = indexin(xs, x)
iy = indexin(ys, y)
this_contour = z[ix, iy]
However, xs
and ys
do not belong exactly to x
and y
, and I can't figure out how to extract the indices. The reason I need to do this is that I have an auxiliary array w
that has the same shape as z
, and I would like to extract the part corresponding to the contours.
Is there some way to do this? Does contour.jl return the indices somehow?
Hello, and thanks for the great package!
I noticed that currently contour
fails if provided an array of integers. For example:
using Contour
contours(1:10,1:10, rand(1:10, 10, 10))
Gives
ERROR: InexactError: Int64(2.409090909090909)
Stacktrace:
[1] Int64
@ .\float.jl:788 [inlined]
[2] convert
@ .\number.jl:7 [inlined]
[3] macro expansion
@ C:\Users\William\.julia\packages\StaticArrays\0T5rI\src\util.jl:17 [inlined]
[4] convert_ntuple
@ C:\Users\William\.julia\packages\StaticArrays\0T5rI\src\util.jl:13 [inlined]
[5] SArray
@ C:\Users\William\.julia\packages\StaticArrays\0T5rI\src\SArray.jl:28 [inlined]
[6] StaticArray
@ C:\Users\William\.julia\packages\StaticArrays\0T5rI\src\convert.jl:152 [inlined]
[7] interpolate(x::UnitRange{Int64}, y::UnitRange{Int64}, z::Matrix{Int64}, h::Float64, ind::Tuple{Int64, Int64}, edge::UInt8, #unused#::Type{StaticArrays.SVector{2, Int64}})
@ Contour C:\Users\William\.julia\packages\Contour\YsFGr\src\interpolate.jl:39
[8] trace_contour(x::UnitRange{Int64}, y::UnitRange{Int64}, z::Matrix{Int64}, h::Float64, cells::Dict{Tuple{Int64, Int64}, UInt8})
@ Contour C:\Users\William\.julia\packages\Contour\YsFGr\src\Contour.jl:294
[9] contour
@ C:\Users\William\.julia\packages\Contour\YsFGr\src\Contour.jl:69 [inlined]
[10] #1
@ .\none:0 [inlined]
[11] iterate
@ .\generator.jl:47 [inlined]
[12] collect(itr::Base.Generator{StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, Contour.var"#1#2"{UnitRange{Int64}, UnitRange{Int64}, Matrix{Int64}}})
@ Base .\array.jl:787
[13] contours
@ C:\Users\William\.julia\packages\Contour\YsFGr\src\Contour.jl:83 [inlined]
[14] contours
@ C:\Users\William\.julia\packages\Contour\YsFGr\src\Contour.jl:90 [inlined]
[15] contours(x::UnitRange{Int64}, y::UnitRange{Int64}, z::Matrix{Int64})
@ Contour C:\Users\William\.julia\packages\Contour\YsFGr\src\Contour.jl:96
[16] top-level scope
@ REPL[94]:1
If it's not possible for contour to work with these arrays, may I suggest either restricting the type signature or automatically calling float.(arr)
on the input?
Thanks!
Currently, there is no simple way to access the coordinates of the contour lines. It would be nice with something like
function coordinates(c::Curve2)
N = length(c.vertices)
xlist = Array(Float64,N)
ylist = Array(Float64,N)
for (i,v) in enumerate(c.vertices)
xlist[i] = v[1]
ylist[i] = v[2]
end
xlist, ylist
end
to be used as xs, ys = coordinates(line)
but there might be an even better API for it. See also some discussion here: https://groups.google.com/forum/?fromgroups=#!topic/julia-users/yVKubPEoUYE
@tlycken I think we should decide on how the output of the contour function is structured before moving on. Otherwise, it might make it difficult to make changes without constantly breaking compatibility with other packages. How about something like
type ContourLine
level::Number
x::Vector{Float64}
y::Vector{Float64}
end
or
type ContourLine
level::Number
coordinates::Matrix{Float64}
end
What do you think?
This is breaking Gadfly on 0.4 master as well right now.
LoadError: LoadError: LoadError: LoadError: ArgumentError: invalid type for argument pos in method definition for add_vertex! at /home/juser/.julia/v0.4/Contour/src/Contour.jl:146
while loading /home/juser/.julia/v0.4/Contour/src/Contour.jl, in expression starting on line 145
while loading /home/juser/.julia/v0.4/Gadfly/src/statistics.jl, in expression starting on line 5
while loading /home/juser/.julia/v0.4/Gadfly/src/Gadfly.jl, in expression starting on line 1054
while loading In[3], in expression starting on line 1
in include at ./boot.jl:252
in include_from_node1 at ./loading.jl:134
in reload_path at ./loading.jl:158
in _require at ./loading.jl:70
in require at ./loading.jl:56
in include at ./boot.jl:252
in include_from_node1 at ./loading.jl:134
in include at ./boot.jl:252
in include_from_node1 at ./loading.jl:134
in reload_path at ./loading.jl:158
in _require at ./loading.jl:70
in require at ./loading.jl:53
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.