Development blog 2024-01-04
Rob van Putten
senior specialist flood protection and geotechnics | developer | trainer | innovator
Introduction
I have been working on a web application for levee safety for a couple of years now and I cannot remember the times I started over because I had new ideas or run into trouble with existing ideas. This time the plan is much simpler and I have much more experience with the toolkits that I use so I decided to start a development blog about the leveelogic web application which will be an easy way for levee safety assessments and realtime insight.
What it is...
Leveelogic will be a simple, intuitive web application where you can view and maintain the most important assets for levee safety assessments, your soil information (like CPT's and boreholes), the geometry of the levee and the calculation files you have created. All these assets will be available online and will be presented on a map. There will be logic added to the assets that is already available in my leveelogic python package so it will soon enable things like;
How it is done...
I use Python for all of my code, even for the web application. The base of all functionality is my leveelogic package. All levee assessment knowledge that is useful is put into this package. It uses d-geolib to make calculations using Deltares software D-Stability (stability assessments) and DGeoFlow (piping assessments) which is the leading (free to use) software in The Netherlands for levee assessments. The leveelogic package is put into a repository and every pull to the main branch will automatically create an updated package. Simple as that.
The web application is written using Anvil Works which is a great way to create multipage, complicated web applications. After trying out a lot of different solutions (streamlit, viktor etc) I found this the most flexible and major one. It is also pretty affordable. The only downside is that the server of your web application is shutdown if it is not in use so worst case you will have to deal with a slight delay (approximately 5-8 seconds) at startup. If you switch to a more expensive plan the server will be running constantly and that will be my option as soon as I generate money out of the application.
One of the best things of AnvilWorks is that you can connect your web application code with locally running code so it is possible to make calls from the web application to your own computer or a server that executes the calculations. It's a matter of a line of code like;
ds = anvil.server.call('LL_get_bro_cpts_by_bounds', bottom, top)
and Anvil will look on the local machine or server that you have connected and run that function. This means that you can create your web application on the Anvil server and run all your needed Windows software on your local machine or a rented virtual machine. I have not seen any other solution that offers this option and it is vital for making calculations.
State of the web application
Like I said, I started over and focus on keeping the app as simple as possible. I have implemented the following things;
领英推荐
I am not too happy about the current layout but that's something that is easy to change as soon as I have a more definitive idea about the user interface.
Next up (and some code)
Now this is done I will focus on the following implementation;
The code to generate fragility curves is already available and makes use of multithreaded calculations with d-geolib so the time spent on the calculations will be drastically reduced. The speed depends on the number of cores on the hardware of the local machine / server but it is possible to do as much calculations as you have cores on your machine. This is a code snippet of how I handle this multi threaded approach (which is actually implemented in d-geolib so I can make use of that)
class Runner(BaseModel):
models: List[DStability] = []
def execute(self):
result = []
# create runner
bml = gl.BaseModelList(models=[])
meta = []
for i in range(len(self.models)):
bml.models.append(self.models[i].model)
meta.append(self.models[i].name)
newbm = bml.execute(Path(TEMP_FILES_PATH), nprocesses=len(self.models))
# save output
for i, model in enumerate(newbm.models):
dm = DStability(model=model)
dm._post_process()
dm.name = meta[i]
fos_dict = dm.safety_factor_to_dict()
if fos_dict != {}:
result.append(RunnerResult(model=dm, fos=fos_dict["fos"]))
return result
The hard part will be the translation of a STIX file to an object to store in the Anvil database. This database can deal with a type called SimpleObject which can be declared with the portable_class decorator like this;
@anvil.server.portable_class
class CptInterpretation:
def __init__(self):
self.soillayers = []
If you store an object like this in the database it will be stored as a JSON variable which is pretty convenient. Unfortunately I have not yet found a way to convert the database object to a class so if you know the answer I would be happy to know. For I simply create a classmethod like;
@classmethod
def from_database_dict(cls, d):
cpt_interpretation = CptInterpretation()
for sl in d['soillayers']: cpt_interpretation.soillayers.append(SoilLayer.from_database_dict(sl))
return cpt_interpretation
yeah.. sorry about the way LinkedIn displays code.. but you get the point.. or not!
The reason why it will be hard to convert the stix file to a simple object type is that one stix file can contain multiple stages and scenarios so it will be a crowded object and I have to determine what information to store and what not but hey, live could be boring without these kind of challenges.
See you next time, and enjoy this short video with a demonstration of the current state;