GithubHelp home page GithubHelp logo

stochss / gillespy2 Goto Github PK

View Code? Open in Web Editor NEW
71.0 71.0 30.0 139.27 MB

Modeling toolkit for biochemical simulation

Home Page: http://gillespy2.readthedocs.io/

License: GNU General Public License v3.0

Shell 1.39% Python 50.12% C++ 10.35% HTML 0.01% C 38.11% Batchfile 0.03%

gillespy2's Introduction

StochSS: Software as a service for simulation-driven investigations of stochastic biochemical models

StochSS provides advanced tools for simulating and analyzing biochemical systems as Software as a Service. StochSS supports a wide range of model types ranging from continuous ODEs to discrete (spatial) stochastic simulations as well as advanced model analysis workflows.

Try out StochSS Live!

Why use StochSS

StochSS provides both an easy-to-use UI for constructing biochemical models as well as intuitive UIs for the most common model analysis tools such as visualization of results, parameter sweeps and parameter inference. StochSS is built on top of Jupyter Hub, and this lets you seemlessly switch between UI representations and Notebooks exposing the full backend API. In this way a user can benefit from the best of graphical representations with a clear upgrade path to modeling as code. For this reason, StochSS is also uniquely suited for the computational biologist starting out with mathematical modeling of biochemical systems.

StochSS is a software project involving several leading research groups in computational systems biology. We welcome collaborators to help expand the capabilities of StochSS. Read more about the project at www.stochss.org.

StochSS is intended to be used as Software as a Service via StochSS Live!. The following instructions can help you set up your own local development environment or deploy your own instance as SaaS.

Deploying your own Single-User StochSS Instance

Requirements

At the moment StochSS development on Windows is not supported. You can try using Make for Windows, but this is untested!

Quickstart

  • Build and run the StochSS notebook server. This starts a local docker container running StochSS.
    make

  • Once your terminal calms down you'll see a link to your server that looks something like this: 127.0.0.1:8888/?token=X8dSfd... Navigate to that link and get started.

  • Your files are persisted on your local machine to the local\_data/ directory by default.

Setup

  • Build the docker container.
    make build

  • Run the container.
    make run

  • Rebuild frontend static assets on changes to files in /client .
    make watch

  • Upon changing backend code in stochss/handlers you can update a running StochSS notebook server.
    make update

  • [Optional] By default your files are saved to your local machine at ./local\_data/ . You can change this location by the changing value of DOCKER\_WORKING\_DIR in the file .env .

Add a python dependency

Use requirements.txt to add Python dependencies that will be installed into the StochSS docker container.

Deploying Multi-User StochSS

StochSS uses JupyterHub as the basis for the multi-user deployment. See their documentation for more details on configuring the JupyterHub environment.

Setup

  • In addition to the single-user requirements, you will need Docker Compose.

  • [Optional] To set admins for JupyterHub, make a file called userlist in the userlist/ directory. On each line of this file place a username followed by the word 'admin'. For example: myuser admin. If using Google OAuth, the username will be a Gmail address. Navigate to /hub/admin to use the JupyterHub admin interface.

  • [Optional] By default multi-user StochSS is set up to allocate 2 logical cpus per user, reserving 2 logical cpus for the hub container and underlying OS. You can define "power users" that are excluded from resource limitations using the same method as above for adding an admin, but instead of following the username with 'admin', use the keyword 'power' instead.

  • [Optional] To disseminate messages to all users, make a JSON decodable file called messages.json in the userlist/ directory. The contents of the messages file should be formatted as a list of dictionaries defining each message. Accepted keys are message, string containing the message to be display with tags for dates and time i.e. StochSS Live! will be down for scheduled maintenance on __DATE__ from __START__ to __END__ an additional __DATE__ tag can be added if the start and end dates differ, start, string representing the starting date and time i.e. Sep 26, 2022 14:00 EST, end, string representing the ending date and time i.e. Sep 26, 2022 18:00 EST, and style, a string containing a background color keyword i.e. warning or css i.e. background-color: rgba(160, 32, 240, 0.5) !important;.

