Package: compas-cloud
compas_cloudcompas_cloud is the further development ofcompas.rpcmodule. 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.InstallationInstall from sourcegitclonehttps://github.com/BlockResearchGroup/compas_cloud.git
pipinstall-e.Install for Rhinopython-mcompas_rhino.install-pcompas_cloudUsing ProxyRunning the sever:Start from command line:python-mcompas_cloud.serverThe 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.Basic UsageOne 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:basic.pyfromcompas_cloudimportProxyfromcompas.geometryimportTranslationproxy=Proxy()transform_points_numpy=proxy.function('compas.geometry.transform_points_numpy')# create a proxy funcitonpts=[[0,0,0],[1,0,0]]T=Translation([100,0,0]).matrixtransform_points_numpy(pts,T)# call the function through proxyprint(result)# will print: [[100.0, 0.0 ,0.0], [101.0, 0.0, 0.0]]CachingCompas_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.caching.pyfromcompas_cloudimportProxyfromcompas.geometryimportTranslation# CACHING INPUT PARAMETERSproxy=Proxy()transform_points_numpy=proxy.function('compas.geometry.transform_points_numpy')# create a proxy funcitonpts=[[0,0,0],[1,0,0]]pts_cache=proxy.cache(pts)# cache the object to server side and return its referenceprint(pts_cache)# will print: {'cached': some_unique_id}T=Translation([100,0,0]).matrixresult=transform_points_numpy(pts_cache,T)# call the function through proxyprint(result)# will print: [[100.0, 0.0 ,0.0], [101.0, 0.0, 0.0]]# CACHING RETURNED DATAtransform_points_numpy=proxy.function('compas.geometry.transform_points_numpy',cache=True)# this function will now return a cache object instead of the actual datapts=[[0,0,0],[1,0,0]]pts_cache=proxy.cache(pts)print(pts_cache)# will print: {'cached': some_unique_id}T=Translation([100,0,0]).matrixresult_cache=transform_points_numpy(pts_cache,T)# call the function through proxyprint(result_cache)# will print: {'cached': some_unique_id}result=proxy.get(result_cache)# fetch the actual data of the cache objectprint(result)# will print: [[100.0, 0.0 ,0.0], [101.0, 0.0, 0.0]]Server controlUser canrestart/check/shutdowna connected server from proxy with commands in following example:server_control.pyfromcompas_cloudimportProxyimporttimeprint("\nstarting a new Proxy and by default starts a server in background")proxy=Proxy(background=True)time.sleep(3)print("\nrestarting the background server and open a new one in a prompt console")proxy.background=Falseproxy.restart()time.sleep(3)print("\ncheck if the proxy is healthily connected to server")print(proxy.check())time.sleep(3)print("\nshut the the server and quite the program")proxy.shutdown()time.sleep(3)Other ExamplesAbenchmark testcomparing pure python and numpy with caching to transform 10k points for 100 times:pythonexamples/benchmark.pyIterative plottingexample with callbacks:pythonexamples/dr_numpy.pyUsing non-compas packages like numpy with IronPython:runexamples/example_numpy.pywith RhinoUsing Sessions (Currently only work with MacOS/Linux)Compas_cloud.Sessionsis 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.Sessionscan be run either locally or in a background server throughProxy.ExamplesRunning Sessions Locally:pythonexamples/sessions_local.pyfromcompas_cloudimportSessions# define a psuedo task that will take few seconds to finishdeffunc(a):importtimeforiinrange(a):time.sleep(1)print('sleeped ',i,'s')# initiate a session object, and specify where the logs will be stored and number of workers# if no log_path is given, all logs will be streamed to terminal and not saved# the default worker_num is equal to the number of cpus accessible on the computers=Sessions(log_path=None,worker_num=4)# add several tasks to the session using different parameterss.add_task(func,1)s.add_task(func,2)s.add_task(func,3)s.add_task(func,4)s.add_task(func,5)# kick of the taks and start to listen to the events when tasks start or finishs.start()s.listen()You should see following logs:{'waiting': 5, 'running': 0, 'failed': 0, 'finished': 0, 'total': 5} ________ START
{'waiting': 5, 'running': 0, 'failed': 0, 'finished': 0, 'total': 5} ________ using 4 workers
{'waiting': 5, 'running': 0, 'failed': 0, 'finished': 0, 'total': 5} ________ worker 58884 started
{'waiting': 4, 'running': 1, 'failed': 0, 'finished': 0, 'total': 5} ________ task-0: started
{'waiting': 4, 'running': 1, 'failed': 0, 'finished': 0, 'total': 5} ________ worker 58885 started
{'waiting': 4, 'running': 1, 'failed': 0, 'finished': 0, 'total': 5} ________ task-0: streaming log to temp/task-0.log
{'waiting': 3, 'running': 2, 'failed': 0, 'finished': 0, 'total': 5} ________ task-1: started
...

{'waiting': 0, 'running': 0, 'failed': 0, 'finished': 5, 'total': 5} ________ task-4: finished
{'waiting': 0, 'running': 0, 'failed': 0, 'finished': 5, 'total': 5} ________ worker 58884 terminated
{'waiting': 0, 'running': 0, 'failed': 0, 'finished': 5, 'total': 5} ________ FINISHEDRunning Sessions With Proxy:pythonexamples/sessions_remote.pyfromcompas_cloudimportProxy# define a psuedo task that will take few seconds to finishdeffunc(a):importtimeforiinrange(a):time.sleep(1)print('sleeped ',i,'s')# initiate a Sessions object through Proxy that connects to a background serverp=Proxy()s=p.Sessions()# add several tasks to the session using different parameterss.add_task(func,1)s.add_task(func,2)s.add_task(func,3)s.add_task(func,4)s.add_task(func,5)# kick of the taks and start to listen to the events when tasks start or finishs.start()s.listen()You should be able to see same logs from above example