{"id":20885815,"url":"https://github.com/compas-dev/compas_cloud","last_synced_at":"2025-05-12T19:31:25.633Z","repository":{"id":49543296,"uuid":"221418499","full_name":"compas-dev/compas_cloud","owner":"compas-dev","description":"COMPAS Remote Procedure Calls using websockets","archived":false,"fork":false,"pushed_at":"2024-07-29T20:05:41.000Z","size":243,"stargazers_count":6,"open_issues_count":9,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-13T19:03:27.768Z","etag":null,"topics":["remote-procedure-calls","sessions","websockets"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/compas-dev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-13T09:13:55.000Z","updated_at":"2024-07-29T20:05:45.000Z","dependencies_parsed_at":"2024-02-01T09:54:08.389Z","dependency_job_id":null,"html_url":"https://github.com/compas-dev/compas_cloud","commit_stats":{"total_commits":142,"total_committers":5,"mean_commits":28.4,"dds":0.09154929577464788,"last_synced_commit":"e4bae1c296ef8482b874f6a3ebe60a6f3ee7ee10"},"previous_names":["blockresearchgroup/compas_cloud"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compas-dev%2Fcompas_cloud","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compas-dev%2Fcompas_cloud/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compas-dev%2Fcompas_cloud/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compas-dev%2Fcompas_cloud/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/compas-dev","download_url":"https://codeload.github.com/compas-dev/compas_cloud/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253808197,"owners_count":21967504,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["remote-procedure-calls","sessions","websockets"],"created_at":"2024-11-18T08:14:43.670Z","updated_at":"2025-05-12T19:31:25.220Z","avatar_url":"https://github.com/compas-dev.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# compas_cloud\ncompas_cloud is the further development of `compas.rpc` module. It uses websocktes instead of RESTful APIs to allow bi-directional communications between various front-end programs like Rhino, GH, RhinoVault2, blender or web-based viewers that are implemented in different enviroments including CPython, IronPython and Javascript. It also allows to save certain variables to backend inside a user session to avoid overheads created by redundant data transfers.\n\n## Installation\n\n### Install from source\n```bash\ngit clone https://github.com/BlockResearchGroup/compas_cloud.git\npip install -e .\n```\n\n\n### Install for Rhino\n```bash\npython -m compas_rhino.install -p compas_cloud\n```\n\n\n## Using Proxy\n\n### Running the sever:\n\n1. Start from command line:\n    ```bash\n    python -m compas_cloud.server\n    ```  \n2. The proxy will automatically start a server in background if there isn't one to connect to. If the server is started this way, it will keep operating in background and reconnect if a new proxy is create later.\n\n### Basic Usage\nOne of the main purposes of compas_cloud is to allow usage of full COMPAS functionalities in more closed envinroments like IronPython. The following example shows how to use a numpy based COMPAS function through a proxy which can be run in softwares like Rhino:  \n[basic.py](examples/basic.py)\n```python\nfrom compas_cloud import Proxy\nfrom compas.geometry import Translation\n\n\nproxy = Proxy()\ntransform_points_numpy = proxy.function('compas.geometry.transform_points_numpy')\n# create a proxy funciton\n\npts = [[0,0,0], [1,0,0]]\nT = Translation([100, 0, 0]).matrix\ntransform_points_numpy(pts, T) # call the function through proxy\nprint(result)\n# will print: [[100.0, 0.0 ,0.0], [101.0, 0.0, 0.0]]\n```\n\n### Caching\nCompas_cloud allows to cache data or function outputs at server side instead of sending them to the front-end all the time. This can vastly improve the performance for long iterative operations that involves large amount of data inputs and outputs.\n\n[caching.py](examples/caching.py)\n```python\nfrom compas_cloud import Proxy\nfrom compas.geometry import Translation\n\n# CACHING INPUT PARAMETERS\n\nproxy = Proxy()\ntransform_points_numpy = proxy.function('compas.geometry.transform_points_numpy')\n# create a proxy funciton\n\npts = [[0,0,0], [1,0,0]]\npts_cache = proxy.cache(pts) # cache the object to server side and return its reference\nprint(pts_cache) # will print: {'cached': some_unique_id}\n\nT = Translation([100, 0, 0]).matrix\nresult = transform_points_numpy(pts_cache, T) # call the function through proxy\nprint(result) # will print: [[100.0, 0.0 ,0.0], [101.0, 0.0, 0.0]]\n\n\n\n# CACHING RETURNED DATA\n\ntransform_points_numpy = proxy.function('compas.geometry.transform_points_numpy', cache=True)\n# this function will now return a cache object instead of the actual data\n\npts = [[0,0,0], [1,0,0]]\npts_cache = proxy.cache(pts)\nprint(pts_cache) # will print: {'cached': some_unique_id}\n\nT = Translation([100, 0, 0]).matrix\nresult_cache = transform_points_numpy(pts_cache, T) # call the function through proxy\nprint(result_cache) # will print: {'cached': some_unique_id}\n\nresult = proxy.get(result_cache) # fetch the actual data of the cache object\nprint(result) # will print: [[100.0, 0.0 ,0.0], [101.0, 0.0, 0.0]]\n```\n\n### Server control\nUser can `restart/check/shutdown` a connected server from proxy with commands in following example: [server_control.py](examples/server_control.py)\n```python\nfrom compas_cloud import Proxy\nimport time\n\nprint(\"\\n starting a new Proxy and by default starts a server in background\")\nproxy = Proxy(background=True)\ntime.sleep(3)\n\nprint(\"\\n restarting the background server and open a new one in a prompt console\")\nproxy.background = False\nproxy.restart()\ntime.sleep(3)\n\nprint(\"\\n check if the proxy is healthily connected to server\")\nprint(proxy.check())\ntime.sleep(3)\n\n\nprint(\"\\n shut the the server and quite the program\")\nproxy.shutdown()\ntime.sleep(3)\n```\n\n\n### Other Examples\nA [benchmark test](examples/benchmark.py) comparing pure python and numpy with caching to transform 10k points for 100 times: \n```bash\npython examples/benchmark.py\n```\n\n[Iterative plotting](examples/dr_numpy.py) example with callbacks:    \n```bash\npython examples/dr_numpy.py\n```\n\n[Using non-compas packages like numpy with IronPython](examples/example_numpy.py):  \nrun `examples/example_numpy.py` with Rhino\n\n\n## Using Sessions (Currently only work with MacOS/Linux)\n`Compas_cloud.Sessions` is a task-manager class that helps to execute a batch of long-lasting tasks such as FEA and DEM simulations. It creates a queue of tasks and a collection of workers to execute the tasks in parallel and save the program logs into each corresponding locations. `Sessions` can be run either locally or in a background server through `Proxy`.\n\n### Examples\n\n#### [Running Sessions Locally](examples/sessions_local.py):\n```bash\npython examples/sessions_local.py\n```\n\n```python\nfrom compas_cloud import Sessions\n\n# define a psuedo task that will take few seconds to finish\ndef func(a):\n    import time\n\n    for i in range(a):\n        time.sleep(1)\n        print('sleeped ', i, 's')\n\n# initiate a session object, and specify where the logs will be stored and number of workers\n# if no log_path is given, all logs will be streamed to terminal and not saved\n# the default worker_num is equal to the number of cpus accessible on the computer\ns = Sessions(log_path=None, worker_num=4)\n\n# add several tasks to the session using different parameters\ns.add_task(func, 1)\ns.add_task(func, 2)\ns.add_task(func, 3)\ns.add_task(func, 4)\ns.add_task(func, 5)\n\n# kick of the taks and start to listen to the events when tasks start or finish\ns.start()\ns.listen()\n```\n\nYou should see following logs:\n\n```\n{'waiting': 5, 'running': 0, 'failed': 0, 'finished': 0, 'total': 5} ________ START\n{'waiting': 5, 'running': 0, 'failed': 0, 'finished': 0, 'total': 5} ________ using 4 workers\n{'waiting': 5, 'running': 0, 'failed': 0, 'finished': 0, 'total': 5} ________ worker 58884 started\n{'waiting': 4, 'running': 1, 'failed': 0, 'finished': 0, 'total': 5} ________ task-0: started\n{'waiting': 4, 'running': 1, 'failed': 0, 'finished': 0, 'total': 5} ________ worker 58885 started\n{'waiting': 4, 'running': 1, 'failed': 0, 'finished': 0, 'total': 5} ________ task-0: streaming log to temp/task-0.log\n{'waiting': 3, 'running': 2, 'failed': 0, 'finished': 0, 'total': 5} ________ task-1: started\n...\n\n{'waiting': 0, 'running': 0, 'failed': 0, 'finished': 5, 'total': 5} ________ task-4: finished\n{'waiting': 0, 'running': 0, 'failed': 0, 'finished': 5, 'total': 5} ________ worker 58884 terminated\n{'waiting': 0, 'running': 0, 'failed': 0, 'finished': 5, 'total': 5} ________ FINISHED\n```\n\n\n####  [Running Sessions With Proxy](examples/sessions_local.py):\n```bash\npython examples/sessions_remote.py\n```\n\n```python\nfrom compas_cloud import Proxy\n\n# define a psuedo task that will take few seconds to finish\ndef func(a):\n    import time\n\n    for i in range(a):\n        time.sleep(1)\n        print('sleeped ', i, 's')\n\n\n# initiate a Sessions object through Proxy that connects to a background server\np = Proxy()\ns = p.Sessions()\n\n# add several tasks to the session using different parameters\ns.add_task(func, 1)\ns.add_task(func, 2)\ns.add_task(func, 3)\ns.add_task(func, 4)\ns.add_task(func, 5)\n\n# kick of the taks and start to listen to the events when tasks start or finish\ns.start()\ns.listen()\n```\n\nYou should be able to see same logs from above example","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompas-dev%2Fcompas_cloud","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcompas-dev%2Fcompas_cloud","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompas-dev%2Fcompas_cloud/lists"}