[
    {
        "message": "StochSS Live! will be down for scheduled maintenance on __DATE__ from __START__ to __END__",
        "start": "Sep 26, 2022  14:00 EST",
        "end": "Sep 26, 2022  18:00 EST",
        "style": "info"
    },
    {
        "message": "StochSS Live! will be down for scheduled maintenance from"
    },
    {
        "message": "__DATE__ __START__ to __DATE__ __END__",
        "start": "Sep 26, 2022  14:00 EST",
        "end": "Sep 27, 2022  14:00 EST",
        "style": "warning"
    },
    {
        "message": "StochSS Live! is down for scheduled maintenance",
        "style": "background-color: rgba(160, 32, 240, 0.5) !important;"
    }
]

Run Locally

To run JupyterHub locally run make hub and go to http://127.0.0.1:8000/ .

Set Up A Staging Server

To set up the staging environment you'll need to set up Google OAuth for your instance. Once you're set up, you'll need to put your OAuth credentials in jupyterhub/secrets/.oauth.staging.env. Do not wrap these environment variables in quotes!

Example oauth file:

OAUTH_CALLBACK=https://staging.stochss.org/hub/oauth_callback
CLIENT_ID=8432438242-32432ada3ff23f248sf7ds.apps.googleusercontent.com
CLIENT_SECRET=adfsaf2327f2f7taafdsa34

After your oauth credentials are setup, run these commands:

make build
make build_hub
make run_hub_staging

Set Up A Production Server

Similar to staging, except you'll need the correct Google OAuth credentials set in jupyterhub/secrets/.oauth.prod.env.

Then:

make build
make build_hub
make run_hub_prod

gillespy2's People

Contributors

aratz avatar briandrawert avatar bryanrumsey avatar dilpath avatar ethangreen-dev avatar eweisger avatar fin109 avatar ghilmanbrock avatar github-actions[bot] avatar hodgespodge avatar jdreeve avatar jonrkarr avatar joshuafisherc avatar jtcooper10 avatar justjackson avatar makdl avatar mdip226 avatar mhucka avatar prasi372 avatar renato-lombardo avatar seanebum avatar technodivergent avatar thisisnotdalton avatar wrede avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

gillespy2's Issues

List of Enhancements

  • Implement a way for the user to see current progress

  • Create a Checkpoint Restart option for stop-starting

Adding parameter with duplicate name should throw ModelError

I was copy-pasting some parameters and forgot to change the name argument. The same thing happened for Species before - it just needs to be applied to Parameter as well (and presumably rate_rule?)

While fixing, maybe look at consistency of error messages. The "is a duplicate" error message is worded differently for reactions and species.

SSACSolver does not compile on win10

BuildError: Error encountered while compiling file:
Return code: 2.
Error:
b'UserSimulation.cpp: In member function \xe2\x80\x98virtual double PropensityFunction::evaluate(uint, uint*)\xe2\x80\x99:\nUserSimulation.cpp:36:28: error: expected \xe2\x80\x98;\xe2\x80\x99 before \xe2\x80\x98a\xe2\x80\x99\n return state[0]a*vol;\n ^\nUserSimulation.cpp:36:28: error: \xe2\x80\x98a\xe2\x80\x99 was not declared in this scope\nUserSimulation.cpp:39:20: error: \xe2\x80\x98Mustate\xe2\x80\x99 was not declared in this scope\n return Mustate[1]*state[1];\n ^\nmake: *** [UserSimulation] Error 1\n'

@briandrawert @Thisisnotdalton

Adding a dictionary of reactions raises a ModelError

When providing add_reaction with a dictionary of reactions, a ModelError is raised (see example code below).

    model = Model()
    rate = Parameter(name='rate', expression=0.5)
    model.add_parameter(rate)
    species1 = Species('A', initial_value=0)
    species2 = Species('B', initial_value=0)
    model.add_species([species1, species2])
    reactions = {
            name: Reaction(
                name=name, 
                reactants={species1: 1}, products={species2: 1}, rate=rate)
            for name in ["reaction1", "reaction2"]}
    model.add_reaction(reactions) # Raises ModelError

