fumitoh / modelx Goto Github PK
View Code? Open in Web Editor NEWUse Python like a spreadsheet!
Home Page: https://modelx.io
License: GNU Lesser General Public License v3.0
Use Python like a spreadsheet!
Home Page: https://modelx.io
License: GNU Lesser General Public License v3.0
I didn't manage to find the way to debug cell calculations using normal debugger (pyCharm / Spyder).
I'm using the following function to get into the space namespace:
def debug_space(space):
for c in space.cells:
globals()['%s' % c] = space.cells[c]
How do you do it?
I need to create a cell with no arguments and some data inside. Is there a way to do it so that "write_model" will capture it?
I don't understand the meaning of:
• param_cols (optional)
• names_col (optional)
• param_rows (optional)
• space_param_order
• cell_param_order (optional)
in the function- new_space_from_excel(book, range_, sheet=None, name=None, names_row=None, param_cols=None, space_param_order=None, cells_param_order=None, transpose=False, names_col=None, param_rows=None)
Can you please explain what they do in layman language?
spyder-modelx 0.11.0 does not work with Spyder 5.1.5 onwards.
As of Jan 1, 2022, Spyder 5.0.4 is the last version that is tested fine with spyder-modelx 0.11.0.
When for some reason the value of the cell can't be evaluated, the error log contains only function name, not arguments, with which it was called. E.g.:
Traceback (most recent call last):
File "<string>", line 3, in CF_discounted_df
File "...\Anaconda3\lib\site-packages\pandas\core\indexing.py", line 204, in __setitem__
indexer = self._get_setitem_indexer(key)
It would really be helpful for troubleshooting to see the arguments with which function CF_discounted_df
was called.
Hi,
I have read through and debug some scripts of modelx (the previous version). I have uploaded 2
documents, which include:
Thanks.
Hi,
I'm getting an error when trying to load my model, it has worked fine until now and also old versions that has worked before has stopped working...
I have tried to uninstall modelx/spyder modelx as well as running it in another environment but with the same result, see execution below.
Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.
IPython 7.19.0 -- An enhanced Interactive Python.
Restarting kernel...
import modelx as mx
model=mx.read_model("A:/Christian/Modeller/CF-model/Company/V0.2")
Traceback (most recent call last):
File "", line 1, in
model=mx.read_model("A:/Christian/Modeller/CF-model/Company/V0.2")
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\core\api.py", line 646, in read_model
return _serialize.read_model(_system, model_path, name=name)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\serialize_init_.py", line 123, in read_model
system, path).read_model(**kwargs)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\serialize\serializer_4.py", line 1037, in read_model
model = self._read_model_inner()
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\serialize\serializer_4.py", line 1064, in _read_model_inner
self.read_pickledata()
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\serialize\serializer_4.py", line 1151, in read_pickledata
custom_load, file, "b")
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\serialize\ziputil.py", line 366, in read_file_utf8
return read_file(callback, path, mode, encoding="utf-8", newline=newline)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\serialize\ziputil.py", line 362, in read_file
return callback(f)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\serialize\serializer_4.py", line 1139, in custom_load
return unpickler.load()
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\io\baseio.py", line 220, in setstate
self._on_unserialize(state)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\io\pandasio.py", line 133, in _on_unserialize
self._read_pandas()
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\modelx\io\pandasio.py", line 141, in _read_pandas
self._data.load_from, **self._read_args)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\excel_base.py", line 304, in read_excel
io = ExcelFile(io, engine=engine)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\excel_base.py", line 821, in init
self._reader = self._enginesengine
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\excel_openpyxl.py", line 485, in init
super().init(filepath_or_buffer)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\excel_base.py", line 353, in init
self.book = self.load_workbook(filepath_or_buffer)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\excel_openpyxl.py", line 497, in load_workbook
filepath_or_buffer, read_only=True, data_only=True, keep_links=False
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\openpyxl\reader\excel.py", line 313, in load_workbook
data_only, keep_links)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\openpyxl\reader\excel.py", line 124, in init
self.archive = _validate_archive(fn)
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\site-packages\openpyxl\reader\excel.py", line 96, in _validate_archive
archive = ZipFile(filename, 'r')
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\zipfile.py", line 1258, in init
self._RealGetContents()
File "C:\Users\csalmeron\AppData\Local\Continuum\anaconda3\lib\zipfile.py", line 1325, in _RealGetContents
raise BadZipFile("File is not a zip file")
BadZipFile: File is not a zip file
Until version 13.1 I used to store explicit reference to the model as a ref:
m = mx.new_model()
m.model = m
Version 14 doesn't allow it as it seems to have built in "model" ref. But for some reason this ref isn't recongnisable in the space formula namespace:
import modelx as mx
m = mx.new_model()
print(m.model)
def s_arg():
print(model)
s = mx.new_space(formula=s_arg)
s()
I have been fighting for a long time with configuration of xlwings to make the following modelx line to work with it:
from qtpy.QtWidgets import QApplication
Sometimes I succedded, but with the recent Anaconda update I have this issue again.
I don't use QApplication GUI. The problem seems to be that the import command doesn't break immediately and somewhere underneath it throws
qtpy.PythonQtError: No Qt bindings could be found raise PythonQtError('No Qt bindings could be found')
This errors isn't catched by except ImportError
statement in the code and xlwings crashes.
So I'm now commenting out line
from modelx.qtgui.api import *
in the modelx __init__.py
, but that's ugly
import modelx as mx
m, s_p = mx.new_model(), mx.new_space()
s_p.a = 1
s_c = s_p.new_space()
print(s_c.a)
Hi, I have just started using modelx, and it seems that modelx does not allow to read models with reference equal to np.inf, the model can be used, but can not be read from a zip file. The solution I have found is store the reference like a np.array with a only element which is np.inf.
How to make dynamic space cross-referencing each other? I've tried the following and it doesn't work:
from modelx import *
m = new_model()
def try_param_x(a):
return {'refs': {'y': y_base(a), 'bases': _self}}
m.new_space(name='x', formula=try_param_x)
def try_param_y(a):
return {'refs': {'x': x_base(a), 'bases': _self}}
m.new_space(name='y', formula=try_param_y, refs={'x_base': m.x})
m.x.y_base = m.y
m.x(1)
On a related subject: what is the way to profile modelx execution? I would like to see how long it takes to evaluate various functions.
Originally posted by @alebaran in #12 (comment)
Not a big thing, but I have noticed that when I've upgraded pandas from 0.25.3 to 1.0.4, I wasn't able to load previously saved model versions. Object structure probably changed a bit and it wasn't loading correctly. I was able to reproduce the issue by using
pickle.dump( pd.DataFrame(['a','b'],index=pd.MultiIndex.from_tuples(((1,2,3),(2,4,5)))), open( "try", "wb" ) )
with the older version and
pickle.load(open(r'try', "rb"))
with the newer one.
Pandas itself provides pickling function, which seems to ensure backward compatibility. The following works:
pd.DataFrame(['a','b'],index=pd.MultiIndex.from_tuples(((1,2,3),(2,4,5)))).to_pickle('try')
with the older version and
pd.read_pickle('try')
with the newer one.
It would be nice to have to use native pandas pickling.
modelx version: 0.19.0
execute_actions
does not work correctly under the scenario below.
generate_actions
is assigned to a reference in the model and the model is written to disk.execute_actions
.I'm thinking about the best way to make use of the multi-core processor I've on my computer to speed up the model calculations. It seems that modelx is programmed to be single-threaded. Do I understand correctly that it is expected to stay this way?
I see the following ways to use more computer resources:
model.save; mx.open_model()
. This method gets slower, when opening model with lots of results in it. Another method is to copy a model: import copy; model2 = copy.deepcopy(model)
. This method seems to be 5 times faster, but the copy of the model for some reason doesn't work:import modelx as mx
import copy
m = mx.new_model(); mx.new_space()
@mx.defcells
def a():
return 1
m2 = copy.deepcopy(m)
m2.Space1.a()
Traceback (most recent call last):
File "...\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3326, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-3-f474ed443ec3>", line 9, in <module>
m2.Space1.a()
File "...\Anaconda3\lib\site-packages\modelx\core\cells.py", line 77, in __call__
return self._impl.get_value(args, kwargs)
File "...\Anaconda3\lib\site-packages\modelx\core\cells.py", line 568, in get_value
value = self.system.executor.eval_cell(node)
AttributeError: 'CellsImpl' object has no attribute 'system'
multiprocessing
module, but so far wasn't successful. I'll keep trying.Thank you for this development. Unfortunately it breaks in case function is used within the cell:
from modelx import *
m, s = new_model(), new_space()
@defcells
def a(t):
if t > 0:
return sum([a(t - i) for i in range(1, 2)])
else:
raise ValueError()
a(1)
Originally posted by @alexeybaran in #16 (comment)
I have followed the instruction on https://modelx.readthedocs.io/en/latest/spyder.html to install the spyder plugin though I am not able to show the formula after clicking "Show Formula."
I also tried it on another PC without success. My spyder version is 3.3.6.
Below is an illustration of the blocking issue I have after upgrading modelx to the recent version with updated dynamic reference structure:
import modelx as mx
m = mx.new_model()
m.new_space('a')
def t_arg():
pass
m.new_space('b')
m.new_space('c', formula=t_arg, refs={'x': m.b})
m.a.new_space('d',refs={'c':m.c()})
print(m.a.d.c)
mx.write_model(m,'m')
m2 = mx.read_model('m')
print(m2.a.d.c)
I wanted to get more infos from type Space, I tried JSON dumps(space), but failed.
Hi Sir,
I was facing a problem. the space inheritance is not working in Spyder in modelx. I even tried copy pasting the example you mentioned in your blog in 'More Complex Example' ( http://docs.modelx.io/en/latest/tutorial.html#more-complex-example ). I was unable to use life space as the base in term life space.
Kindly help.
I'm currently using version 3.3.2 of spyder and 0.0.20 of modelx.
Thank you for releasing new version and all the improvement. There is one item, which creates a problem for me:
Before version 0.1.0, when a new input value is assigned to a node of a Cells, the values of the nodes depending on the input cells are cleared. From version 0.1.0, those values are recalculated.
The model I built has hundreds of parameters. After performing a base run, I do a number of sensitivity runs, in which several parameters are changed together. It often doesn't make sense to change one parameter without changing the other. It isn't beneficial to have the model automatically recalculating after each parameter is changed. It slows down the execution a lot and in some cases may lead to breakage of the model (as the parameter should only be changed together with the other one).
This change goes against the basic design principle of modelx that it only calculates what has been asked for. For example, in the base run I may produce 100 results, but in the sensitivity run I only need 1 number. But I can't control it, if everything is always recalculated.
I tried using modelx to similar a unit account deducting charges, applying growth. I wanted to project up to 720 months but there seems to be a limit that causes and error. The code I'm running is below:
from modelx import *
model, space = new_model(), new_space()
@defcells
def unit_reserve_opening(t):
if t == 1:
return 100000
else:
return unit_reserve_closing(t-1)
@defcells
def unit_reserve_after_growth(t):
return unit_reserve_opening(t) * (1 + 0.05) ** (1 / 12.0)
@defcells
def internal_amc(t):
return unit_reserve_after_growth(t) * 0.005 / 12
@defcells
def unit_reserve_after_charges(t):
return unit_reserve_after_growth(t) - internal_amc(t)
@defcells
def unit_reserve_closing(t):
return unit_reserve_after_charges(t) - 100
x = unit_reserve_after_charges[300]
print(unit_reserve_after_charges.series)
from modelx import *
import pandas as pd
m,s = new_model(),new_space('s')
series = pd.Series([1, 2], pd.Index([3, 4], name='a'))
s.new_cells_from_pandas(series, 'x')
s.x[3] = 10
write_model(m, 'm')
m2 = read_model('m')
print(m.s.x[3], m2.s.x[3])
import modelx as mx
m = mx.new_model(); s = mx.new_space()
s.a = False
mx.write_model(m, 'm')
m2 = mx.read_model('m')
There is a bug, when saving a model with a cell containing *args. The following code
from modelx import *
m, s = new_model(), new_space('s')
@defcells
def a(*args):
return b()
@defcells
def b():
return 1
a(1, 2)
m.save('m.mx')
m2 = open_model('m.mx', 'm2')
m2.s.b[()] = 2
Triggers an error
Traceback (most recent call last):
File "...\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3326, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-2-7aa69d0eb43e>", line 15, in <module>
m2.s.b[()] = 2
File "...\lib\site-packages\modelx\core\cells.py", line 97, in __setitem__
self._impl.set_value(tuplize_key(self, key), value)
File "...\lib\site-packages\modelx\core\cells.py", line 611, in set_value
self._store_value(key, value, True)
File "...\lib\site-packages\modelx\core\cells.py", line 623, in _store_value
self.clear_value(*key)
File "...\lib\site-packages\modelx\core\cells.py", line 644, in clear_value
self._model.clear_descendants(node)
File "...\lib\site-packages\modelx\core\model.py", line 220, in clear_descendants
del node[OBJ].data[node[KEY]]
KeyError: (((1, 2),),)
Note that the same call works for the model without saving: m.s.b[()] = 2
It seems that saving adds an extra tuple layer to the *args: (((1, 2),),)
This issue is blocking for me: if not fixed I'll need to significantly redesign / rebuild the code base.
Is it possible to set the doc string for a cell outside of a module import? After creating a cell with new_cell, I want to add a doc string, but using the doc property or set_property method return an error.
Not sure if this is an issue or intended. I wanted to use numpy so that each 'cell' represents an array.
In my example below 'unit_reserve_opening' is the opening account value at each projection timestep, but it get numpy to work, I had to import it within the function. Putting the import at the top of the module didn't work.
@defcells
def unit_reserve_opening(t):
import numpy as np
if t == 1:
return np.array([200, 300, 100, 400])
else:
return unit_reserve_closing(t-1)
Background:
I have a space that I use for inputs set up as references. I then have other spaces that have interdependent cell references. These spaces also depend on the input space and use its references. The issue that I'm getting is a error when I update the input references I get an error.
The error appears to be somewhat random. Once I ran the below script three times before getting the error and then on a fresh console the error appeared on the first run but not the second and then again on a third run.
Example Code:
import modelx as mx
model = mx.new_model("test")
inputs = model.new_space("Inputs")
inputs.a = 2
inputs.b = 3
calc = model.new_space("Pythagoras")
@mx.defcells
def pythagoras():
return (Inputs.a ** 2 + Add.add2() ** 2) ** .5
calc2 = model.new_space("Add")
@mx.defcells
def add2():
return Inputs.a + Inputs.b
calc.Inputs = inputs
calc.Add = calc2
calc2.Inputs = inputs
print(model.Pythagoras.pythagoras())
model.Inputs.a = 5
print(model.Pythagoras.pythagoras())
Output:
5.385164807134504
Traceback (most recent call last):
File "<ipython-input-4-68bc2d796ba1>", line 1, in <module>
runfile('**[removed]**/test.py', wdir='**[removed]**')
File "C:\Anaconda3201910\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 827, in runfile
execfile(filename, namespace)
File "C:\Anaconda3201910\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "**[removed]**/test.py", line 34, in <module>
model.Inputs.a = 5
File "C:\Anaconda3201910\lib\site-packages\modelx\core\space.py", line 974, in __setattr__
self._impl.set_attr(name, value, refmode="auto")
File "C:\Anaconda3201910\lib\site-packages\modelx\core\space.py", line 1657, in set_attr
self.spacemgr.change_ref(self, name, value, refmode)
File "C:\Anaconda3201910\lib\site-packages\modelx\core\model.py", line 1245, in change_ref
is_relative=is_relative)
File "C:\Anaconda3201910\lib\site-packages\modelx\core\space.py", line 1798, in on_change_ref
self.on_del_ref(name)
File "C:\Anaconda3201910\lib\site-packages\modelx\core\space.py", line 1815, in on_del_ref
self.self_refs.del_item(name)
File "C:\Anaconda3201910\lib\site-packages\modelx\core\space.py", line 100, in del_item
self.owner.model.clear_attr_referrers(self.fresh[name])
File "C:\Anaconda3201910\lib\site-packages\modelx\core\model.py", line 352, in clear_attr_referrers
descs = self.tracegraph.remove_with_descs(node)
File "C:\Anaconda3201910\lib\site-packages\modelx\core\model.py", line 61, in remove_with_descs
desc = nx.descendants(self, source)
File "C:\Anaconda3201910\lib\site-packages\networkx\algorithms\dag.py", line 71, in descendants
raise nx.NetworkXError("The node %s is not in the graph." % source)
TypeError: not all arguments converted during string formatting
Versions:
modelx = 0.13.1
networkx = 2.3
New_space_from_pandas doesn't allow non string space_params:
import pandas as pd
import numpy as np
import modelx as mx
def make_sample2(columns, idx_names):
"""Series with MultiIndex"""
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=idx_names)
return pd.DataFrame(np.random.randn(8, 2), index=index, columns=columns)
df=make_sample2(None, ["Col1", "Col2"])
space_params = [2]
m = mx.new_model()
m.new_space_from_pandas(
df, cells=["Col1", "Col2"], param=None,
space_params=space_params, cells_params=None)
There seems to be an issue with with dynamic space formula, when creating refs different from name:
from modelx import *
m = new_model()
def try_param(a):
return {'b': 1, 'bases': _self}
m.new_space(name='x', formula=try_param)
m.x(1)
Traceback (most recent call last):
File "...\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3326, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-2-bc5d1a811ba4>", line 6, in <module>
m.x(1)
File "...\Anaconda3\lib\site-packages\modelx\core\space.py", line 346, in __call__
return self._impl.get_dynspace(args, kwargs).interface
File "...\Anaconda3\lib\site-packages\modelx\core\space.py", line 1057, in get_dynspace
space = self._new_dynspace(**space_args)
TypeError: _new_dynspace() got an unexpected keyword argument 'b'
The following circular reference code crashes the model without any warning or explanation:
import modelx as mx
m, s = mx.new_model(), mx.new_space()
@mx.defcells
def a():
return b()
@mx.defcells
def b():
return a()
s.a()
The following code including space referencing dynamic space breaks.
from modelx import *
m = new_model()
def t_arg(t):
pass
m.new_space('s1', formula=t_arg)
m.new_space('s2', refs={'s1': m.s1(0)})
write_model(m, 'm')
read_model('m')
ZipFile()
seems to have compression parameter, which is defaulted to no compression. Here is one of the options making it compress: compression=zipfile.ZIP_DEFLATED
Originally posted by @alexeybaran in #33 (comment)
In the actuarial model example:
x0
and n
are defined as Refs in Base and redefined as Cells._self
is passed as base to ItemSpace
What is the reason "parent" not defined in dynamic space formula? See the code below.
from modelx import *
new_model()
def s_arg(t):
print(parent)
pass
s = new_space(formula=s_arg)
s(1)
import_module
breaks if I have:
import b
in the beginning of the file import a
in the beginning of the fileLine 1507 in cf8a2a9
String cell arguments are shown without parentheses in preds
.
from modelx import *
m,s = new_model('m'), new_space('s')
@defcells
def a(name):
return 'Hello ' + name
@defcells
def b(name):
return a(name)
b('World')
b.preds('World')
It returns [m.s.a(name=World)=Hello World]
. This makes it inconvenient, if I want to follow through the dependencies by calling m.s.a(name=World)
. It would be much more convenient if the preds
function returned [m.s.a(name='World')='Hello World]'
. Parentheses around the output aren't important.
What is the reason that a cell provided as an argument to another cell is converted to the value? II was trying to build generic cell operating on outputs of the other cells with multiple arguments.
I can't save the model, opened from file.
import modelx as mx
m, s = mx.new_model(), mx.new_space()
@mx.defcells
def a():
return 1
m.save('m.mx')
m2 = mx.open_model('m.mx')
m2.save('m2.mx')
I'm trying to measure speed of the modelx with 500 variables and 40 time steps (see the code below). I get 25 seconds execution time, which is terribly slow, if you compare it with Excel.
The time is the same, when I trigger recalculation, when the cells are already created (second part of the speed measurement below)
from modelx import *
import time
model = new_model()
space = model.new_space()
@defcells
def a(t):
return 1
@defcells
def PnL_b(t, var):
return a(0)
times = range(1,41+1)
variables = range(1,500+1)
start = time.time()
for t in times:
for var in variables:
space.PnL_b(t, var)
time1 = time.time()
print(time1 - start)
space.a[0] = 2
for t in times:
for var in variables:
space.PnL_b(t, var)
print(time.time() - time1)
Why return? Must be not reaching here.
Line 484 in 527758e
There is a problem, when saving previously zipped model with embedded module. The issue seems to be that the module code isn't available for saving function as the temporary folder is removed after opening of the model.
import modelx as mx
m = mx.new_model()
m.new_module('gf', 'generic_func.py', 'generic_func.py')
m.zip('m.zip')
m2 = mx.read_model('m.zip')
m2.zip('m2.zip')
One more thing as we are talking about model saving. Have you thought about zip archiving the folder? It will save space and make it more convenient to send the model around. We save the model on OneDrive cloud and it ends up syncing a hundered files instead of 1.
Using zip archive will be the same as what Excel does with its files.
I can also implement this myself.
Originally posted by @alebaran in #32 (comment)
import modelx as mx
m=mx.new_model('a')
def s_arg(t):
pass
s=m.new_space(formula=s_arg)
@mx.defcells
def b():
return 1
s(1).b[()] = 2
m.zip('a.zip')
In a separate console window:
import modelx as mx
mx.read_model('a.zip','e')
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.