This is because reactions.values returns dict_values object instead of a list (see line 347 in core/gillespy2.py).

Remove numpy dependency from gillespy2

It would be good to have gillespy2 useable if numpy is not installed.

  • replace current BasicSSASolver with a 'downgraded' version of the numpy solver.
  • remove all 'numpy' references from gillespy2.py
  • break stochkit solver into its own file => re-structure the solver inheritance tree

DVODE errors in console when running hybrid_switch solver

      such that in the machine, T + H = T on the next step
      (H = step size). solver will continue anyway
     In above,  R1 =  0.6363051353986D-01   R2 =  0.5359752523533D-17
DVODE--  Warning..internal T (=R1) and H (=R2) are
      such that in the machine, T + H = T on the next step
      (H = step size). solver will continue anyway
     In above,  R1 =  0.6363051353986D-01   R2 =  0.5359752523533D-17
DVODE--  Above warning has been issued I1 times.
      it will not be issued again for this problem
     In above message,  I1 =         2
DVODE--  Warning..internal T (=R1) and H (=R2) are
      such that in the machine, T + H = T on the next step
      (H = step size). solver will continue anyway
     In above,  R1 =  0.6363106730433D-01   R2 =  0.4024238892615D-17
DVODE--  Warning..internal T (=R1) and H (=R2) are
      such that in the machine, T + H = T on the next step
      (H = step size). solver will continue anyway
     In above,  R1 =  0.6363106730433D-01   R2 =  0.4024238892615D-17
DVODE--  Above warning has been issued I1 times.
      it will not be issued again for this problem
     In above message,  I1 =         2
DVODE--  Warning..internal T (=R1) and H (=R2) are
      such that in the machine, T + H = T on the next step
      (H = step size). solver will continue anyway
     In above,  R1 =  0.6363127067517D-01   R2 =  0.5933865203329D-17
DVODE--  Warning..internal T (=R1) and H (=R2) are
      such that in the machine, T + H = T on the next step
      (H = step size). solver will continue anyway
     In above,  R1 =  0.6363127067517D-01   R2 =  0.5933865203329D-17
DVODE--  Above warning has been issued I1 times.
      it will not be issued again for this problem
     In above message,  I1 =         2
DVODE--  Warning..internal T (=R1) and H (=R2) are
      such that in the machine, T + H = T on the next step
      (H = step size). solver will continue anyway
     In above,  R1 =  0.6363132661496D-01   R2 =  0.4101159916230D-17
DVODE--  Warning..internal T (=R1) and H (=R2) are
      such that in the machine, T + H = T on the next step
      (H = step size). solver will continue anyway
     In above,  R1 =  0.6363132661496D-01   R2 =  0.4101159916230D-17
DVODE--  Above warning has been issued I1 times.
      it will not be issued again for this problem
     In above message,  I1 =         2

There's an almost endless amount of these that will stop for a while, then come back. This appears to be specifically related to the B. Anthracis model having the numerical stiffness in it. This page seems to support the idea that instead of just changing maxsteps, we need to select a different method altogether.

Fix ODE solver

Import structure for solver needs to be fixed to fit within the new project structure

In the GeneticToggleSwitch example, the ODE solver is giving strange result for the last element of the array.

TypeError when plotting results of NumPySSASolver


TypeError Traceback (most recent call last)
in ()
1 fig = plt.figure(figsize=(20,8))
----> 2 plt.plot(results['time'], results['S_'], 'g-', label='Anthrax')
3 plt.plot(results['time'], results['M_'], 'b-', label='Macrophage')
4 plt.plot(results['time'], results['H_'], 'k-', label='Infected Cell')
5 plt.xlabel("Time in Seconds", fontsize=12)

TypeError: list indices must be integers or slices, not str

<matplotlib.figure.Figure at 0x155eec4d860>

@seanebum
@briandrawert

Enable timeout for simulations

Would need the capability to set a timeout for the simulation. When running large parameter sweeps, it is common that some paramter combinations lead to explosion of some species, with run times growing exponentially as a consequence. We need to be able to quench such trajectories.

BasicSSASolver not structuring output data correctly

Model:

class DayModel(gillespy2.Model):
    def __init__(self, parameter_values=None, init_v=0):
        # initialize
        gillespy2.Model.__init__(self, name="Macrophage")
        
        # species
        S_ = gillespy2.Species(name='S_', initial_value=4e3) # low = 4e3; mid = 2e4; high = 1e7
        
        A_ = gillespy2.Species(name='A_', initial_value=6e9) # A = Sa/(k2*S+MuA)
        
        H1 = gillespy2.Species(name='H1', initial_value=0)
        H2 = gillespy2.Species(name='H2', initial_value=0)
        H3 = gillespy2.Species(name='H3', initial_value=0)
        H4 = gillespy2.Species(name='H4', initial_value=0)
        H5 = gillespy2.Species(name='H5', initial_value=0)
        H6 = gillespy2.Species(name='H6', initial_value=0)
        
        HLN1 = gillespy2.Species(name='HLN1', initial_value=0)
        HLN2 = gillespy2.Species(name='HLN2', initial_value=0)
        HLN3 = gillespy2.Species(name='HLN3', initial_value=0)
        HLN4 = gillespy2.Species(name='HLN4', initial_value=0)
        HLN5 = gillespy2.Species(name='HLN5', initial_value=0)
        HLN6 = gillespy2.Species(name='HLN6', initial_value=0)
        
        self.add_species([S_,A_,H1,H2,H3,H4,H5,H6,HLN1,HLN2,HLN3,HLN4,HLN5,HLN6])
        
        # parameters
        # num(spores) per macrophage
        ns = gillespy2.Parameter(name='ns', expression=3) # avg = 3.38
        
        # rate of phagocytosis
        k2 = gillespy2.Parameter(name='k2', expression=1e-5)
        
        # migration to TMLN
        k3 = gillespy2.Parameter(name='k3', expression=1e3)

        # source of macrophages per hour
        Sa = gillespy2.Parameter(name='Sa', expression=3e8)
        
        # decay rate of macrophages
        MuA = gillespy2.Parameter(name='MuA', expression=0.05)
        
        self.add_parameter([ns,k2,k3,Sa,MuA])
        
        # reactions
        R1 = gillespy2.Reaction(
            name='R1',
            reactants={S_:1, A_:1},
            products={H1:1},
            rate=k2
        )
        
        R2 = gillespy2.Reaction(
            name='R2',
            reactants={S_:1, H1:1},
            products={H2:1},
            rate=k2
        )
        
        R3 = gillespy2.Reaction(
            name='R3',
            reactants={S_:1, H2:1},
            products={H3:1},
            rate=k2
        )
        
        R4 = gillespy2.Reaction(
            name='R4',
            reactants={S_:1, H3:1},
            products={H4:1},
            rate=k2
        )
        
        R5 = gillespy2.Reaction(
            name='R5',
            reactants={S_:1, H4:1},
            products={H5:1},
            rate=k2
        )
        
        R6 = gillespy2.Reaction(
            name='R6',
            reactants={S_:1, H5:1},
            products={H6:1},
            rate=k2
        )
        
        # To the lung
        R7 = gillespy2.Reaction(
            name='R7',
            reactants={H1:1},
            products={HLN1:1},
            rate=k3
        )
        
        R8 = gillespy2.Reaction(
            name='R8',
            reactants={H2:1},
            products={HLN2:1},
            rate=k3
        )
        
        R9 = gillespy2.Reaction(
            name='R9',
            reactants={H3:1},
            products={HLN3:1},
            rate=k3
        )
        
        R10 = gillespy2.Reaction(
            name='R10',
            reactants={H4:1},
            products={HLN4:1},
            rate=k3
        )
        
        R11 = gillespy2.Reaction(
            name='R11',
            reactants={H5:1},
            products={HLN5:1},
            rate=k3
        )
        
        R12 = gillespy2.Reaction(
            name='R12',
            reactants={H6:1},
            products={HLN6:1},
            rate=k3
        )
                
        self.add_reaction([R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12])
        t = numpy.linspace(0,40,801)
        self.timespan(t)
        #print(t)

When running this model through the BasicSSASolver, the results array is not always structured in a manner consistent with the other solvers while at other times it is.

For instance:
When using the value k3 <= 0.25, I can print/plot results[0]['time']
When using the value k3 >= 0.26, I must use results['time'] instead

ValueError: all the input array dimensions except for the concatenation axis must match exactly

After importing BasicODESolver and trying to run it on a model...
%time results = model.run(solver=BasicODESolver())

I get the following error...

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-fe28477fa8a0> in <module>()
----> 1 get_ipython().magic('time results = model.run(solver=BasicODESolver())')

C:\Program Files\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py in magic(self, arg_s)
   2156         magic_name, _, magic_arg_s = arg_s.partition(' ')
   2157         magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
-> 2158         return self.run_line_magic(magic_name, magic_arg_s)
   2159 
   2160     #-------------------------------------------------------------------------

C:\Program Files\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py in run_line_magic(self, magic_name, line)
   2077                 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
   2078             with self.builtin_trap:
-> 2079                 result = fn(*args,**kwargs)
   2080             return result
   2081 

<decorator-gen-60> in time(self, line, cell, local_ns)

C:\Program Files\Anaconda3\lib\site-packages\IPython\core\magic.py in <lambda>(f, *a, **k)
    186     # but it's overkill for just that one bit of state.
    187     def magic_deco(arg):
--> 188         call = lambda f, *a, **k: f(*a, **k)
    189 
    190         if callable(arg):

C:\Program Files\Anaconda3\lib\site-packages\IPython\core\magics\execution.py in time(self, line, cell, local_ns)
   1178         else:
   1179             st = clock2()
-> 1180             exec(code, glob, local_ns)
   1181             end = clock2()
   1182             out = None

<timed exec> in <module>()

J:\Users\devgruseal\OneDrive\College\Research\B_anthracis\gillespy2\gillespy2.py in run(self, number_of_trajectories, seed, solver, stochkit_home, profile, debug, show_labels)
    403                                   number_of_trajectories=number_of_trajectories,
    404                                   stochkit_home=stochkit_home, profile=profile, debug=debug,
--> 405                                   show_labels=show_labels)
    406             else:
    407                 raise SimuliationError(

J:\Users\devgruseal\OneDrive\College\Research\B_anthracis\gillespy2\basic_ode_solver.py in run(self, model, t, number_of_trajectories, increment, seed, debug, profile, show_labels, stochkit_home)
     46         # return results
     47         # return[results, time]
---> 48         return np.append(results, time.reshape(len(time), 1), axis=1)

C:\Program Files\Anaconda3\lib\site-packages\numpy\lib\function_base.py in append(arr, values, axis)
   4584         values = ravel(values)
   4585         axis = arr.ndim-1
-> 4586     return concatenate((arr, values), axis=axis)
   4587 


ValueError: all the input array dimensions except for the concatenation axis must match exactly

Species constructor should not convert to int() in continuous species.

If species is discrete, check if value is int. If not throw ValueError.

If species is less than zero, throw value error.

Add argument to constructor "allow_negative_populations=False", if it is set, don't throw error.

In the importSBML() function, add "allow_negative_populations=False" argument. Pass the value of this argument when you create species. This will

NumPySSASolver propensity function error

species

    S = gillespy2.Species(name='S', initial_value=init_v)
    A = gillespy2.Species(name='A', initial_value=200)
    H = gillespy2.Species(name='H', initial_value=0)
    
    self.add_species([S,A,H])
    
    # parameters
    k2 = gillespy2.Parameter(name='k2', expression=1e-10)
    k3 = gillespy2.Parameter(name='k3', expression=0.05)
    Sa = gillespy2.Parameter(name='Sa', expression=3e8)
    MuA = gillespy2.Parameter(name='MuA', expression=0.05)

%time results = model.run(solver=NumPySSASolver, show_labels=True)

File "", line 1
lambda x:x[0]a*vol
^
SyntaxError: invalid syntax

Note: parameter 'Sa' and species 'S' - search & replace on line 58 is struggling

@briandrawert @Thisisnotdalton

Auto solver has traces of BasicSSASolver

gillespy2\solvers\auto\ssa_solver.py still contains a reference to the BasicSSASolver which I see has been removed from the develop branch.

I changed the default to the NumPy SSA solver in my travis-testing-fix branch which I will create a PR for soon, but I wanted to create this issue just to notify everyone
@briandrawert @seanebum @Thisisnotdalton

Invalid syntax on hybrid_switch when running this model

Dr. Drawert and I had discussed running the B. Anthracis simulation through the hybrid_switch model (since it has a combination of large and small populations). This is the error I got when I tried to do so:

File "<string>", line 1
    0 + k3*HLN1k3*HLN1k3*HLN1k3*HLN1k3*HLN1 + k3*HLN2k3*HLN2k3*HLN2k3*HLN2k3*HLN2 + k3*HLN3k3*HLN3k3*HLN3k3*HLN3k3*HLN3 + k3*HLN4k3*HLN4k3*HLN4k3*HLN4k3*HLN4 + k3*HLN5k3*HLN5k3*HLN5k3*HLN5k3*HLN5k3*HLN5 + k3*HLN6k3*HLN6k3*HLN6k3*HLN6k3*HLN6k3*HLN6k3*HLN6 - k5*Be*(1 - (Be/BeMAX)) + k5*Be*(1 - (Be/BeMAX))k5*Be*(1 - (Be/BeMAX)) - k6*E*Be/vol - (k8*N*Be)/(1+(Ta/CT1)) - k1*E*Be/vol + k1*E*Be/vol - (k9*Be*E*N0)/(1+(Ta/CT2)) + (k9*Be*E*N0)/(1+(Ta/CT2)) - k4*(Be/(CTB+Be)) + k4*(Be/(CTB+Be))
                                                                                                                                                                                                                                                                                                                 ^
SyntaxError: invalid syntax

Possibly an issue with propensity_function?

Submodel - Lung+Lymph.zip

Exception handling: Adding a duplicate [Species, Parameter, Reaction] should raise Error specific to that entity

I noticed this while fixing some broken unit tests...

For example, in gillespy2/core/gillespy2.py:

def problem_with_name(self, name):
        [...]
        if name in self.listOfParameters:
            return ModelError('Name "{}" is unavailable. A parameter with that name exists.'.format(name))

According to gillespyError.py, we have specific exceptions - SpeciesError, ReactionError, ParameterError, etc

I make a motion that in a future release, we utilize those for more robust error reporting.

No module named gillespySolver

Gillespy2 was installed as sudo pip3 insall git+https://github.com/GillesPy2/GillesPy2.git@develop

Then it got the following error:

skarmavbild 2018-09-24 kl 15 49 09

BasicODESolver refactor adds extraneous dimension to results array

I did not notice this artifact before until starting to work on the anthrax project, but the results array returns an array of an array.

For instance:
results['HLN1'] returns:
[array([ 0. , 16653785.74877705, 26002627.6329709 ,
28718802.60260643, 29433607.79326785, 29615997.02363227,
29661857.99554113, 29673290.96226966, 29676126.01726486,
29676826.70805103, 29676999.53284013, 29677042.10686238,
29677052.58669181, 29677055.1651728 , 29677055.7994111 ,
29677055.95539059, 29677055.99374701, 29677056.00317853,
29677056.00549757, 29677056.00606777, 29677056.00620797])]

Whereas the old solver returns:
[0.0, 16653785.74877705, 26002627.6329709, 28718802.602606427, 29433607.79326785, 29615997.02363227, 29661857.99554113, 29673290.962269664, 29676126.017264858, 29676826.708051026, 29676999.53284013, 29677042.106862377, 29677052.58669181, 29677055.165172804, 29677055.799411096, 29677055.95539059, 29677055.993747007, 29677056.003178526, 29677056.00549757, 29677056.00606777]

That means to access the last element, I would need results['HLN1'][0][-1].

Fix tests in develop branch

There are 2 failing tests and 1 erroring test in the develop branch (test_simple_model.py) that need to be fixed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.