├── .gitignore ├── DeepLearning ├── Salinity_Demo │ ├── Correlation_Analysis.ipynb │ ├── Data_Preprocessing.ipynb │ ├── Preprocess_NN_Data.ipynb │ ├── README.md │ ├── Test_Model.ipynb │ ├── Train_Model.ipynb │ └── data │ │ ├── Cl_KadIJ_Merge_dt1h.tek │ │ ├── Cl_Lobith_Merge_dt1h.lss │ │ ├── Q_Lobith_Merge_dt1h.lss │ │ ├── h_HvH_Merge_dt1h.tek │ │ └── shuffle ├── Zout_test.ipynb ├── deep_learning_example.ipynb └── deep_learning_salinity.ipynb ├── EarthObservationWebServices.ipynb ├── EarthObservationWebServices.pptx ├── LICENSE ├── README.md ├── aerial_photographs.ipynb ├── ahn2.ipynb ├── alcatraz_similar.ipynb ├── amelandflowmap.ipynb ├── analysis-brouwershavensegat.ipynb ├── catalog-check.ipynb ├── curvilinear_grid_fill.ipynb ├── date and times.ipynb ├── dcsmflowmap.ipynb ├── delft3d bmi vrui.ipynb ├── delft3d io river.ipynb ├── delft3d io sea.ipynb ├── distribution-example.ipynb ├── dredge-vs-slr.ipynb ├── extract_grid.py ├── flow_around_cylinder.ipynb ├── geometries.ipynb ├── geotop.ipynb ├── gridenclosure.ipynb ├── kockengen.ipynb ├── lisflood_interactive.ipynb ├── matlab ├── EarthObservationWebServices.html ├── EarthObservationWebServices.m ├── EarthObservationWebServices.png ├── EarthObservationWebServices_01.png ├── EarthObservationWebServices_02.png └── EarthObservationWebServices_03.png ├── maximum_waterlevels_in_west_terschelling.ipynb ├── mayavi.ipynb ├── mercatormovie.ipynb ├── milling-machine.ipynb ├── modelaveraging.ipynb ├── netcdf_fortran.ipynb ├── netcdf_grid_read.ipynb ├── ogr 31370.ipynb ├── processing_lidar.ipynb ├── processing_lidar_lastools.ipynb ├── rivercurrents.ipynb ├── sandengine_landsat.ipynb ├── sealevelmonitor.ipynb ├── sentinel1-delineation.ipynb ├── streamline-demo.ipynb ├── superpixel.ipynb ├── tidalstuff.ipynb ├── time and timezones.ipynb ├── twitter.ipynb ├── unstrucgridplot.ipynb ├── viewshed-cost.ipynb ├── visualizing_point_cloud_mayavi.ipynb ├── waddenflowmap.ipynb └── wpsclient.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | *[0-9]*.png 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | bin/ 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # Installer logs 27 | pip-log.txt 28 | pip-delete-this-directory.txt 29 | 30 | # Unit test / coverage reports 31 | htmlcov/ 32 | .tox/ 33 | .coverage 34 | .cache 35 | nosetests.xml 36 | coverage.xml 37 | 38 | # Translations 39 | *.mo 40 | 41 | # Mr Developer 42 | .mr.developer.cfg 43 | .project 44 | .pydevproject 45 | 46 | # Rope 47 | .ropeproject 48 | 49 | # Django stuff: 50 | *.log 51 | *.pot 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | .ipynb_checkpoints/ 57 | file.kml 58 | notebook.bat 59 | -------------------------------------------------------------------------------- /DeepLearning/Salinity_Demo/README.md: -------------------------------------------------------------------------------- 1 | ## Files explanation 2 | This demo contains five notebooks which together can be used to train and test a neural network on the provided salinity data: 3 | * Data_Preprocessing: used to get the relevant data from the original files and merge it into a single dataset which is then written to a csv files 4 | * Correlation_Analysis: used to analyse the correlation between the input parameters (the salinity and discharge in Lobith and water level at Hoek van Holland) and the output parameter (the salinity in Capelle aan de IJssel) 5 | * Preprocess_NN_Data: used to take the raw data and convert it to input ready to be put into the neural network, this notebook randomly divides the resulting batches among train, test and validation data. 6 | * Train_Model: trains a model on the training data provided 7 | * Test_Model: tests a trained model on the test data provided 8 | 9 | The first three notebooks should be run in the order they are listed to generate a database on which models can be trained and tested. In order to run the Preprocess_NN_Data notebook there needs to be three folder 'train', 'test', and 'validate' in the 'data' folder. The notebook will use the 'data/shuffle' file to divide the batches among train, test and validation data. Note that if any change is made to this file, the batches will be ordered differently and using a previously trained model in the Test_Model notebook could then result in mixing the test and training data for a model. Similarly, if the data preprocessing scripts are changed the resulting data will of course also differ from those used by previously trained models. 10 | 11 | The model created in the Train_Model notebook can be adapted each time a new NN is desired, don't forget to change the output filename in the last cell to make sure the newly trained model is saved in a different file (the notebook will test whether the provided filename exists and refuse to write the model to file if it does). This saved model can then be read by the Test_Model notebook. 12 | 13 | In addition to the notebooks there should already be a folder 'data' present containing the following files: 14 | * Cl_KadIJ_Merge_dt1h.tek 15 | * Cl_Lobith_Merge_dt1h.lss 16 | * Q_Lobith_Merge_dt1h.lss 17 | * h_HvH_Merge_dt1h.tek 18 | * shuffle 19 | -------------------------------------------------------------------------------- /DeepLearning/Salinity_Demo/Train_Model.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stderr", 10 | "output_type": "stream", 11 | "text": [ 12 | "Using TensorFlow backend.\n" 13 | ] 14 | } 15 | ], 16 | "source": [ 17 | "import keras\n", 18 | "import matplotlib.pyplot as plt\n", 19 | "import numpy as np\n", 20 | "import pandas as pd\n", 21 | "%matplotlib inline" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 2, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "# read the train batches from files created by the Preprocessing_NN_Data notebook\n", 31 | "def read_batches(filepath, include_cl_kadij_input=True):\n", 32 | " batches = []\n", 33 | " number_read = -1\n", 34 | " while True:\n", 35 | " number_read += 1\n", 36 | " try:\n", 37 | " batch = pd.read_csv(filepath + '_' + str(number_read) + '.csv', index_col=0, parse_dates=True)\n", 38 | " if not include_cl_kadij_input:\n", 39 | " batch = batch.drop('cl_kadij_1', 1)\n", 40 | " batches.append(batch)\n", 41 | " except FileNotFoundError:\n", 42 | " break\n", 43 | " \n", 44 | " return batches\n", 45 | "\n", 46 | "include_cl_kadij_input = False #used to toggle whether cl_kadij_1 (yesterday's value) is included in input\n", 47 | "train_batches = read_batches('data/train/batch', include_cl_kadij_input) " 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 3, 53 | "metadata": {}, 54 | "outputs": [ 55 | { 56 | "data": { 57 | "text/html": [ 58 | "
\n", 59 | "\n", 72 | "\n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | "
cl_kadij_outcl_lobith_3cl_lobith_4cl_lobith_5cl_lobith_6afv_lobith_6afv_lobith_7afv_lobith_8afv_lobith_9cum_stand_1cum_stand_2
1987-11-21 21:00:000.4713890.6005410.6174820.6769920.7308880.2038890.1766970.1568190.1466250.7540010.491503
1987-11-22 21:00:000.4076750.6341600.6005410.6174820.6769920.2387790.2038890.1766970.1568190.6050160.754001
1987-11-23 21:00:000.3799310.6259950.6341600.6005410.6174820.2744230.2387790.2038890.1766970.5408350.605016
1987-11-24 21:00:000.3707290.5657580.6259950.6341600.6005410.2925540.2744230.2387790.2038890.5018970.540835
1987-11-25 21:00:000.3455030.4454610.5657580.6259950.6341600.3060190.2925540.2744230.2387790.3870650.501897
\n", 162 | "
" 163 | ], 164 | "text/plain": [ 165 | " cl_kadij_out cl_lobith_3 cl_lobith_4 cl_lobith_5 \\\n", 166 | "1987-11-21 21:00:00 0.471389 0.600541 0.617482 0.676992 \n", 167 | "1987-11-22 21:00:00 0.407675 0.634160 0.600541 0.617482 \n", 168 | "1987-11-23 21:00:00 0.379931 0.625995 0.634160 0.600541 \n", 169 | "1987-11-24 21:00:00 0.370729 0.565758 0.625995 0.634160 \n", 170 | "1987-11-25 21:00:00 0.345503 0.445461 0.565758 0.625995 \n", 171 | "\n", 172 | " cl_lobith_6 afv_lobith_6 afv_lobith_7 afv_lobith_8 \\\n", 173 | "1987-11-21 21:00:00 0.730888 0.203889 0.176697 0.156819 \n", 174 | "1987-11-22 21:00:00 0.676992 0.238779 0.203889 0.176697 \n", 175 | "1987-11-23 21:00:00 0.617482 0.274423 0.238779 0.203889 \n", 176 | "1987-11-24 21:00:00 0.600541 0.292554 0.274423 0.238779 \n", 177 | "1987-11-25 21:00:00 0.634160 0.306019 0.292554 0.274423 \n", 178 | "\n", 179 | " afv_lobith_9 cum_stand_1 cum_stand_2 \n", 180 | "1987-11-21 21:00:00 0.146625 0.754001 0.491503 \n", 181 | "1987-11-22 21:00:00 0.156819 0.605016 0.754001 \n", 182 | "1987-11-23 21:00:00 0.176697 0.540835 0.605016 \n", 183 | "1987-11-24 21:00:00 0.203889 0.501897 0.540835 \n", 184 | "1987-11-25 21:00:00 0.238779 0.387065 0.501897 " 185 | ] 186 | }, 187 | "execution_count": 3, 188 | "metadata": {}, 189 | "output_type": "execute_result" 190 | } 191 | ], 192 | "source": [ 193 | "#print an example batch to see what they look like\n", 194 | "batch = train_batches[0]\n", 195 | "batch.head()" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 4, 201 | "metadata": { 202 | "collapsed": true 203 | }, 204 | "outputs": [], 205 | "source": [ 206 | "# convert the dataframes in train_batches to the correct input and output shape (and make it arrays)\n", 207 | "def convert_to_keras_input(batches):\n", 208 | " input_batches = []\n", 209 | " output_batches = []\n", 210 | " for batch in batches:\n", 211 | " input_df = batch.iloc[:,1:]\n", 212 | " output_df = batch['cl_kadij_out']\n", 213 | " input_batches.append(input_df.as_matrix()[:,np.newaxis,:])\n", 214 | " output_batches.append(output_df.as_matrix())\n", 215 | " return (input_batches, output_batches)\n", 216 | "\n", 217 | "(input_train_batches, output_train_batches) = convert_to_keras_input(train_batches)" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 5, 223 | "metadata": {}, 224 | "outputs": [ 225 | { 226 | "name": "stdout", 227 | "output_type": "stream", 228 | "text": [ 229 | "_________________________________________________________________\n", 230 | "Layer (type) Output Shape Param # \n", 231 | "=================================================================\n", 232 | "lstm_1 (LSTM) (None, 1, 4) 240 \n", 233 | "_________________________________________________________________\n", 234 | "lstm_2 (LSTM) (None, 4) 144 \n", 235 | "_________________________________________________________________\n", 236 | "dense_1 (Dense) (None, 1) 5 \n", 237 | "=================================================================\n", 238 | "Total params: 389\n", 239 | "Trainable params: 389\n", 240 | "Non-trainable params: 0\n", 241 | "_________________________________________________________________\n" 242 | ] 243 | } 244 | ], 245 | "source": [ 246 | "# create a Keras model of the NN\n", 247 | "n_cells = 4\n", 248 | "input_shape = input_train_batches[0].shape[1:]\n", 249 | "\n", 250 | "model = keras.models.Sequential()\n", 251 | "model.add(keras.layers.LSTM(n_cells, input_shape=input_shape, return_sequences=True))\n", 252 | "model.add(keras.layers.LSTM(n_cells))\n", 253 | "model.add(keras.layers.Dense(1))\n", 254 | "model.compile(loss='mean_squared_error', optimizer='adam')\n", 255 | "\n", 256 | "model.summary()" 257 | ] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": 6, 262 | "metadata": {}, 263 | "outputs": [ 264 | { 265 | "name": "stdout", 266 | "output_type": "stream", 267 | "text": [ 268 | "At epoch 0\n", 269 | "Epoch 1/1\n", 270 | "1s - loss: 0.1580\n", 271 | "At epoch 25\n", 272 | "Epoch 1/1\n", 273 | "0s - loss: 9.2738e-04\n", 274 | "At epoch 50\n", 275 | "Epoch 1/1\n", 276 | "0s - loss: 9.1536e-04\n", 277 | "At epoch 75\n", 278 | "Epoch 1/1\n", 279 | "0s - loss: 8.7842e-04\n", 280 | "At epoch 100\n", 281 | "Epoch 1/1\n", 282 | "0s - loss: 8.4336e-04\n", 283 | "At epoch 125\n", 284 | "Epoch 1/1\n", 285 | "0s - loss: 8.3015e-04\n", 286 | "At epoch 150\n", 287 | "Epoch 1/1\n", 288 | "0s - loss: 8.5183e-04\n", 289 | "At epoch 175\n", 290 | "Epoch 1/1\n", 291 | "0s - loss: 8.5729e-04\n", 292 | "At epoch 200\n", 293 | "Epoch 1/1\n", 294 | "0s - loss: 8.5354e-04\n", 295 | "At epoch 225\n", 296 | "Epoch 1/1\n", 297 | "0s - loss: 8.4674e-04\n", 298 | "At epoch 250\n", 299 | "Epoch 1/1\n", 300 | "0s - loss: 8.4350e-04\n", 301 | "At epoch 275\n", 302 | "Epoch 1/1\n", 303 | "0s - loss: 8.3171e-04\n", 304 | "At epoch 300\n", 305 | "Epoch 1/1\n", 306 | "0s - loss: 8.3943e-04\n", 307 | "At epoch 325\n", 308 | "Epoch 1/1\n", 309 | "0s - loss: 8.0809e-04\n", 310 | "At epoch 350\n", 311 | "Epoch 1/1\n", 312 | "0s - loss: 7.8491e-04\n", 313 | "At epoch 375\n", 314 | "Epoch 1/1\n", 315 | "0s - loss: 7.9298e-04\n", 316 | "At epoch 400\n", 317 | "Epoch 1/1\n", 318 | "0s - loss: 7.9735e-04\n", 319 | "At epoch 425\n", 320 | "Epoch 1/1\n", 321 | "0s - loss: 7.9130e-04\n", 322 | "At epoch 450\n", 323 | "Epoch 1/1\n", 324 | "0s - loss: 7.9296e-04\n", 325 | "At epoch 475\n", 326 | "Epoch 1/1\n", 327 | "0s - loss: 7.9487e-04\n", 328 | "At epoch 500\n", 329 | "Epoch 1/1\n", 330 | "0s - loss: 7.8669e-04\n", 331 | "At epoch 525\n", 332 | "Epoch 1/1\n", 333 | "0s - loss: 7.8290e-04\n", 334 | "At epoch 550\n", 335 | "Epoch 1/1\n", 336 | "0s - loss: 7.7617e-04\n", 337 | "At epoch 575\n", 338 | "Epoch 1/1\n", 339 | "0s - loss: 7.7052e-04\n", 340 | "At epoch 600\n", 341 | "Epoch 1/1\n", 342 | "0s - loss: 7.5806e-04\n", 343 | "At epoch 625\n", 344 | "Epoch 1/1\n", 345 | "0s - loss: 7.4854e-04\n", 346 | "At epoch 650\n", 347 | "Epoch 1/1\n", 348 | "0s - loss: 7.4485e-04\n", 349 | "At epoch 675\n", 350 | "Epoch 1/1\n", 351 | "0s - loss: 7.3673e-04\n", 352 | "At epoch 700\n", 353 | "Epoch 1/1\n", 354 | "0s - loss: 7.3419e-04\n", 355 | "At epoch 725\n", 356 | "Epoch 1/1\n", 357 | "0s - loss: 7.2986e-04\n", 358 | "At epoch 750\n", 359 | "Epoch 1/1\n", 360 | "0s - loss: 7.2416e-04\n", 361 | "At epoch 775\n", 362 | "Epoch 1/1\n", 363 | "0s - loss: 7.2258e-04\n", 364 | "At epoch 800\n", 365 | "Epoch 1/1\n", 366 | "0s - loss: 7.2318e-04\n", 367 | "At epoch 825\n", 368 | "Epoch 1/1\n", 369 | "0s - loss: 7.1825e-04\n", 370 | "At epoch 850\n", 371 | "Epoch 1/1\n", 372 | "0s - loss: 7.1810e-04\n", 373 | "At epoch 875\n", 374 | "Epoch 1/1\n", 375 | "0s - loss: 7.1601e-04\n", 376 | "At epoch 900\n", 377 | "Epoch 1/1\n", 378 | "0s - loss: 7.1230e-04\n", 379 | "At epoch 925\n", 380 | "Epoch 1/1\n", 381 | "0s - loss: 7.1012e-04\n", 382 | "At epoch 950\n", 383 | "Epoch 1/1\n", 384 | "0s - loss: 7.1202e-04\n", 385 | "At epoch 975\n", 386 | "Epoch 1/1\n", 387 | "0s - loss: 7.1357e-04\n", 388 | "Wall time: 2h 18min 42s\n" 389 | ] 390 | } 391 | ], 392 | "source": [ 393 | "%%time\n", 394 | "# train the model (this will take hours!)\n", 395 | "\n", 396 | "n_epochs = 1000\n", 397 | "report_at = 25\n", 398 | "for i in range(0, n_epochs):\n", 399 | " first_batch = 0\n", 400 | " if i % report_at == 0:\n", 401 | " print('At epoch', i)\n", 402 | " model.fit(input_train_batches[0], output_train_batches[0], epochs=1, batch_size=len(output_train_batches[0]), verbose=2)\n", 403 | " first_batch = 1\n", 404 | " for j in range(first_batch,len(input_train_batches)):\n", 405 | " model.fit(input_train_batches[j], output_train_batches[j], epochs=1, batch_size=len(output_train_batches[j]), verbose=0)" 406 | ] 407 | }, 408 | { 409 | "cell_type": "code", 410 | "execution_count": 7, 411 | "metadata": {}, 412 | "outputs": [], 413 | "source": [ 414 | "# write the model to a file, don't forget to change the output filename otherwise it won't write!\n", 415 | "output_filename = 'models/2layer_lstm_4cells_noKadij'\n", 416 | "\n", 417 | "from pathlib import Path\n", 418 | "output_file = Path(output_filename + '.h5')\n", 419 | "if output_file.is_file():\n", 420 | " print('Please choose a different filename, this one already exists!')\n", 421 | "else:\n", 422 | " model.save(output_filename + '.h5')\n", 423 | " info_file = open(output_filename + '_info.txt', 'w')\n", 424 | " info_file.write('number of epochs: ' + str(n_epochs) + '\\n')\n", 425 | " info_file.write('number of cells per layer: ' + str(n_cells) + '\\n')\n", 426 | " info_file.write('including cl_kadij in input:' + str(include_cl_kadij_input) + '\\n\\n')\n", 427 | " model.summary(print_fn=lambda x: info_file.write(x + '\\n'))\n", 428 | " info_file.close()" 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": null, 434 | "metadata": { 435 | "collapsed": true 436 | }, 437 | "outputs": [], 438 | "source": [] 439 | } 440 | ], 441 | "metadata": { 442 | "kernelspec": { 443 | "display_name": "Python 3", 444 | "language": "python", 445 | "name": "python3" 446 | }, 447 | "language_info": { 448 | "codemirror_mode": { 449 | "name": "ipython", 450 | "version": 3 451 | }, 452 | "file_extension": ".py", 453 | "mimetype": "text/x-python", 454 | "name": "python", 455 | "nbconvert_exporter": "python", 456 | "pygments_lexer": "ipython3", 457 | "version": "3.5.4" 458 | }, 459 | "widgets": { 460 | "state": {}, 461 | "version": "1.1.2" 462 | } 463 | }, 464 | "nbformat": 4, 465 | "nbformat_minor": 2 466 | } 467 | -------------------------------------------------------------------------------- /DeepLearning/Salinity_Demo/data/Cl_KadIJ_Merge_dt1h.tek: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openearth/notebooks/1786d5162aa0a0a8c2f5bd880328d92f0efeaf1b/DeepLearning/Salinity_Demo/data/Cl_KadIJ_Merge_dt1h.tek -------------------------------------------------------------------------------- /DeepLearning/Salinity_Demo/data/Cl_Lobith_Merge_dt1h.lss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openearth/notebooks/1786d5162aa0a0a8c2f5bd880328d92f0efeaf1b/DeepLearning/Salinity_Demo/data/Cl_Lobith_Merge_dt1h.lss -------------------------------------------------------------------------------- /DeepLearning/Salinity_Demo/data/Q_Lobith_Merge_dt1h.lss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openearth/notebooks/1786d5162aa0a0a8c2f5bd880328d92f0efeaf1b/DeepLearning/Salinity_Demo/data/Q_Lobith_Merge_dt1h.lss -------------------------------------------------------------------------------- /DeepLearning/Salinity_Demo/data/h_HvH_Merge_dt1h.tek: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openearth/notebooks/1786d5162aa0a0a8c2f5bd880328d92f0efeaf1b/DeepLearning/Salinity_Demo/data/h_HvH_Merge_dt1h.tek -------------------------------------------------------------------------------- /EarthObservationWebServices.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openearth/notebooks/1786d5162aa0a0a8c2f5bd880328d92f0efeaf1b/EarthObservationWebServices.pptx -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | notebooks 2 | ========= 3 | 4 | A collection of python notebooks 5 | -------------------------------------------------------------------------------- /catalog-check.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Check an opendap catalog" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import pathlib\n", 17 | "import xml.etree.ElementTree\n", 18 | "import lxml.etree\n", 19 | "import datetime\n", 20 | "import requests\n", 21 | "import tqdm\n" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 2, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "catalog = pathlib.Path('/Users/baart_f/src/thredds-docker/catalogList.xml')" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 3, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "tree = lxml.etree.parse(str(catalog))" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 6, 45 | "metadata": {}, 46 | "outputs": [ 47 | { 48 | "name": "stdout", 49 | "output_type": "stream", 50 | "text": [ 51 | "81\n" 52 | ] 53 | } 54 | ], 55 | "source": [ 56 | "refs = tree.findall('.//{http://www.unidata.ucar.edu/namespaces/thredds/InvCatalog/v1.0}catalogRef')\n", 57 | "print(len(refs))" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 7, 63 | "metadata": {}, 64 | "outputs": [ 65 | { 66 | "data": { 67 | "application/vnd.jupyter.widget-view+json": { 68 | "model_id": "41779241b519456f887d4da38c370ab7", 69 | "version_major": 2, 70 | "version_minor": 0 71 | }, 72 | "text/plain": [ 73 | "HBox(children=(IntProgress(value=0, max=81), HTML(value='')))" 74 | ] 75 | }, 76 | "metadata": {}, 77 | "output_type": "display_data" 78 | }, 79 | { 80 | "name": "stdout", 81 | "output_type": "stream", 82 | "text": [ 83 | "\n" 84 | ] 85 | } 86 | ], 87 | "source": [ 88 | "for i, ref in enumerate(tqdm.tqdm_notebook(refs)):\n", 89 | " url = ref.attrib['{http://www.w3.org/1999/xlink}href'] \n", 90 | " msg = ''\n", 91 | " parent = ref.getparent()\n", 92 | " \n", 93 | " try:\n", 94 | " resp = requests.get(url, timeout=5)\n", 95 | " if resp.status_code != 200:\n", 96 | " msg = \"result not ok (status %s)\" % (resp.status_code, ) \n", 97 | " except requests.exceptions.Timeout as e: \n", 98 | " msg = \"result not ok (timeout)\"\n", 99 | " except requests.exceptions.ConnectionError as e:\n", 100 | " msg = \"result not ok (connection error)\"\n", 101 | " \n", 102 | " if (msg):\n", 103 | " comment = lxml.etree.Comment(\n", 104 | " 'Url checked: not ok: %s (%s)' % (msg, datetime.datetime.now(), )\n", 105 | " )\n", 106 | " ref.addprevious(comment)\n", 107 | " ref_string = lxml.etree.tostring(ref)\n", 108 | " comment = lxml.etree.Comment(ref_string) \n", 109 | " # replace by comment\n", 110 | " parent.replace(ref, comment)\n", 111 | " else:\n", 112 | " comment = lxml.etree.Comment('Url checked: ok (%s)' % (datetime.datetime.now(), ))\n", 113 | " ref.addprevious(comment)\n" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 8, 119 | "metadata": {}, 120 | "outputs": [], 121 | "source": [ 122 | "tree.write('catalog.xml', xml_declaration=True, pretty_print=True, encoding='UTF-8')" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 9, 128 | "metadata": {}, 129 | "outputs": [], 130 | "source": [ 131 | "!open .\n" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 14, 137 | "metadata": {}, 138 | "outputs": [ 139 | { 140 | "data": { 141 | "text/plain": [ 142 | "" 143 | ] 144 | }, 145 | "execution_count": 14, 146 | "metadata": {}, 147 | "output_type": "execute_result" 148 | } 149 | ], 150 | "source": [ 151 | "tree" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": null, 157 | "metadata": {}, 158 | "outputs": [], 159 | "source": [] 160 | } 161 | ], 162 | "metadata": { 163 | "kernelspec": { 164 | "display_name": "Python 3", 165 | "language": "python", 166 | "name": "python3" 167 | }, 168 | "language_info": { 169 | "codemirror_mode": { 170 | "name": "ipython", 171 | "version": 3 172 | }, 173 | "file_extension": ".py", 174 | "mimetype": "text/x-python", 175 | "name": "python", 176 | "nbconvert_exporter": "python", 177 | "pygments_lexer": "ipython3", 178 | "version": "3.6.8" 179 | } 180 | }, 181 | "nbformat": 4, 182 | "nbformat_minor": 2 183 | } 184 | -------------------------------------------------------------------------------- /delft3d io sea.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "webinar_delft3d" 4 | }, 5 | "nbformat": 3, 6 | "nbformat_minor": 0, 7 | "worksheets": [ 8 | { 9 | "cells": [ 10 | { 11 | "cell_type": "code", 12 | "collapsed": false, 13 | "input": [ 14 | "cd C:\\Users\\boer_g\\Desktop\\Webinar\\OEM" 15 | ], 16 | "language": "python", 17 | "metadata": {}, 18 | "outputs": [ 19 | { 20 | "output_type": "stream", 21 | "stream": "stdout", 22 | "text": [ 23 | "C:\\Users\\boer_g\\Desktop\\Webinar\\OEM\n" 24 | ] 25 | } 26 | ], 27 | "prompt_number": 4 28 | }, 29 | { 30 | "cell_type": "code", 31 | "collapsed": false, 32 | "input": [ 33 | "import openearthtools.io.delft3d as d3d\n", 34 | "dir(d3d)" 35 | ], 36 | "language": "python", 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "output_type": "pyout", 41 | "prompt_number": 5, 42 | "text": [ 43 | "['Grid',\n", 44 | " '__builtins__',\n", 45 | " '__doc__',\n", 46 | " '__file__',\n", 47 | " '__name__',\n", 48 | " '__package__',\n", 49 | " '__path__',\n", 50 | " 'grid',\n", 51 | " 'mdf',\n", 52 | " 'read',\n", 53 | " 'tekal',\n", 54 | " 'tekalblock',\n", 55 | " 'write']" 56 | ] 57 | } 58 | ], 59 | "prompt_number": 5 60 | }, 61 | { 62 | "cell_type": "code", 63 | "collapsed": false, 64 | "input": [ 65 | "help(d3d.Grid)\n", 66 | "# example from https://svn.oss.deltares.nl/repos/openearthmodels/trunk/deltares/brazil_patos_lagoon_52S_32E/\n", 67 | "G = d3d.Grid.fromfile('lake_and_sea_5_ll.grd')" 68 | ], 69 | "language": "python", 70 | "metadata": {}, 71 | "outputs": [ 72 | { 73 | "output_type": "stream", 74 | "stream": "stdout", 75 | "text": [ 76 | "Help on class Grid in module openearthtools.io.delft3d.grid:\n", 77 | "\n", 78 | "class Grid(__builtin__.object)\n", 79 | " | Create a Delft3D grid file\n", 80 | " | # Create an empty grid\n", 81 | " | grid = Grid()\n", 82 | " | # Load a grid from file\n", 83 | " | grid = Grid.read('filename.grd')\n", 84 | " | # Write grid to file\n", 85 | " | Grid.read(grid,'filename.grd')\n", 86 | " | \n", 87 | " | Methods defined here:\n", 88 | " | \n", 89 | " | __init__(self, *args, **kwargs)\n", 90 | " | \n", 91 | " | write(self, filename, **kwargs)\n", 92 | " | \n", 93 | " | ----------------------------------------------------------------------\n", 94 | " | Static methods defined here:\n", 95 | " | \n", 96 | " | fromfile(filename, **kwargs)\n", 97 | " | \n", 98 | " | ----------------------------------------------------------------------\n", 99 | " | Data descriptors defined here:\n", 100 | " | \n", 101 | " | __dict__\n", 102 | " | dictionary for instance variables (if defined)\n", 103 | " | \n", 104 | " | __weakref__\n", 105 | " | list of weak references to the object (if defined)\n", 106 | "\n" 107 | ] 108 | } 109 | ], 110 | "prompt_number": 11 111 | }, 112 | { 113 | "cell_type": "code", 114 | "collapsed": false, 115 | "input": [ 116 | "# curvilinear grids typically have many invalid matrix positions\n", 117 | "# to represent islands, thick dams or cul-de-sacs (estuaries/rivers) \n", 118 | "# therefore the matrices are stored as Masked array type\n", 119 | "G.X" 120 | ], 121 | "language": "python", 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "output_type": "pyout", 126 | "prompt_number": 7, 127 | "text": [ 128 | "masked_array(data =\n", 129 | " [[-- -- -- ..., -51.21892397029205 -51.25650464051964 -51.28911971484214]\n", 130 | " [-- -- -- ..., -51.25256180611927 -51.274277884869164 -51.29888408312184]\n", 131 | " [-- -- -- ..., -51.26523724097448 -51.288310621047295 -51.31035946306346]\n", 132 | " ..., \n", 133 | " [-51.92346119182868 -51.94226259182987 -51.96086078342037 ..., -- -- --]\n", 134 | " [-51.92608902265055 -51.94527933494353 -51.96403316815339 ..., -- -- --]\n", 135 | " [-51.928765963284064 -51.948398147668485 -51.967149196828366 ..., -- -- --]],\n", 136 | " mask =\n", 137 | " [[ True True True ..., False False False]\n", 138 | " [ True True True ..., False False False]\n", 139 | " [ True True True ..., False False False]\n", 140 | " ..., \n", 141 | " [False False False ..., True True True]\n", 142 | " [False False False ..., True True True]\n", 143 | " [False False False ..., True True True]],\n", 144 | " fill_value = 1e+20)\n" 145 | ] 146 | } 147 | ], 148 | "prompt_number": 7 149 | }, 150 | { 151 | "cell_type": "code", 152 | "collapsed": false, 153 | "input": [ 154 | "G.dep = G.z" 155 | ], 156 | "language": "python", 157 | "metadata": {}, 158 | "outputs": [] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "collapsed": false, 163 | "input": [ 164 | "matplotlib.pyplot.pcolor(G.X,G.Y,G.dep)\n", 165 | "gca().set_aspect(1./cos(mean(ylim())/180*pi),adjustable='box') # see Matlab axislat()" 166 | ], 167 | "language": "python", 168 | "metadata": {}, 169 | "outputs": [ 170 | { 171 | "output_type": "display_data", 172 | "png": "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\n" 173 | } 174 | ], 175 | "prompt_number": 9 176 | }, 177 | { 178 | "cell_type": "code", 179 | "collapsed": false, 180 | "input": [], 181 | "language": "python", 182 | "metadata": {}, 183 | "outputs": [] 184 | } 185 | ], 186 | "metadata": {} 187 | } 188 | ] 189 | } -------------------------------------------------------------------------------- /dredge-vs-slr.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Can we dredge away the sea-level rise\n", 8 | "This is a back-of-the-envelope calculation based on a question I got. The question was: Can we dredge the ocean to componsate for sea-level rise? Here we try to answer this question. We'll answer the question in the following steps\n", 9 | "\n", 10 | "- Sea-level rise -> volume of water\n", 11 | "- Volume sea-level -> to volume of sand\n", 12 | "- Volume of sand -> cost\n", 13 | "- Cost -> cost per year\n", 14 | "- Cost per year -> % per GDP\n", 15 | "\n", 16 | "To answer the question we need to make some assumptions. Let's start with those. But before we do, we need to import some libraries. " 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "# library for working with units\n", 26 | "import pint\n", 27 | "\n", 28 | "# load some default units\n", 29 | "ureg = pint.UnitRegistry()\n", 30 | "\n", 31 | "ureg.define('EUR = [currency]')\n", 32 | "ureg.define('USD = 0.88 * EUR')" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "# how big is the earth's ocean surface (src: http://www.physicalgeography.net/fundamentals/8o.html)\n", 42 | "earth_ocean_surface = 361132000 * ureg.kilometer**2\n", 43 | "earth_land_surface = 148940000 * ureg.kilometer**2\n", 44 | "# how much sea level do want to compensate (src: just a number, somewhere in the order of SSP5-8.5)\n", 45 | "sea_level_rise = 1 * ureg.meter / ureg.century\n", 46 | "# rough estimate how much it costs to dredge 1m3. If you dredge more it will be cheaper\n", 47 | "cost_to_dredge = 3 * ureg.EUR / ureg.meter**3\n", 48 | "\n", 49 | "# global gross domestic product: https://www.statista.com/statistics/268750/global-gross-domestic-product-gdp/\n", 50 | "global_gdp = 93863.85 * 1000000000 * ureg.USD / ureg.year\n", 51 | "\n", 52 | "# just a random source: https://blog.ucsusa.org/guest-commentary/what-is-the-cost-of-one-meter-of-sea-level-rise/ \n", 53 | "# of the cost to do nothing\n", 54 | "cost_of_consequences = 1000000000000 * ureg.USD / ureg.year\n" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "## Sea level to volume\n", 62 | "The first step is to go from sea-level rise to volume. " 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 3, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "sea_level_volume = (sea_level_rise * earth_ocean_surface)\n" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 4, 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "data": { 81 | "text/html": [ 82 | "\\[361132.0\\ kilometer^3/century\\]" 83 | ], 84 | "text/latex": [ 85 | "$361132.0\\ \\frac{\\mathrm{kilometer}^{3}}{\\mathrm{century}}$" 86 | ], 87 | "text/plain": [ 88 | "361132.0 " 89 | ] 90 | }, 91 | "execution_count": 4, 92 | "metadata": {}, 93 | "output_type": "execute_result" 94 | } 95 | ], 96 | "source": [ 97 | "sea_level_volume.to_reduced_units()" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "## Volume of sand\n", 105 | "The second step is to compute the volume of sand that we need to remove. We can remove the same ammount of wet sand below sea-level to lower the sea level. But we can also use this sand to raise the land. So for each meter of sand you can raise (ocean area / land area, which also reduces sea level). So we only have to do 40% of the work. You can even assume that you will only raise the areas where earth is below 1m sea-level. Then you need even less. This is referred to as relative sea-level rise. " 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 5, 111 | "metadata": {}, 112 | "outputs": [ 113 | { 114 | "data": { 115 | "text/html": [ 116 | "\\[148940.0\\ kilometer^3/century\\]" 117 | ], 118 | "text/latex": [ 119 | "$148940.0\\ \\frac{\\mathrm{kilometer}^{3}}{\\mathrm{century}}$" 120 | ], 121 | "text/plain": [ 122 | "148940.0 " 123 | ] 124 | }, 125 | "execution_count": 5, 126 | "metadata": {}, 127 | "output_type": "execute_result" 128 | } 129 | ], 130 | "source": [ 131 | "sand_volume = sea_level_volume * (earth_land_surface / earth_ocean_surface)\n", 132 | "sand_volume.to_reduced_units()\n" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "## Volume of sand to cost\n", 140 | "Dredging up this amount of sand costs money. Let's multiply it with the cost to dredge sand. And dump it near the shore. " 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 6, 146 | "metadata": {}, 147 | "outputs": [ 148 | { 149 | "data": { 150 | "text/html": [ 151 | "\\[446820000000000.0\\ EUR/century\\]" 152 | ], 153 | "text/latex": [ 154 | "$446820000000000.0\\ \\frac{\\mathrm{EUR}}{\\mathrm{century}}$" 155 | ], 156 | "text/plain": [ 157 | "446820000000000.0 " 158 | ] 159 | }, 160 | "execution_count": 6, 161 | "metadata": {}, 162 | "output_type": "execute_result" 163 | } 164 | ], 165 | "source": [ 166 | "cost = sand_volume * cost_to_dredge\n", 167 | "cost.to_reduced_units()" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "## Cost per century to cost per year\n", 175 | "We want to know the costs per year so that we can compare it with our annual income. \n" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 7, 181 | "metadata": {}, 182 | "outputs": [ 183 | { 184 | "data": { 185 | "text/html": [ 186 | "\\[4468200000000.0\\ EUR/year\\]" 187 | ], 188 | "text/latex": [ 189 | "$4468200000000.0\\ \\frac{\\mathrm{EUR}}{\\mathrm{year}}$" 190 | ], 191 | "text/plain": [ 192 | "4468200000000.0 " 193 | ] 194 | }, 195 | "execution_count": 7, 196 | "metadata": {}, 197 | "output_type": "execute_result" 198 | } 199 | ], 200 | "source": [ 201 | "cost.to(ureg.EUR / ureg.year)" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "## Cost relative to GDP\n", 209 | "We can compare this cost to how much we (as the world) make each here. Of course this assumes that all countries will chip in, which might be optimistic. " 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": 8, 215 | "metadata": {}, 216 | "outputs": [ 217 | { 218 | "name": "stdout", 219 | "output_type": "stream", 220 | "text": [ 221 | "The cost to dredge the ocean to compensate for sea-level rise is 5% relative to gdp\n" 222 | ] 223 | } 224 | ], 225 | "source": [ 226 | "relative_gdp_cost = (cost / global_gdp).to_reduced_units()\n", 227 | "print(f\"The cost to dredge the ocean to compensate for sea-level rise is {(relative_gdp_cost.m * 100):.0f}% relative to gdp\")\n" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "## Cost relative to doing nothing\n", 235 | "Here we compare the cost of dredging the ocean is cheaper than not doing anything and dealing with damages of sea-level rise. " 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": 12, 241 | "metadata": {}, 242 | "outputs": [ 243 | { 244 | "name": "stdout", 245 | "output_type": "stream", 246 | "text": [ 247 | "The cost to dredge the ocean to compensate for sea-level rise is 508% relative to gdp\n" 248 | ] 249 | } 250 | ], 251 | "source": [ 252 | "relative_to_nothing = (cost / cost_of_consequences).to_reduced_units()\n", 253 | "print(f\"The cost to dredge the ocean to compensate for sea-level rise is {(relative_to_nothing.m * 100):.0f}% relative to gdp\")\n", 254 | "\n" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "## Conclusion\n", 262 | "To dredge against sea-level rise, a rough estimate is that it takes about 5% of our GDP. The cost of dredging is more than 500% more expensive than doing nothing based on an unsubstantiated estimate of the cost of doing nothing. \n", 263 | "\n" 264 | ] 265 | } 266 | ], 267 | "metadata": { 268 | "kernelspec": { 269 | "display_name": "Python 3", 270 | "language": "python", 271 | "name": "python3" 272 | }, 273 | "language_info": { 274 | "codemirror_mode": { 275 | "name": "ipython", 276 | "version": 3 277 | }, 278 | "file_extension": ".py", 279 | "mimetype": "text/x-python", 280 | "name": "python", 281 | "nbconvert_exporter": "python", 282 | "pygments_lexer": "ipython3", 283 | "version": "3.8.8" 284 | } 285 | }, 286 | "nbformat": 4, 287 | "nbformat_minor": 4 288 | } 289 | -------------------------------------------------------------------------------- /extract_grid.py: -------------------------------------------------------------------------------- 1 | # remove part of the grid 2 | ds = netCDF4.Dataset(path.with_name('pillar_net.nc')) 3 | variables = {} 4 | node_vars = ['NetNode_x', 'NetNode_y', 'NetNode_z', 'NetNode_lat', 'NetNode_lon'] 5 | link_vars = ['NetLink', 'NetLinkType'] 6 | bndlink_vars = ['BndLink'] 7 | elem_vars = ['NetElemNode'] 8 | 9 | for var in node_vars: 10 | # copy data 11 | variables[var] = ds.variables[var][:] 12 | node_selection = np.logical_and(variables['NetNode_y'] >= 1000, variables['NetNode_y'] <= 2000) 13 | for var in node_vars: 14 | variables[var] = variables[var][node_selection] 15 | 16 | 17 | for var in link_vars: 18 | variables[var] = ds.variables[var][:] 19 | # lookup nodes that are still available 20 | node_idx_1 = np.where(node_selection)[0] + 1 21 | # look which links are still available 22 | from_filter = np.in1d(variables['NetLink'][:, 0], node_idx_1) 23 | to_filter = np.in1d(variables['NetLink'][:, 1], node_idx_1) 24 | # assume three grids are not connected 25 | assert (from_filter == to_filter).all() 26 | # otherwise we would have to transform into boundary links on removal of link 27 | link_selection = np.logical_and(from_filter, to_filter) 28 | for var in link_vars: 29 | variables[var] = variables[var][link_selection] 30 | 31 | for var in bndlink_vars: 32 | variables[var] = ds.variables[var][:] 33 | variables['BndLink'] 34 | bndlink_selection = np.in1d(variables['BndLink'], node_idx_1) 35 | for var in bndlink_vars: 36 | variables[var] = variables[var][bndlink_selection] 37 | 38 | 39 | for var in elem_vars: 40 | variables[var] = ds.variables[var][:] 41 | variables['NetElemNode'] 42 | net_elem_node = np.ma.masked_equal(variables['NetElemNode'], -2147483647) 43 | elem_selection = np.apply_along_axis(np.ma.in1d, 0, net_elem_node, node_idx_1) 44 | elem_selection = np.ma.masked_array(elem_selection, mask=net_elem_node.mask) 45 | # assume all cells are all in, or all out 46 | assert (elem_selection.all(axis=1) == elem_selection.any(axis=1)).all() 47 | elem_selection = elem_selection.all(axis=1) 48 | for var in elem_vars: 49 | variables[var] = variables[var][elem_selection] 50 | 51 | dims = { 52 | 'nNetNode': node_selection.sum(), 53 | 'nNetLink': link_selection.sum(), 54 | 'nNetLinkPts': 2, 55 | 'nBndLink': bndlink_selection.sum(), 56 | 'nNetElem': elem_selection.sum(), 57 | 'nNetElemMaxNode': 4 58 | } 59 | 60 | 61 | ds_new = netCDF4.Dataset(path.with_name('pillar_new.nc'), mode='w') 62 | # copy attributes 63 | for attr in ds.ncattrs(): 64 | ds_new.setncattr(attr, ds.getncattr(attr)) 65 | for dim, length in dims.items(): 66 | ds_new.createDimension(dim, length) 67 | for name, var in ds.variables.items(): 68 | new_var = ds_new.createVariable(name, var.dtype, var.dimensions) 69 | for attr in var.ncattrs(): 70 | new_var.setncattr(attr, var.getncattr(attr)) 71 | 72 | for name in ds.variables.keys(): 73 | ds_new.variables[name][:] = variables.get(name, ds.variables[name][:]) 74 | ds_new.close() -------------------------------------------------------------------------------- /matlab/EarthObservationWebServices.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | EarthObservationWebServices

Contents

% Tutorial on how to work with different flavours of web services for Earth Obersvation data
 70 | % 1. netCDF-CF-OPeNDAP using netcdf4 package
 71 | % 2. OGC WMS using owslib package
 72 | % 3. OGC WCS using owslib package
 73 | % For overview see OpenEarrth.eu > Data
 74 | % Image(url='https://publicwiki.deltares.nl/download/attachments/42401809/OpenEarthBuildingBlocks_standards_client_server.png
 75 | 
 76 | bbox = [-10 50 15 60];
 77 | clim = [0 10];
 78 | 

1. OPeNDAP: query indices, generate matlab code

http://zandmotor.citg.tudelft.nl/netcdfreadersguide/

dap0 = 'http://thredds.jpl.nasa.gov/thredds/dodsC/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml';
 79 | 
 80 | nc.lat  = ncread(dap0, 'lat');
 81 | nc.lon  = ncread(dap0, 'lon');
 82 | nc.time = ncread_cf_time(dap0, 'time');
 83 | 
 84 | ilon  = find(nc.lon >= bbox(1) & nc.lon <= bbox(3));
 85 | ilat  = find(nc.lat >= bbox(2) & nc.lat <= bbox(4));
 86 | itime = 1;
 87 | nc.l3m_data = ncread(dap0, 'l3m_data', [ilon(1) ilat(1) itime], [length(ilon) length(ilat) 1], [1 1 1]); % slow: 2D
 88 | 

render OPeNDAP

    figure('name','OPeNDAP')
 89 |     pcolorcorcen(nc.lon(ilon),nc.lat(ilat),nc.l3m_data')
 90 |     tickmap('ll');grid on;
 91 |     set(gca,'ydir','normal')
 92 |     caxis(clim)
 93 |     axislat
 94 |     title(['OPeNDAP: ',datestr(nc.time(itime),'yyyy-mm-ddTHH:MM:SS')]);
 95 |     [ax, h]=colorbarwithvtext('OPeDAP');
 96 |     print2screensizeoverwrite(['OPeNDAP_plotted_',datestr(nc.time(itime),30)])
 97 | 
Warning: An empty directory name was given. No directory will be created.
 98 | This syntax may not be supported in future releases. 
 99 | 

2.WCS

https://publicwiki.deltares.nl/display/OET/WCS+primer
wcs0 = 'http://thredds.jpl.nasa.gov/thredds/wcs/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml?' % service=WCS&version=1.0.0&request=GetCapabilities
100 | [url.wcs,OPT.wcs,lims.wcs] = wcs('server',wcs0,...
101 |                          'axis',[-10 50 15 60],...
102 |                          'format','GeoTIFF',....
103 |                          'time','1997-09-01T00:00:00Z');
104 | dprintf(strrep(url.wcs,'&','\n&'))
105 | % http://thredds.jpl.nasa.gov/thredds/wcs/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml?
106 | % &service=WCS
107 | % &version=1.0.0
108 | % &request=GetCoverage
109 | % &bbox=-10,50,15,60
110 | % &coverage=l3m_data
111 | % &format=GeoTIFF
112 | % &resx=
113 | % &resy=
114 | % &crs=OGC:CRS84
115 | % &time=1997-09-01T00:00:00
116 | wcsname = ['WCS_',OPT.wcs.coverage,'_',datestr(datenum(OPT.wcs.time,'yyyy-mm-ddTHH:MM:SS'),30),'.',OPT.wcs.format];
117 | urlwrite(url.wcs,wcsname);
118 | 
119 | wcs0 =
120 | 
121 | http://thredds.jpl.nasa.gov/thredds/wcs/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml?
122 | 
123 | used WxS cache:C:\Users\UYJ\AppData\Local\Temp\matlab.ows\\thredds_jpl_nasa_gov_thredds_wcs_ncml_aggregation_Chlorophyll_seawifs_aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R_ncml_service_WCS_version_1_0_0_request_GetCapabilities.xml
124 | wxs:not valid: only valid option returned: l3m_data
125 | used WxS cache:C:\Users\UYJ\AppData\Local\Temp\matlab.ows\\thredds_jpl_nasa_gov_thredds_wcs_ncml_aggregation_Chlorophyll_seawifs_aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R_ncml_service_WCS_version_1_0_0_request_DescribeCoverage_coverage_l3m_data.xml
126 | 
127 | OPT = 
128 | 
129 |            server: 'http://thredds.jpl.nasa.gov/thredds/wcs/ncml_aggregati...'
130 |           version: '1.0.0'
131 |           request: 'GetCoverage'
132 |          coverage: 'l3m_data'
133 |              axis: [-10 50 15 60]
134 |              bbox: ''
135 |            format: 'GeoTIFF'
136 |               crs: 'EPSG%3A4326'
137 |              resx: []
138 |              resy: []
139 |     interpolation: ''
140 |              time: '1997-09-01T00:00:00Z'
141 |              disp: 1
142 |          cachedir: 'C:\Users\UYJ\AppData\Local\Temp\matlab.ows\'
143 |          fixqmark: 1
144 | 
145 | wxs:validated: a format="GeoTIFF"
146 | wxs:not valid: a crs="EPSG%3A4326", choose from valid options:
147 | wxs:not valid: only valid option returned: OGC:CRS84
148 | wxs:not valid: only valid option returned: none
149 | http://thredds.jpl.nasa.gov/thredds/wcs/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml?
150 | &service=WCS
151 | &version=1.0.0
152 | &request=GetCoverage
153 | &bbox=-10,50,15,60
154 | &coverage=l3m_data
155 | &format=GeoTIFF
156 | &resx=
157 | &resy=
158 | &crs=OGC:CRS84
159 | &time=1997-09-01T00:00:00

render WCS

    figure('name',OPT.wcs.coverage)
160 |     [A,map,alpha] = imread(wcsname);
161 |     A = double(A);A(A==0)=NaN;
162 |     OPT.wcs.x = linspace(OPT.wcs.axis(1),OPT.wcs.axis(3),size(A,2));
163 |     OPT.wcs.y = linspace(OPT.wcs.axis(4),OPT.wcs.axis(2),size(A,1));
164 |     pcolorcorcen(OPT.wcs.x,OPT.wcs.y,double(A))
165 |     tickmap('ll');grid on;
166 |     set(gca,'ydir','normal')
167 |     axislat
168 |     title(['WCS: ',OPT.wcs.time]);
169 |     colorbar
170 |     caxis(clim)
171 |     [ax, h]=colorbarwithvtext(OPT.wcs.coverage);
172 |     print2screensizeoverwrite(['WCS_plotted_',mkvar(OPT.wcs.time)])
173 | 
Warning: An empty directory name was given. No directory will be created.
174 | This syntax may not be supported in future releases. 
175 | 

3.WMS: NB sometimes fails to to slow server rendering

https://publicwiki.deltares.nl/display/OET/WMS+primer
wms0 = 'http://thredds.jpl.nasa.gov/thredds/wms/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml?'; % service=WMS&version=1.3.0&request=GetCapabilities
176 | [url.wms,OPT.wms,lims.wms] = wms('server',wms0,...
177 |                 'colorscalerange',clim,... % non-OGC extension
178 |                 'styles','boxfill/sst_36',...
179 |                 'time','1997-09-01T00:00:00.000Z',...
180 |                 'axis',bbox); % spatial subet: speed-up
181 | dprintf(strrep(url.wms,'&','\n&'))
182 | % http://thredds.jpl.nasa.gov/thredds/wms/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml?
183 | % &service=WMS
184 | % &version=1.3.0
185 | % &request=GetMap
186 | % &bbox=50,-10,60,15
187 | % &layers=l3m_data
188 | % &format=image/png
189 | % &CRS=EPSG
190 | wmsname = ['WMS_',OPT.wms.layers,'_',datestr(datenum(OPT.wms.time,'yyyy-mm-ddTHH:MM:SS'),30),OPT.wms.ext];
191 | urlwrite(url.wms,wmsname);
192 | 
used WxS cache:C:\Users\UYJ\AppData\Local\Temp\matlab.ows\\thredds_jpl_nasa_gov_thredds_wms_ncml_aggregation_Chlorophyll_seawifs_aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R_ncml_service_WMS_version_1_3_0_request_GetCapabilities.xml
193 | wxs:not valid: only valid option returned: l3m_data
194 | crs=CRS:84 to be used instead of crs=EPSG:4326 to prevent mixing-up lat-lon in THREDDS
195 | http://thredds.jpl.nasa.gov/thredds/wms/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml?
196 | &service=WMS
197 | &version=1.3.0
198 | &request=GetMap
199 | &bbox=50,-10,60,15
200 | &layers=l3m_data
201 | &format=image/png
202 | &CRS=EPSG

render WMS

    figure('name',OPT.wms.layers)
203 |     [A,map,alpha] = imread(wmsname);
204 |     image(OPT.wms.x,OPT.wms.y,A)
205 |     colormap(map)
206 |     tickmap('ll');grid on;
207 |     set(gca,'ydir','normal')
208 |     axislat
209 |     title(['WMS: ',OPT.wms.time]);
210 |     [ax, h]=colorbarwithvtext(OPT.wms.layers);
211 |     set(ax,'YTickLabel',get(ax,'YTick')./size(map,1).*clim(2));
212 |     print2screensizeoverwrite(['WMS_plotted_',mkvar(OPT.wcs.time)])
213 | 
Warning: An empty directory name was given. No directory will be created.
214 | This syntax may not be supported in future releases. 
215 | 
-------------------------------------------------------------------------------- /matlab/EarthObservationWebServices.m: -------------------------------------------------------------------------------- 1 | % Tutorial on how to work with different flavours of web services for Earth Obersvation data 2 | % 1. netCDF-CF-OPeNDAP using netcdf4 package 3 | % 2. OGC WMS using owslib package, part of openearthtools 4 | % 3. OGC WCS using owslib package, part of openearthtools 5 | % For overview see OpenEarrth.eu > Data 6 | % Image(url='https://publicwiki.deltares.nl/download/attachments/42401809/OpenEarthBuildingBlocks_standards_client_server.png 7 | 8 | bbox = [-10 50 15 60]; 9 | clim = [0 10]; 10 | 11 | %% 1. OPeNDAP: query indices, generate matlab code 12 | % http://zandmotor.citg.tudelft.nl/netcdfreadersguide/ 13 | dap0 = 'http://thredds.jpl.nasa.gov/thredds/dodsC/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml'; 14 | 15 | nc.lat = ncread(dap0, 'lat'); 16 | nc.lon = ncread(dap0, 'lon'); 17 | nc.time = ncread_cf_time(dap0, 'time'); 18 | 19 | ilon = find(nc.lon >= bbox(1) & nc.lon <= bbox(3)); 20 | ilat = find(nc.lat >= bbox(2) & nc.lat <= bbox(4)); 21 | itime = 1; 22 | nc.l3m_data = ncread(dap0, 'l3m_data', [ilon(1) ilat(1) itime], [length(ilon) length(ilat) 1], [1 1 1]); % slow: 2D 23 | 24 | %% render OPeNDAP 25 | figure('name','OPeNDAP') 26 | pcolorcorcen(nc.lon(ilon),nc.lat(ilat),nc.l3m_data') 27 | tickmap('ll');grid on; 28 | set(gca,'ydir','normal') 29 | caxis(clim) 30 | axislat 31 | title(['OPeNDAP: ',datestr(nc.time(itime),'yyyy-mm-ddTHH:MM:SS')]); 32 | [ax, h]=colorbarwithvtext('OPeDAP'); 33 | print2screensizeoverwrite(['OPeNDAP_plotted_',datestr(nc.time(itime),30)]) 34 | 35 | %% 2.WCS 36 | % https://publicwiki.deltares.nl/display/OET/WCS+primer 37 | wcs0 = 'http://thredds.jpl.nasa.gov/thredds/wcs/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml?' % service=WCS&version=1.0.0&request=GetCapabilities 38 | [url.wcs,OPT.wcs,lims.wcs] = wcs('server',wcs0,... 39 | 'axis',[-10 50 15 60],... 40 | 'format','GeoTIFF',.... 41 | 'time','1997-09-01T00:00:00Z'); 42 | dprintf(strrep(url.wcs,'&','\n&')) 43 | % http://thredds.jpl.nasa.gov/thredds/wcs/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml? 44 | % &service=WCS 45 | % &version=1.0.0 46 | % &request=GetCoverage 47 | % &bbox=-10,50,15,60 48 | % &coverage=l3m_data 49 | % &format=GeoTIFF 50 | % &resx= 51 | % &resy= 52 | % &crs=OGC:CRS84 53 | % &time=1997-09-01T00:00:00 54 | wcsname = ['WCS_',OPT.wcs.coverage,'_',datestr(datenum(OPT.wcs.time,'yyyy-mm-ddTHH:MM:SS'),30),'.',OPT.wcs.format]; 55 | urlwrite(url.wcs,wcsname); 56 | %% render WCS 57 | figure('name',OPT.wcs.coverage) 58 | [A,map,alpha] = imread(wcsname); 59 | A = double(A);A(A==0)=NaN; 60 | OPT.wcs.x = linspace(OPT.wcs.axis(1),OPT.wcs.axis(3),size(A,2)); 61 | OPT.wcs.y = linspace(OPT.wcs.axis(4),OPT.wcs.axis(2),size(A,1)); 62 | pcolorcorcen(OPT.wcs.x,OPT.wcs.y,double(A)) 63 | tickmap('ll');grid on; 64 | set(gca,'ydir','normal') 65 | axislat 66 | title(['WCS: ',OPT.wcs.time]); 67 | colorbar 68 | caxis(clim) 69 | [ax, h]=colorbarwithvtext(OPT.wcs.coverage); 70 | print2screensizeoverwrite(['WCS_plotted_',mkvar(OPT.wcs.time)]) 71 | 72 | %% 3.WMS: NB sometimes fails to to slow server rendering 73 | % https://publicwiki.deltares.nl/display/OET/WMS+primer 74 | wms0 = 'http://thredds.jpl.nasa.gov/thredds/wms/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml?'; % service=WMS&version=1.3.0&request=GetCapabilities 75 | [url.wms,OPT.wms,lims.wms] = wms('server',wms0,... 76 | 'colorscalerange',clim,... % non-OGC extension 77 | 'styles','boxfill/sst_36',... 78 | 'time','1997-09-01T00:00:00.000Z',... 79 | 'axis',bbox); % spatial subet: speed-up 80 | dprintf(strrep(url.wms,'&','\n&')) 81 | % http://thredds.jpl.nasa.gov/thredds/wms/ncml_aggregation/Chlorophyll/seawifs/aggregate__SEAWIFS_L3_CHLA_MONTHLY_9KM_R.ncml? 82 | % &service=WMS 83 | % &version=1.3.0 84 | % &request=GetMap 85 | % &bbox=50,-10,60,15 86 | % &layers=l3m_data 87 | % &format=image/png 88 | % &CRS=EPSG 89 | wmsname = ['WMS_',OPT.wms.layers,'_',datestr(datenum(OPT.wms.time,'yyyy-mm-ddTHH:MM:SS'),30),OPT.wms.ext]; 90 | urlwrite(url.wms,wmsname); 91 | %% render WMS 92 | figure('name',OPT.wms.layers) 93 | [A,map,alpha] = imread(wmsname); 94 | image(OPT.wms.x,OPT.wms.y,A) 95 | colormap(map) 96 | tickmap('ll');grid on; 97 | set(gca,'ydir','normal') 98 | axislat 99 | title(['WMS: ',OPT.wms.time]); 100 | [ax, h]=colorbarwithvtext(OPT.wms.layers); 101 | set(ax,'YTickLabel',get(ax,'YTick')./size(map,1).*clim(2)); 102 | print2screensizeoverwrite(['WMS_plotted_',mkvar(OPT.wcs.time)]) 103 | -------------------------------------------------------------------------------- /matlab/EarthObservationWebServices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openearth/notebooks/1786d5162aa0a0a8c2f5bd880328d92f0efeaf1b/matlab/EarthObservationWebServices.png -------------------------------------------------------------------------------- /matlab/EarthObservationWebServices_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openearth/notebooks/1786d5162aa0a0a8c2f5bd880328d92f0efeaf1b/matlab/EarthObservationWebServices_01.png -------------------------------------------------------------------------------- /matlab/EarthObservationWebServices_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openearth/notebooks/1786d5162aa0a0a8c2f5bd880328d92f0efeaf1b/matlab/EarthObservationWebServices_02.png -------------------------------------------------------------------------------- /matlab/EarthObservationWebServices_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openearth/notebooks/1786d5162aa0a0a8c2f5bd880328d92f0efeaf1b/matlab/EarthObservationWebServices_03.png -------------------------------------------------------------------------------- /maximum_waterlevels_in_west_terschelling.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import datetime\n", 10 | "import netCDF4\n", 11 | "import pandas as pd\n", 12 | "import seaborn as sns\n", 13 | "\n", 14 | "import numpy as np\n", 15 | "import matplotlib.pyplot as plt\n", 16 | "%matplotlib inline" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 2, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "# the URL for West Terschelling\n", 26 | "url = 'http://opendap.deltares.nl/thredds/dodsC/opendap/rijkswaterstaat/waterbase/27_Waterhoogte_in_cm_t.o.v._normaal_amsterdams_peil_in_oppervlaktewater/nc/id1-WESTTSLG.nc'" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 3, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "# open the dataset\n", 36 | "ds = netCDF4.Dataset(url)" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 4, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "# lookup relevant variables\n", 46 | "t = ds.variables['time']\n", 47 | "ssh = ds.variables['sea_surface_height']\n", 48 | " \n" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 5, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "# convert to table\n", 58 | "# get all times and convert to date objects (so we can group by year)\n", 59 | "dates = netCDF4.num2date(t[:], ds.variables['time'].units)\n", 60 | "# query history of sea surface height and squeeze out empty dimension (1 location x time)\n", 61 | "ssh_values = np.squeeze(ssh[:])\n", 62 | "df = pd.DataFrame(data=dict(dates=dates, ssh=ssh_values))\n", 63 | "# use date as an index\n", 64 | "df = df.set_index('dates')" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 10, 70 | "metadata": {}, 71 | "outputs": [ 72 | { 73 | "data": { 74 | "image/png": "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\n", 75 | "text/plain": [ 76 | "" 77 | ] 78 | }, 79 | "metadata": {}, 80 | "output_type": "display_data" 81 | } 82 | ], 83 | "source": [ 84 | "# make a new figure\n", 85 | "fig, ax = plt.subplots(figsize=(13, 8))\n", 86 | "# group data per year (max over 2000 is stored as 2000-12-31)\n", 87 | "grouped = df.groupby(pd.Grouper(freq=\"A\", label='right'))\n", 88 | "grouped_max = grouped.max()\n", 89 | "grouped_min = grouped.min()\n", 90 | "ax.plot(\n", 91 | " grouped_max.index.to_pydatetime(), \n", 92 | " grouped_max.ssh, \n", 93 | " marker='_', \n", 94 | " linewidth=0, \n", 95 | " markeredgewidth=5, \n", 96 | " markersize=12\n", 97 | ")\n", 98 | "\n", 99 | "y_label = \"{name}, maximum per jaar [{units}]\".format(\n", 100 | " name=ds.variables['sea_surface_height'].Aquo_Grootheid_omschrijving,\n", 101 | " units=ds.variables['sea_surface_height'].Aquo_Eenheid_code\n", 102 | ")\n", 103 | "ax.set_ylabel(y_label)\n", 104 | "ax.set_xlabel('Tijd')\n", 105 | "title = \"station: {station}, donar id: {donar_id}\".format(station=ds.stationname, donar_id=ds.donar_code)\n", 106 | "ax.set_title(title)\n", 107 | "ticks = list(\n", 108 | " datetime.datetime(1920 + i, 1, 1).toordinal() \n", 109 | " for i \n", 110 | " in range(0, 110, 20)\n", 111 | ")\n", 112 | "ax.xaxis.set_ticks(ticks);\n" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": null, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [] 121 | } 122 | ], 123 | "metadata": { 124 | "kernelspec": { 125 | "display_name": "Python 3", 126 | "language": "python", 127 | "name": "python3" 128 | }, 129 | "language_info": { 130 | "codemirror_mode": { 131 | "name": "ipython", 132 | "version": 3 133 | }, 134 | "file_extension": ".py", 135 | "mimetype": "text/x-python", 136 | "name": "python", 137 | "nbconvert_exporter": "python", 138 | "pygments_lexer": "ipython3", 139 | "version": "3.6.3" 140 | } 141 | }, 142 | "nbformat": 4, 143 | "nbformat_minor": 2 144 | } 145 | -------------------------------------------------------------------------------- /ogr 31370.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "" 4 | }, 5 | "nbformat": 3, 6 | "nbformat_minor": 0, 7 | "worksheets": [ 8 | { 9 | "cells": [ 10 | { 11 | "cell_type": "code", 12 | "collapsed": false, 13 | "input": [ 14 | "# Let's check our version\n", 15 | "!cs2cs \n" 16 | ], 17 | "language": "python", 18 | "metadata": {}, 19 | "outputs": [ 20 | { 21 | "output_type": "stream", 22 | "stream": "stdout", 23 | "text": [ 24 | "Rel. 4.7.1, 23 September 2009\r\n", 25 | "usage: cs2cs [ -eEfIlrstvwW [args] ] [ +opts[=arg] ]\r\n", 26 | " [+to [+opts[=arg] [ files ]\r\n" 27 | ] 28 | } 29 | ], 30 | "prompt_number": 12 31 | }, 32 | { 33 | "cell_type": "code", 34 | "collapsed": false, 35 | "input": [ 36 | "# We would expect this to work, but it doesn't\n", 37 | "# The towgs84 is used for transformation\n", 38 | "! echo \"49554 215020 0\" | cs2cs -v +init=epsg:31370 +to +init=epsg:4326 -f %.6f" 39 | ], 40 | "language": "python", 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "output_type": "stream", 45 | "stream": "stdout", 46 | "text": [ 47 | "# ---- From Coordinate System ----\r\n", 48 | "#Lambert Conformal Conic\r\n", 49 | "#\tConic, Sph&Ell\r\n", 50 | "#\tlat_1= and lat_2= or lat_0\r\n", 51 | "# +init=epsg:31370 +proj=lcc +lat_1=51.16666723333333 +lat_2=49.8333339\r\n", 52 | "# +lat_0=90 +lon_0=4.367486666666666 +x_0=150000.013 +y_0=5400088.438\r\n", 53 | "# +ellps=intl\r\n", 54 | "# +towgs84=106.869,-52.2978,103.724,-0.33657,0.456955,-1.84218,1 +units=m\r\n", 55 | "# +no_defs\r\n", 56 | "# ---- To Coordinate System ----\r\n", 57 | "#Lat/long (Geodetic alias)\r\n", 58 | "#\t\r\n", 59 | "# +init=epsg:4326 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs\r\n", 60 | "# +towgs84=0,0,0\r\n", 61 | "#--- following specified but NOT used\r\n", 62 | "# +ellps=WGS84\r\n", 63 | "2.928019\t51.235804 347.868509\r\n" 64 | ] 65 | } 66 | ], 67 | "prompt_number": 13 68 | }, 69 | { 70 | "cell_type": "code", 71 | "collapsed": false, 72 | "input": [ 73 | "# We get a different result if we use invproj, what's going on?\n", 74 | "! echo \"49554 215020\" | invproj -v +init=epsg:31370 -f %.6f\n", 75 | "\n", 76 | " " 77 | ], 78 | "language": "python", 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "output_type": "stream", 83 | "stream": "stdout", 84 | "text": [ 85 | "#Lambert Conformal Conic\r\n", 86 | "#\tConic, Sph&Ell\r\n", 87 | "#\tlat_1= and lat_2= or lat_0\r\n", 88 | "# +init=epsg:31370 +proj=lcc +lat_1=51.16666723333333 +lat_2=49.8333339\r\n", 89 | "# +lat_0=90 +lon_0=4.367486666666666 +x_0=150000.013 +y_0=5400088.438\r\n", 90 | "# +ellps=intl\r\n", 91 | "# +towgs84=106.869,-52.2978,103.724,-0.33657,0.456955,-1.84218,1 +units=m\r\n", 92 | "# +no_defs\r\n", 93 | "2.929249\t51.236883\r\n" 94 | ] 95 | } 96 | ], 97 | "prompt_number": 14 98 | }, 99 | { 100 | "cell_type": "code", 101 | "collapsed": false, 102 | "input": [ 103 | "# We get the correct result if we fix the last parameter of the towgs84 parameter\n", 104 | "# http://osgeo-org.1560.x6.nabble.com/proj4-epsg-31370-possible-wrong-parameters-td3841364.html\n", 105 | "!echo \"49554 215020\" | cs2cs -v \\\n", 106 | " +proj=lcc +lat_1=51.16666723333333 +lat_2=49.8333339 +lat_0=90 \\\n", 107 | " +lon_0=4.367486666666666 +x_0=150000.013 +y_0=5400088.438 +ellps=intl \\\n", 108 | " +towgs84=-106.869,52.2978,-103.724,0.3366,-0.457,1.8422,-1.2747 +units=m \\\n", 109 | " +no_defs -to +proj=longlat +datum=WGS84 +ellps=WGS84 +no_defs -f %6f" 110 | ], 111 | "language": "python", 112 | "metadata": {}, 113 | "outputs": [ 114 | { 115 | "output_type": "stream", 116 | "stream": "stdout", 117 | "text": [ 118 | "o ---- From Coordinate System ----\r\n", 119 | "#Lambert Conformal Conic\r\n", 120 | "#\tConic, Sph&Ell\r\n", 121 | "#\tlat_1= and lat_2= or lat_0\r\n", 122 | "# +proj=lcc +lat_1=51.16666723333333 +lat_2=49.8333339 +lat_0=90\r\n", 123 | "# +lon_0=4.367486666666666 +x_0=150000.013 +y_0=5400088.438 +ellps=intl\r\n", 124 | "# +towgs84=-106.869,52.2978,-103.724,0.3366,-0.457,1.8422,-1.2747\r\n", 125 | "# +units=m +no_defs +datum=WGS84\r\n", 126 | "#--- following specified but NOT used\r\n", 127 | "# +proj=longlat +ellps=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0\r\n", 128 | "o ---- To Coordinate System ----\r\n", 129 | "#Lat/long (Geodetic alias)\r\n", 130 | "#\t\r\n", 131 | "# +proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0\r\n", 132 | "2.930480\t51.236358 41.428643\r\n" 133 | ] 134 | } 135 | ], 136 | "prompt_number": 15 137 | }, 138 | { 139 | "cell_type": "code", 140 | "collapsed": false, 141 | "input": [ 142 | "# This does not work for invproj because proj and invproj ignore the datum shift\n", 143 | "# The towgs84 is ignored\n", 144 | "!echo \"49554 215020\" | invproj -v \\\n", 145 | " +proj=lcc +lat_1=51.16666723333333 +lat_2=49.8333339 \\\n", 146 | " +lat_0=90 +lon_0=4.367486666666666 +x_0=150000.013 +y_0=5400088.438 +ellps=intl \\\n", 147 | " +towgs84=-1,1,1,1,1,1,1 +units=m \\\n", 148 | " +no_defs \\\n", 149 | " -f %6f" 150 | ], 151 | "language": "python", 152 | "metadata": {}, 153 | "outputs": [ 154 | { 155 | "output_type": "stream", 156 | "stream": "stdout", 157 | "text": [ 158 | "#Lambert Conformal Conic\r\n", 159 | "#\tConic, Sph&Ell\r\n", 160 | "#\tlat_1= and lat_2= or lat_0\r\n", 161 | "# +proj=lcc +lat_1=51.16666723333333 +lat_2=49.8333339 +lat_0=90\r\n", 162 | "# +lon_0=4.367486666666666 +x_0=150000.013 +y_0=5400088.438 +ellps=intl\r\n", 163 | "# +towgs84=-1,1,1,1,1,1,1 +units=m +no_defs\r\n", 164 | "2.929249\t51.236883\r\n" 165 | ] 166 | } 167 | ], 168 | "prompt_number": 16 169 | }, 170 | { 171 | "cell_type": "code", 172 | "collapsed": false, 173 | "input": [ 174 | "# There is another datums shift that gives the same result on spatialreference.org\n", 175 | "# http://spatialreference.org/ref/sr-org/epsg31370-correct-datum-shift/\n", 176 | "!echo \"49554 215020\" | cs2cs -v \\\n", 177 | "+proj=lcc +lat_1=51.16666723333334 +lat_2=49.83333389999999 \\\n", 178 | "+lat_0=90 +lon_0=4.367486666666666 +x_0=150000.013 +y_0=5400088.438 \\\n", 179 | "+ellps=intl +towgs84=-99.1,53.3,-112.5,0.419,-0.83,1.885,-1.0 +units=m +no_defs \\\n", 180 | "-to +datum=WGS84 +ellps=WGS84 -f %6f" 181 | ], 182 | "language": "python", 183 | "metadata": {}, 184 | "outputs": [ 185 | { 186 | "output_type": "stream", 187 | "stream": "stdout", 188 | "text": [ 189 | "o ---- From Coordinate System ----\r\n", 190 | "#Lambert Conformal Conic\r\n", 191 | "#\tConic, Sph&Ell\r\n", 192 | "#\tlat_1= and lat_2= or lat_0\r\n", 193 | "# +proj=lcc +lat_1=51.16666723333334 +lat_2=49.83333389999999 +lat_0=90\r\n", 194 | "# +lon_0=4.367486666666666 +x_0=150000.013 +y_0=5400088.438 +ellps=intl\r\n", 195 | "# +towgs84=-99.1,53.3,-112.5,0.419,-0.83,1.885,-1.0 +units=m +no_defs\r\n", 196 | "# +datum=WGS84\r\n", 197 | "#--- following specified but NOT used\r\n", 198 | "# +ellps=WGS84 +ellps=WGS84 +towgs84=0,0,0\r\n", 199 | "o ---- To Coordinate System ----\r\n", 200 | "#Lat/long (Geodetic alias)\r\n", 201 | "#\t\r\n", 202 | "# +proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0\r\n", 203 | "2.930478\t51.236358 41.262401\r\n" 204 | ] 205 | } 206 | ], 207 | "prompt_number": 17 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "metadata": {}, 212 | "source": [ 213 | "You can also use the ogr2ogr tool, which uses the osr library.\n", 214 | "\n", 215 | "This one is more up to date on my system. We have to define the format of our csv file in a vrt file (or use geojson).\n" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "collapsed": false, 221 | "input": [ 222 | "%%file test.vrt\n", 223 | "\n", 224 | " \n", 225 | " test.csv\n", 226 | " wkbPoint\n", 227 | " EPSG:31370\n", 228 | " \n", 229 | " \n", 230 | "" 231 | ], 232 | "language": "python", 233 | "metadata": {}, 234 | "outputs": [ 235 | { 236 | "output_type": "stream", 237 | "stream": "stdout", 238 | "text": [ 239 | "Overwriting test.vrt\n" 240 | ] 241 | } 242 | ], 243 | "prompt_number": 18 244 | }, 245 | { 246 | "cell_type": "code", 247 | "collapsed": false, 248 | "input": [ 249 | "! echo \"x,y\\n49554,215020\" >test.csv \n", 250 | "jsontxt = ! ogr2ogr -f GeoJSON -t_srs EPSG:4326 /dev/stdout test.vrt\n", 251 | "import json\n", 252 | "#json.loads(jsontxt)\n", 253 | "print(\"\\n\".join(jsontxt))\n", 254 | "json.loads(\"\".join(jsontxt))['features'][0]['geometry']['coordinates']" 255 | ], 256 | "language": "python", 257 | "metadata": {}, 258 | "outputs": [ 259 | { 260 | "output_type": "stream", 261 | "stream": "stdout", 262 | "text": [ 263 | "{\n", 264 | "\"type\": \"FeatureCollection\",\n", 265 | "\"features\": [\n", 266 | "{ \"type\": \"Feature\", \"properties\": { \"x\": \"49554\", \"y\": \"215020\" }, \"geometry\": { \"type\": \"Point\", \"coordinates\": [ 2.930479615690256, 51.236357952698896 ] } }\n", 267 | "\n", 268 | "]\n", 269 | "}\n" 270 | ] 271 | }, 272 | { 273 | "metadata": {}, 274 | "output_type": "pyout", 275 | "prompt_number": 19, 276 | "text": [ 277 | "[2.930479615690256, 51.236357952698896]" 278 | ] 279 | } 280 | ], 281 | "prompt_number": 19 282 | }, 283 | { 284 | "cell_type": "code", 285 | "collapsed": false, 286 | "input": [ 287 | "# Or you can use a python script to talk to the osr library, which as the correct coordinates.\n", 288 | "import osgeo.osr\n", 289 | "src = osgeo.osr.SpatialReference()\n", 290 | "dst = osgeo.osr.SpatialReference()\n", 291 | "src.ImportFromEPSG(31370)\n", 292 | "print src.GetTOWGS84()\n", 293 | "dst.ImportFromEPSG(4326)\n", 294 | "transform = osgeo.osr.CoordinateTransformation(src, dst)\n", 295 | "lon, lat, z = transform.TransformPoint(49554, 215020, 0)\n", 296 | "print(lon, lat, z)" 297 | ], 298 | "language": "python", 299 | "metadata": {}, 300 | "outputs": [ 301 | { 302 | "output_type": "stream", 303 | "stream": "stdout", 304 | "text": [ 305 | "(-106.869, 52.2978, -103.724, 0.3366, -0.457, 1.8422, -1.2747)\n", 306 | "(2.930479615690256, 51.236357952698896, 41.428643393330276)\n" 307 | ] 308 | } 309 | ], 310 | "prompt_number": 20 311 | }, 312 | { 313 | "cell_type": "code", 314 | "collapsed": false, 315 | "input": [], 316 | "language": "python", 317 | "metadata": {}, 318 | "outputs": [], 319 | "prompt_number": 20 320 | } 321 | ], 322 | "metadata": {} 323 | } 324 | ] 325 | } -------------------------------------------------------------------------------- /time and timezones.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:231c2bf08c3f4347e23efc2c682d6809a370d9c4562379b7aad0a72b0e5d1258" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "- time\n", 16 | "- time notation\n", 17 | "- timeseries\n", 18 | "- reading/writing data\n", 19 | "- plotting dates\n", 20 | "\n", 21 | "- packages, functions, structures inside a .py file\n" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "collapsed": false, 27 | "input": [ 28 | "# relevant packages for time\n", 29 | "# from the standard library:\n", 30 | "import time\n", 31 | "import datetime\n", 32 | "\n", 33 | "# external packages\n", 34 | "import pytz\n", 35 | "import dateutil\n" 36 | ], 37 | "language": "python", 38 | "metadata": {}, 39 | "outputs": [], 40 | "prompt_number": 1 41 | }, 42 | { 43 | "cell_type": "code", 44 | "collapsed": false, 45 | "input": [ 46 | "# time is based on the c time library\n", 47 | "# Return the current time in seconds since the Epoch.\n", 48 | "time.time()" 49 | ], 50 | "language": "python", 51 | "metadata": {}, 52 | "outputs": [ 53 | { 54 | "metadata": {}, 55 | "output_type": "pyout", 56 | "prompt_number": 43, 57 | "text": [ 58 | "1404751531.032971" 59 | ] 60 | } 61 | ], 62 | "prompt_number": 43 63 | }, 64 | { 65 | "cell_type": "code", 66 | "collapsed": false, 67 | "input": [ 68 | "?time" 69 | ], 70 | "language": "python", 71 | "metadata": {}, 72 | "outputs": [], 73 | "prompt_number": 42 74 | }, 75 | { 76 | "cell_type": "code", 77 | "collapsed": false, 78 | "input": [ 79 | "# epoch in greenwich:\n", 80 | "time.gmtime(0)" 81 | ], 82 | "language": "python", 83 | "metadata": {}, 84 | "outputs": [ 85 | { 86 | "metadata": {}, 87 | "output_type": "pyout", 88 | "prompt_number": 14, 89 | "text": [ 90 | "time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)" 91 | ] 92 | } 93 | ], 94 | "prompt_number": 14 95 | }, 96 | { 97 | "cell_type": "code", 98 | "collapsed": false, 99 | "input": [ 100 | "# current time in greenwich\n", 101 | "time.gmtime()" 102 | ], 103 | "language": "python", 104 | "metadata": {}, 105 | "outputs": [ 106 | { 107 | "metadata": {}, 108 | "output_type": "pyout", 109 | "prompt_number": 13, 110 | "text": [ 111 | "time.struct_time(tm_year=2014, tm_mon=7, tm_mday=7, tm_hour=12, tm_min=23, tm_sec=2, tm_wday=0, tm_yday=188, tm_isdst=0)" 112 | ] 113 | } 114 | ], 115 | "prompt_number": 13 116 | }, 117 | { 118 | "cell_type": "code", 119 | "collapsed": false, 120 | "input": [ 121 | "# object oriented date/time\n", 122 | "import datetime\n", 123 | "birthday = datetime.datetime(1976, 2, 23)\n", 124 | "\n", 125 | "class Person:\n", 126 | " def __init__(self, name):\n", 127 | " self.name = name\n", 128 | " @staticmethod\n", 129 | " def born():\n", 130 | " person = Person(name=None)\n", 131 | " return person\n", 132 | "Person.born()" 133 | ], 134 | "language": "python", 135 | "metadata": {}, 136 | "outputs": [ 137 | { 138 | "metadata": {}, 139 | "output_type": "pyout", 140 | "prompt_number": 72, 141 | "text": [ 142 | "<__main__.Person instance at 0x103677d40>" 143 | ] 144 | } 145 | ], 146 | "prompt_number": 72 147 | }, 148 | { 149 | "cell_type": "code", 150 | "collapsed": false, 151 | "input": [ 152 | "now = datetime.datetime.now()\n", 153 | "now" 154 | ], 155 | "language": "python", 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "metadata": {}, 160 | "output_type": "pyout", 161 | "prompt_number": 45, 162 | "text": [ 163 | "datetime.datetime(2014, 7, 7, 18, 48, 20, 320138)" 164 | ] 165 | } 166 | ], 167 | "prompt_number": 45 168 | }, 169 | { 170 | "cell_type": "code", 171 | "collapsed": false, 172 | "input": [ 173 | "# common format\n", 174 | "now.isoformat()" 175 | ], 176 | "language": "python", 177 | "metadata": {}, 178 | "outputs": [ 179 | { 180 | "metadata": {}, 181 | "output_type": "pyout", 182 | "prompt_number": 48, 183 | "text": [ 184 | "'2014-07-07T18:48:20.320138'" 185 | ] 186 | } 187 | ], 188 | "prompt_number": 48 189 | }, 190 | { 191 | "cell_type": "code", 192 | "collapsed": false, 193 | "input": [ 194 | "# date notation\n", 195 | "now + datetime.timedelta(days=10)" 196 | ], 197 | "language": "python", 198 | "metadata": {}, 199 | "outputs": [ 200 | { 201 | "metadata": {}, 202 | "output_type": "pyout", 203 | "prompt_number": 50, 204 | "text": [ 205 | "datetime.datetime(2014, 7, 17, 18, 48, 20, 320138)" 206 | ] 207 | } 208 | ], 209 | "prompt_number": 50 210 | }, 211 | { 212 | "cell_type": "code", 213 | "collapsed": false, 214 | "input": [ 215 | "import pytz" 216 | ], 217 | "language": "python", 218 | "metadata": {}, 219 | "outputs": [], 220 | "prompt_number": 53 221 | }, 222 | { 223 | "cell_type": "code", 224 | "collapsed": false, 225 | "input": [], 226 | "language": "python", 227 | "metadata": {}, 228 | "outputs": [] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "collapsed": false, 233 | "input": [ 234 | "# current timezone\n", 235 | "tz = pytz.timezone('Europe/Amsterdam')\n", 236 | "tz" 237 | ], 238 | "language": "python", 239 | "metadata": {}, 240 | "outputs": [ 241 | { 242 | "metadata": {}, 243 | "output_type": "pyout", 244 | "prompt_number": 74, 245 | "text": [ 246 | "" 247 | ] 248 | } 249 | ], 250 | "prompt_number": 74 251 | }, 252 | { 253 | "cell_type": "code", 254 | "collapsed": false, 255 | "input": [ 256 | "# local time\n", 257 | "tz.localize(now)" 258 | ], 259 | "language": "python", 260 | "metadata": {}, 261 | "outputs": [ 262 | { 263 | "metadata": {}, 264 | "output_type": "pyout", 265 | "prompt_number": 75, 266 | "text": [ 267 | "datetime.datetime(2014, 7, 7, 18, 48, 20, 320138, tzinfo=)" 268 | ] 269 | } 270 | ], 271 | "prompt_number": 75 272 | }, 273 | { 274 | "cell_type": "code", 275 | "collapsed": false, 276 | "input": [ 277 | "import dateutil.parser\n" 278 | ], 279 | "language": "python", 280 | "metadata": {}, 281 | "outputs": [], 282 | "prompt_number": 79 283 | }, 284 | { 285 | "cell_type": "code", 286 | "collapsed": false, 287 | "input": [ 288 | "for date in ['23/02/1976', '2000-01-02']:\n", 289 | " print(dateutil.parser.parse(date))" 290 | ], 291 | "language": "python", 292 | "metadata": {}, 293 | "outputs": [ 294 | { 295 | "output_type": "stream", 296 | "stream": "stdout", 297 | "text": [ 298 | "1976-02-23 00:00:00\n", 299 | "2000-01-02 00:00:00\n" 300 | ] 301 | } 302 | ], 303 | "prompt_number": 85 304 | }, 305 | { 306 | "cell_type": "code", 307 | "collapsed": false, 308 | "input": [ 309 | "datetime.datetime.strptime('03/02/1976', '%d/%m/%Y')" 310 | ], 311 | "language": "python", 312 | "metadata": {}, 313 | "outputs": [ 314 | { 315 | "metadata": {}, 316 | "output_type": "pyout", 317 | "prompt_number": 86, 318 | "text": [ 319 | "datetime.datetime(1976, 2, 3, 0, 0)" 320 | ] 321 | } 322 | ], 323 | "prompt_number": 86 324 | }, 325 | { 326 | "cell_type": "code", 327 | "collapsed": false, 328 | "input": [ 329 | "import dateutil.rrule" 330 | ], 331 | "language": "python", 332 | "metadata": {}, 333 | "outputs": [], 334 | "prompt_number": 88 335 | }, 336 | { 337 | "cell_type": "code", 338 | "collapsed": false, 339 | "input": [ 340 | " " 341 | ], 342 | "language": "python", 343 | "metadata": {}, 344 | "outputs": [ 345 | { 346 | "metadata": {}, 347 | "output_type": "pyout", 348 | "prompt_number": 91, 349 | "text": [ 350 | "datetime.datetime(2014, 7, 7, 19, 8, 1)" 351 | ] 352 | } 353 | ], 354 | "prompt_number": 91 355 | }, 356 | { 357 | "cell_type": "code", 358 | "collapsed": false, 359 | "input": [ 360 | "import pandas" 361 | ], 362 | "language": "python", 363 | "metadata": {}, 364 | "outputs": [], 365 | "prompt_number": 92 366 | }, 367 | { 368 | "cell_type": "code", 369 | "collapsed": false, 370 | "input": [ 371 | "values = [1,2,3]\n", 372 | "times = [datetime.datetime(2000,1,1), datetime.datetime(2000,1,2), datetime.datetime(2000,1,3)]\n", 373 | "ts = pandas.TimeSeries(values, index=times)" 374 | ], 375 | "language": "python", 376 | "metadata": {}, 377 | "outputs": [], 378 | "prompt_number": 102 379 | }, 380 | { 381 | "cell_type": "code", 382 | "collapsed": false, 383 | "input": [ 384 | "import matplotlib.pyplot as plt" 385 | ], 386 | "language": "python", 387 | "metadata": {}, 388 | "outputs": [], 389 | "prompt_number": 103 390 | }, 391 | { 392 | "cell_type": "code", 393 | "collapsed": false, 394 | "input": [ 395 | "fig, ax = plt.subplots()\n", 396 | "ax.plot(times, values)\n", 397 | "ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%d-%m'))\n", 398 | "ax.xaxis.set_major_locator(matplotlib.dates.DayLocator())" 399 | ], 400 | "language": "python", 401 | "metadata": {}, 402 | "outputs": [ 403 | { 404 | "metadata": {}, 405 | "output_type": "display_data", 406 | "png": "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\n", 407 | "text": [ 408 | "" 409 | ] 410 | } 411 | ], 412 | "prompt_number": 111 413 | }, 414 | { 415 | "cell_type": "code", 416 | "collapsed": false, 417 | "input": [], 418 | "language": "python", 419 | "metadata": {}, 420 | "outputs": [] 421 | } 422 | ], 423 | "metadata": {} 424 | } 425 | ] 426 | } -------------------------------------------------------------------------------- /twitter.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import json\n", 10 | "import os.path\n", 11 | "import time\n", 12 | "import logging\n", 13 | "import datetime\n", 14 | "import itertools\n", 15 | "\n", 16 | "import requests\n", 17 | "import geojson\n", 18 | "import tweepy\n", 19 | "\n", 20 | "from tweepy import Stream\n", 21 | "from tweepy.streaming import StreamListener\n", 22 | "\n", 23 | "import IPython.display\n", 24 | "\n", 25 | "\n", 26 | "\n", 27 | "logger = logging.getLogger('notebook')\n", 28 | "logger.setLevel(logging.INFO)\n" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 2, 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "# secret keys are stored here\n", 38 | "keys = json.load(open(os.path.expanduser(\"~/.twitter.json\")))['notebook-example']\n", 39 | "\n", 40 | "# you can generate keys here:\n", 41 | "# https://apps.twitter.com/" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 3, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "# now we can load the access keys\n", 51 | "auth = tweepy.OAuthHandler(keys['consumer_key'], keys['consumer_secret'])\n", 52 | "auth.set_access_token(keys['access_key'], keys['access_secret'])\n", 53 | "api = tweepy.API(auth)" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 4, 59 | "metadata": {}, 60 | "outputs": [ 61 | { 62 | "data": { 63 | "text/plain": [ 64 | "'SiggyF'" 65 | ] 66 | }, 67 | "execution_count": 4, 68 | "metadata": {}, 69 | "output_type": "execute_result" 70 | } 71 | ], 72 | "source": [ 73 | "# this should display your name\n", 74 | "user = api.me()\n", 75 | "user.name" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 5, 81 | "metadata": {}, 82 | "outputs": [ 83 | { 84 | "name": "stdout", 85 | "output_type": "stream", 86 | "text": [ 87 | "2017-11-30 07:31:17 DONDERDAG LIVE: Vanaf 10.15 uur Kamerdebat begroting @ministerieJenV met beantwoording bewindslieden… https://t.co/zhVCxJWNAW\n", 88 | "2017-11-30 02:01:20 RT @chrisvfritz: PSA: The just-released @stylelint ^8.3.0 now supports <style> tags in .vue files out of the box, even with lang detection…\n" 89 | ] 90 | } 91 | ], 92 | "source": [ 93 | "public_tweets = api.home_timeline(count=2)\n", 94 | "for tweet in public_tweets:\n", 95 | " print(tweet.created_at, tweet.text)\n", 96 | " " 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 6, 102 | "metadata": {}, 103 | "outputs": [ 104 | { 105 | "data": { 106 | "text/html": [ 107 | "

PSA: The just-released @stylelint ^8.3.0 now supports <style> tags in .vue files out of the box, even with lang detection and --fix. Huge thanks to @gucong3000 and the stylelint team for making it happen!

— Chris Fritz (@chrisvfritz) November 29, 2017
\n", 108 | "\n" 109 | ], 110 | "text/plain": [ 111 | "" 112 | ] 113 | }, 114 | "execution_count": 6, 115 | "metadata": {}, 116 | "output_type": "execute_result" 117 | } 118 | ], 119 | "source": [ 120 | "# display a tweet inline\n", 121 | "IPython.display.HTML(api.get_oembed(id=tweet.id, hide_media=False)['html'])" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 7, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "name": "stdout", 131 | "output_type": "stream", 132 | "text": [ 133 | "2017-11-22 15:08:33 RT @mikihirano: 本日の夕暮れ。#シドニー #オーストラリア #SnapSydney #CoastSnapNarra https://t.co/6DlvCiGSj1\n", 134 | "2017-11-22 14:52:50 RT @mikihirano: #Narrabeen #beach #CoastSnapNarra #SnapSydney https://t.co/3o8f91HB72\n", 135 | "2017-11-22 14:23:58 RT @mikihirano: #Narrabeen #beach #CoastSnapNarra #SnapSydney https://t.co/3o8f91HB72\n", 136 | "2017-11-22 13:08:47 RT @mikihirano: #Narrabeen #beach #CoastSnapNarra #SnapSydney https://t.co/3o8f91HB72\n", 137 | "2017-11-22 12:52:45 RT @mikihirano: 本日の夕暮れ。#シドニー #オーストラリア #SnapSydney #CoastSnapNarra https://t.co/6DlvCiGSj1\n", 138 | "2017-11-22 11:50:49 本日の夕暮れ。#シドニー #オーストラリア #SnapSydney #CoastSnapNarra https://t.co/6DlvCiGSj1\n", 139 | "2017-11-22 10:44:53 RT @mikihirano: #Narrabeen #beach #CoastSnapNarra #SnapSydney https://t.co/3o8f91HB72\n", 140 | "2017-11-22 07:29:43 RT @mikihirano: #Narrabeen #beach #CoastSnapNarra #SnapSydney https://t.co/3o8f91HB72\n", 141 | "2017-11-22 07:01:10 #Narrabeen #beach #CoastSnapNarra #SnapSydney https://t.co/3o8f91HB72\n" 142 | ] 143 | } 144 | ], 145 | "source": [ 146 | "counter = itertools.count()\n", 147 | "tweets = api.search('#CoastSnapNarra', include_entities=True, count=100)\n", 148 | "for tweet in tweets:\n", 149 | " print(tweet.created_at, tweet.text)\n", 150 | " \n", 151 | " for entity in tweet.entities['media']:\n", 152 | " resp = requests.get(entity['media_url'])\n", 153 | " # download the image\n", 154 | " with open('img-%06d.jpg' % next(counter), 'wb') as f:\n", 155 | " f.write(resp.content)\n", 156 | " \n", 157 | " " 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": 12, 163 | "metadata": {}, 164 | "outputs": [ 165 | { 166 | "name": "stdout", 167 | "output_type": "stream", 168 | "text": [ 169 | "Pull out or get flooded 🤔 Ima flood ya baby girl 🍆💦💦🌊\n", 170 | "Aerial View Shows Colombian Town Flooded With Mud. Credit – Fuerza Aérea Colombiana via Storyful - https://t.co/gpRplXM7PW via @AUNewsToday\n" 171 | ] 172 | } 173 | ], 174 | "source": [ 175 | "# now let's start listening for events\n", 176 | "class PrintListener(tweepy.StreamListener):\n", 177 | " def on_status(self, status):\n", 178 | " print(status.text)\n", 179 | " \n", 180 | "print_listener = PrintListener()\n", 181 | "stream = Stream(api.auth, print_listener)\n", 182 | "stream.filter(track=['flooded'], async=True)" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": 13, 188 | "metadata": {}, 189 | "outputs": [], 190 | "source": [ 191 | "stream.disconnect()" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": null, 197 | "metadata": {}, 198 | "outputs": [], 199 | "source": [ 200 | "api." 201 | ] 202 | } 203 | ], 204 | "metadata": { 205 | "kernelspec": { 206 | "display_name": "Python 3", 207 | "language": "python", 208 | "name": "python3" 209 | }, 210 | "language_info": { 211 | "codemirror_mode": { 212 | "name": "ipython", 213 | "version": 3 214 | }, 215 | "file_extension": ".py", 216 | "mimetype": "text/x-python", 217 | "name": "python", 218 | "nbconvert_exporter": "python", 219 | "pygments_lexer": "ipython3", 220 | "version": "3.6.3" 221 | } 222 | }, 223 | "nbformat": 4, 224 | "nbformat_minor": 1 225 | } 226 | -------------------------------------------------------------------------------- /unstrucgridplot.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 16, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import netCDF4\n", 12 | "import matplotlib.collections\n", 13 | "import matplotlib.lines\n", 14 | "import matplotlib.pyplot as plt" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 17, 20 | "metadata": { 21 | "collapsed": false 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "filename = '/Users/fedorbaart/Documents/checkouts/cases_unstruc/e00_unstruc/f02_1D2D/c086_Index4/input/index4b_net.nc'\n", 26 | "filename = '/Users/baart_f/models/riomagdelena/DFM_OUTPUT_riomagp_q2600/riomagp_q2600_map.nc'" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 18, 32 | "metadata": { 33 | "collapsed": false 34 | }, 35 | "outputs": [], 36 | "source": [ 37 | "ds = netCDF4.Dataset(filename)\n", 38 | "X = ds.variables['NetNode_x'][:]\n", 39 | "Y = ds.variables['NetNode_y'][:]\n", 40 | "Z = ds.variables['NetNode_z'][:]\n", 41 | "netelemnode = ds.variables['NetElemNode'][:]\n", 42 | "netlink = ds.variables['NetLink'][:]\n", 43 | "ds.close()" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "This is an example of how to use the elemnode variable to connect the cells. " 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 19, 56 | "metadata": { 57 | "collapsed": false 58 | }, 59 | "outputs": [], 60 | "source": [ 61 | "# Create split locations\n", 62 | "if not hasattr(netelemnode, 'mask'):\n", 63 | " netelemnode = np.ma.masked_array(netelemnode, mask=False)\n", 64 | "splitidx = np.cumsum(np.r_[(~netelemnode.mask).sum(1)][:-1])\n", 65 | "# Convert to 1d filled idx\n", 66 | "idx = netelemnode[(~netelemnode.mask)]-1\n", 67 | "xpoly = np.split(X[idx],splitidx) # x vector per poly\n", 68 | "ypoly = np.split(Y[idx],splitidx)\n", 69 | "zcell = np.split(Z[idx],splitidx)\n", 70 | "zcellmean = np.array([z.mean() for z in zcell])\n", 71 | "polycoords = [np.c_[xy[0],xy[1]] for xy in np.c_[xpoly,ypoly]]\n" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": { 78 | "collapsed": false 79 | }, 80 | "outputs": [], 81 | "source": [] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 21, 86 | "metadata": { 87 | "collapsed": false 88 | }, 89 | "outputs": [ 90 | { 91 | "data": { 92 | "text/plain": [ 93 | "" 94 | ] 95 | }, 96 | "execution_count": 21, 97 | "metadata": {}, 98 | "output_type": "execute_result" 99 | }, 100 | { 101 | "data": { 102 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAETCAYAAADZHBoWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAF9RJREFUeJzt3X+MXWd95/H3hxhDSLJY3qycX0ax6CQbV+0SrMbZ8iPm\nR7OmavNDVROnUmRSFwm5/NC2gsRUu/E/aVP+KGRFk5W6QByETF1aLKOkwSYwohIiDuAQE8ckhhrF\ns3iS1XZJgaJNmu/+cZ85vhnsmbHneubezfsljfyc55znnO+x7Pu557nnnklVIUkSwCsWuwBJ0vAw\nFCRJHUNBktQxFCRJHUNBktQxFCRJnZEKhSS/m+TxJP+a5I0zbLc+ycEkTyW5da7jk7wuyU+S/PEc\n67kjyfeSHEjy/lM7K0kaHkMbCknWJfn0tO79wPXA12YYdwbwCWA9sBq4Kcllcxz/F8D9c6zvFuDC\nqrq0qlYDn5vLOEkaZksWu4AZ/MK36qrqIECSmcZdARyqqsNt288B1wJPzDQ+yXXAD4CfTuu/GtgK\nvAr4PnBLVf0UeC9wU19tz871xCRpWA3tlQIw4yv/DC4Enu5bPtL6Tnyg5Gzgw/Re/Pv7zwX+BHhH\nVa0BvgX8UVv9emBDkkeSPJDkl06xXkkaGkN3pZDkG/TelZ8NLE+yr626tap2z2EXp/Lcjq3Ax6rq\nZ3npZcSV9Kagvt66lwJfb+teBfxLVf1akuuBTwFvPYVjS9LQGLpQqKorAZJcBby7qm45yV1MACv7\nllfSu1qYyRXA7yT5KLAMeDHJz4EfAnuq6veOM+YI8HetvROY/vmHJI2cWaePklyaZF/fz4+TfCDJ\n8iR7kjyZZHeSZX1jtrQ7fw62Ofmp/jVJ9rd1d8126FNc/01gLMnFSZYCNwK7ZhpfVW+tqlVVtQr4\nOHBHVf0l8DDwpiSvb/WflWSsDdsJvL21rwK+N0u9kjT0Zg2FqvpeVV1eVZcDa4CfAV8AbqP3LvoS\n4KG2TJLV9F6IV9O7A+juvimZe4BNVTVG74V7/UyHZtpUUJLrkzxNb1rn/iR/3/ovSHJ/q/cF4H3A\nl4ADwF9X1RMzjZ/h3J8F3g1sT/IdelNHl7bVd9K7ungMuAP4g5n2JUmjICfz6Oz2rv+/VNVbkhwE\nrqqqySTnAeNV9e+TbAFerKo/b2MepDdn/0PgK1V1WevfAKyrqvcO9pQkSafqZO8+2gBsb+0VVTXZ\n2pPAita+gJfO4U/d/TO9f4JZ7gqSJC2sOYdCm5//beBvpq+r3uWGv61Hkkbcydx99C7gW31f0ppM\ncl5VHU1yPvBM659+989F9K4QJlq7v39i+kGSGC6SdJKq6lS/2/ULO5rTD73HOGzsW/4ove8OQO9D\n5jtbezXwKL17+lfR+xbw1GcXDwNr6d358wCw/jjHqbnWNGw/wNbFrsH6F78O6x+9n1GuvdVfg9rX\nnK4UkpwFvBN4T1/3ncCOJJuAw8ANrbIDSXbQu/PnBWBztaqBzcC9wJnAA1X14FyOL0laGHMKheo9\n6+fcaX3/m15QHG/7PwX+9Dj93wJ+5eTLlCQthGF+9tEoGl/sAuZpfLELmKfxxS5gnsYXu4B5Gl/s\nAuZhfLELGBYn9T2FhZCkalAfmEjSy8AgXze9UpAkdQwFSVLHUJAkdQwFSVLHUJAkdQwFSVLHUJAk\ndQwFSVLHUJAkdQwFSVLHUJAkdQwFSVLHUJAkdQwFSVLHUJAkdQwFSVLHUJAkdQwFSVLHUJAkdQwF\nSVLHUJAkdeYUCkmWJfl8kieSHEiyNsnyJHuSPJlkd5JlfdtvSfJUkoNJru7rX5Nkf1t31+k4IUnS\nqZvrlcJdwANVdRnwq8BB4DZgT1VdAjzUlkmyGrgRWA2sB+5Okrafe4BNVTUGjCVZP7AzkSTN26yh\nkOS1wFuq6lMAVfVCVf0YuAbY1jbbBlzX2tcC26vq+ao6DBwC1iY5Hzinqva27e7rGyNJGgJzuVJY\nBTyb5NNJvp3kr5KcBayoqsm2zSSworUvAI70jT8CXHic/onWL0kaEkvmuM0bgfdV1SNJPk6bKppS\nVZWkBlVUkq19i+NVNT6ofUvSqEuyDlh3OvY9l1A4Ahypqkfa8ueBLcDRJOdV1dE2NfRMWz8BrOwb\nf1Hbx0Rr9/dPHO+AVbV1zmcgSS8z7Y3y+NRyktsHte9Zp4+q6ijwdJJLWtc7gceBLwIbW99GYGdr\n7wI2JFmaZBUwBuxt+3mu3bkU4Oa+MZKkITCXKwWA9wOfTbIU+D5wC3AGsCPJJuAwcANAVR1IsgM4\nALwAbK6qqamlzcC9wJn07mZ6cEDnIUkagBx7vR4OSaqqMvuWkiQY7Oum32iWJHUMBUlSx1CQJHUM\nBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlS\nx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHXmFApJDid5LMm+JHtb3/Ike5I8mWR3kmV9\n229J8lSSg0mu7utfk2R/W3fX4E9HkjQfc71SKGBdVV1eVVe0vtuAPVV1CfBQWybJauBGYDWwHrg7\nSdqYe4BNVTUGjCVZP6DzkCQNwMlMH2Xa8jXAttbeBlzX2tcC26vq+ao6DBwC1iY5Hzinqva27e7r\nGyNJGgInc6Xw5STfTPKe1reiqiZbexJY0doXAEf6xh4BLjxO/0TrlyQNiSVz3O5NVfWjJP8O2JPk\nYP/KqqokNaiikmztWxyvqvFB7VuSRl2SdcC607HvOYVCVf2o/flski8AVwCTSc6rqqNtauiZtvkE\nsLJv+EX0rhAmWru/f+IEx9t6MichSS8n7Y3y+NRyktsHte9Zp4+SvCbJOa19FnA1sB/YBWxsm20E\ndrb2LmBDkqVJVgFjwN6qOgo8l2Rt++D55r4xkqQhMJcrhRXAF9oNREuAz1bV7iTfBHYk2QQcBm4A\nqKoDSXYAB4AXgM1VNTW1tBm4FzgTeKCqHhzguUiS5inHXq+HQ5Kqqul3OkmSTmCQr5t+o1mS1DEU\nJEkdQ0GS1DEUJEkdQ0GS1DEUJEkdQ0GS1DEUJEkdQ0GS1DEUJEkdQ0GS1DEUJEkdQ0GS1DEUJEkd\nQ0GS1DEUJEkdQ0GS1DEUJEkdQ0GS1DEUJEkdQ0GS1DEUJEkdQ0GS1JlTKCQ5I8m+JF9sy8uT7Eny\nZJLdSZb1bbslyVNJDia5uq9/TZL9bd1dgz8VSdJ8zfVK4YPAAaDa8m3Anqq6BHioLZNkNXAjsBpY\nD9ydJG3MPcCmqhoDxpKsH8wpSJIGZdZQSHIR8JvA/wCmXuCvAba19jbguta+FtheVc9X1WHgELA2\nyfnAOVW1t213X98YSdKQmMuVwseADwEv9vWtqKrJ1p4EVrT2BcCRvu2OABcep3+i9UuShsiSmVYm\n+S3gmaral2Td8bapqkpSx1t3qpJs7Vscr6rxQe5fkkZZez1edzr2PWMoAL8OXJPkN4FXA/8myWeA\nySTnVdXRNjX0TNt+AljZN/4ielcIE63d3z9xooNW1daTOgtJehlpb5THp5aT3D6ofc84fVRVH6mq\nlVW1CtgAfKWqbgZ2ARvbZhuBna29C9iQZGmSVcAYsLeqjgLPJVnbPni+uW+MJGlIzHalMN3UNNGd\nwI4km4DDwA0AVXUgyQ56dyq9AGyuqqkxm4F7gTOBB6rqwfmVLkkatBx7zR4OSaqqMvuWkiQY7Oum\n32iWJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQ\nJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHUMBUlSx1CQJHVmDIUkr07ycJJH\nkxxI8metf3mSPUmeTLI7ybK+MVuSPJXkYJKr+/rXJNnf1t11+k5JknSqZgyFqvo58LaqegPwq8Db\nkrwZuA3YU1WXAA+1ZZKsBm4EVgPrgbuTpO3uHmBTVY0BY0nWn44TkiSdulmnj6rqZ625FDgD+Cfg\nGmBb698GXNfa1wLbq+r5qjoMHALWJjkfOKeq9rbt7usbI0kaErOGQpJXJHkUmAS+WlWPAyuqarJt\nMgmsaO0LgCN9w48AFx6nf6L1S5KGyJLZNqiqF4E3JHkt8KUkb5u2vpLUIItKsrVvcbyqxge5f0ka\nZUnWAetOx75nDYUpVfXjJPcDa4DJJOdV1dE2NfRM22wCWNk37CJ6VwgTrd3fPzHDsbbOtS5Jerlp\nb5THp5aT3D6ofc9299G5U3cWJTkT+A1gH7AL2Ng22wjsbO1dwIYkS5OsAsaAvVV1FHguydr2wfPN\nfWMkSUNitiuF84FtSV5BL0A+U1UPJdkH7EiyCTgM3ABQVQeS7AAOAC8Am6tqamppM3AvcCbwQFU9\nOOiTkSTNT469Zg+HJFVVmX1LSRIM9nXTbzRLkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqG\ngiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSp\nYyhIkjqGgiSpYyhIkjqzhkKSlUm+muTxJN9N8oHWvzzJniRPJtmdZFnfmC1JnkpyMMnVff1rkuxv\n6+46PackSTpVc7lSeB74z1X1y8CVwB8muQy4DdhTVZcAD7VlkqwGbgRWA+uBu5Ok7eseYFNVjQFj\nSdYP9GwkSfMyayhU1dGqerS1fwI8AVwIXANsa5ttA65r7WuB7VX1fFUdBg4Ba5OcD5xTVXvbdvf1\njZEkDYGT+kwhycXA5cDDwIqqmmyrJoEVrX0BcKRv2BF6ITK9f6L1S5KGxJK5bpjkbOBvgQ9W1T8f\nmxGCqqokNaiikmztWxyvqvFB7VuSRl2SdcC607HvOYVCklfSC4TPVNXO1j2Z5LyqOtqmhp5p/RPA\nyr7hF9G7Qpho7f7+ieMdr6q2zvkMJOllpr1RHp9aTnL7oPY9l7uPAnwSOFBVH+9btQvY2NobgZ19\n/RuSLE2yChgD9lbVUeC5JGvbPm/uGyNJGgKpmnnWJ8mbga8BjwFTG28B9gI7gNcBh4Ebqur/tDEf\nAX4feIHedNOXWv8a4F7gTOCBqvrAcY5XVZXp/ZKk4xvk6+asobDQDAVJOjmDfN30G82SpI6hIEnq\nGAqSpI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqS\npI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpM6soZDkU0kmk+zv61ueZE+SJ5Ps\nTrKsb92WJE8lOZjk6r7+NUn2t3V3Df5UJEnzNZcrhU8D66f13QbsqapLgIfaMklWAzcCq9uYu5Ok\njbkH2FRVY8BYkun7lCQtsllDoar+Afinad3XANtaextwXWtfC2yvquer6jBwCFib5HzgnKra27a7\nr2+MJGlInOpnCiuqarK1J4EVrX0BcKRvuyPAhcfpn2j9kqQhsmS+O6iqSlKDKGZKkq19i+NVNT7I\n/UvSKEuyDlh3OvZ9qqEwmeS8qjrapoaeaf0TwMq+7S6id4Uw0dr9/RMn2nlVbT3FuiTp/3vtjfL4\n1HKS2we171OdPtoFbGztjcDOvv4NSZYmWQWMAXur6ijwXJK17YPnm/vGSJKGxKxXCkm2A1cB5yZ5\nGvivwJ3AjiSbgMPADQBVdSDJDuAA8AKwuaqmppY2A/cCZwIPVNWDgz0VSdJ85dhr9nBIUlWV2beU\nJMFgXzf9RrMkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMo\nSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6Cx4KSdYnOZjk\nqSS3LvTxJUkntqChkOQM4BPAemA1cFOSyxayhtMpybrFrmE+rH9xWf/iGeXaB22hrxSuAA5V1eGq\neh74HHDtAtdwOq1b7ALmad1iFzBP6xa7gHlat9gFzNO6xS5gHtYtdgHDYqFD4ULg6b7lI61PkjQE\n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\n", 103 | "text/plain": [ 104 | "" 105 | ] 106 | }, 107 | "metadata": {}, 108 | "output_type": "display_data" 109 | } 110 | ], 111 | "source": [ 112 | "fig, ax = plt.subplots(1,1)\n", 113 | "# Plot the cells as polygons\n", 114 | "polys = matplotlib.collections.PolyCollection(polycoords, linewidth=2, edgecolor=(0.5,0.5,0.5), cmap=matplotlib.cm.Accent)\n", 115 | "# Show the number of elements\n", 116 | "polys.set_array((~netelemnode.mask).sum(1))\n", 117 | "ax.add_collection(polys)\n", 118 | "ax.autoscale()\n", 119 | "# Add nodes manually so they don't scale... (could just use ax.plot)\n", 120 | "nodes = matplotlib.lines.Line2D(X, Y, marker='.', linestyle='none', markerfacecolor='black', markeredgecolor='none')\n", 121 | "ax.add_line(nodes)\n" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "This is an example of how to use the netlink variable to connect the links. " 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 23, 134 | "metadata": { 135 | "collapsed": false 136 | }, 137 | "outputs": [], 138 | "source": [ 139 | "# dimension n lines, start, stop\n", 140 | "linecoords = np.concatenate([X[netlink-1][...,np.newaxis], Y[netlink-1][...,np.newaxis]], axis=2)" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 24, 146 | "metadata": { 147 | "collapsed": false 148 | }, 149 | "outputs": [ 150 | { 151 | "data": { 152 | "image/png": "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\n", 153 | "text/plain": [ 154 | "" 155 | ] 156 | }, 157 | "metadata": {}, 158 | "output_type": "display_data" 159 | } 160 | ], 161 | "source": [ 162 | "fig, ax = plt.subplots(1,1, figsize=(10,6))\n", 163 | "# Black is the new purple\n", 164 | "ax.set_axis_bgcolor('black')\n", 165 | "\n", 166 | "# Regenerate the polycollection in a different color\n", 167 | "polys = matplotlib.collections.PolyCollection(polycoords, linewidth=0,cmap=matplotlib.cm.Pastel2)\n", 168 | "polys.set_array((~netelemnode.mask).sum(1))\n", 169 | "ax.add_collection(polys)\n", 170 | "\n", 171 | "# Now add the lines on top\n", 172 | "lines = matplotlib.collections.LineCollection(linecoords, linewidth=2, edgecolor=(0.1,0.5,0.8))\n", 173 | "ax.add_collection(lines)\n", 174 | "ax.autoscale()" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": { 181 | "collapsed": true 182 | }, 183 | "outputs": [], 184 | "source": [] 185 | } 186 | ], 187 | "metadata": { 188 | "kernelspec": { 189 | "display_name": "Python 2", 190 | "language": "python", 191 | "name": "python2" 192 | }, 193 | "language_info": { 194 | "codemirror_mode": { 195 | "name": "ipython", 196 | "version": 2 197 | }, 198 | "file_extension": ".py", 199 | "mimetype": "text/x-python", 200 | "name": "python", 201 | "nbconvert_exporter": "python", 202 | "pygments_lexer": "ipython2", 203 | "version": "2.7.10" 204 | } 205 | }, 206 | "nbformat": 4, 207 | "nbformat_minor": 0 208 | } 209 | -------------------------------------------------------------------------------- /viewshed-cost.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import ee\n", 10 | "ee.Initialize()\n", 11 | "ee.Authenticate()" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 4, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "# location of ship\n", 21 | "geometry = ee.Geometry.Point([4.1591602699991, 51.959397608499735])\n" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 5, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "# viewshed\n", 31 | "viewshed = ee.Image('users/fbaart/vaarwegen/viewshed')\n" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 6, 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "data": { 41 | "text/plain": [ 42 | "226" 43 | ] 44 | }, 45 | "execution_count": 6, 46 | "metadata": {}, 47 | "output_type": "execute_result" 48 | } 49 | ], 50 | "source": [ 51 | "# water of the harbor\n", 52 | "table = ee.FeatureCollection('users/fbaart/vaarwegen/water')\n", 53 | "table.size().getInfo()" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 7, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "# rasterize water geometries\n", 63 | "water = ee.Image().toByte().paint(table, 1)\n", 64 | "# source of the viewshed\n", 65 | "source = ee.Image().toByte().paint(geometry, 1, 10)\n", 66 | "# mask all other pixels\n", 67 | "source = source.updateMask(source)\n", 68 | "# compute distance from \n", 69 | "cumulativeCost = water.cumulativeCost(**{\n", 70 | " \"source\": source,\n", 71 | " \"maxDistance\": 10 * 1000 # 10 kilometers\n", 72 | "})\n" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 9, 78 | "metadata": {}, 79 | "outputs": [], 80 | "source": [ 81 | "# export to google drive\n", 82 | "task = ee.batch.Export.image.toDrive(\n", 83 | " image=cumulativeCost, # an ee.Image object.\n", 84 | " region=viewshed.geometry(),\n", 85 | " description='test-export',\n", 86 | " folder='ee-export',\n", 87 | " fileNamePrefix='viewshed-1',\n", 88 | " scale=10,\n", 89 | " crs='EPSG:4326'\n", 90 | ")" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 10, 96 | "metadata": {}, 97 | "outputs": [], 98 | "source": [ 99 | "task.start()" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": null, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [] 108 | } 109 | ], 110 | "metadata": { 111 | "kernelspec": { 112 | "display_name": "Python 3", 113 | "language": "python", 114 | "name": "python3" 115 | }, 116 | "language_info": { 117 | "codemirror_mode": { 118 | "name": "ipython", 119 | "version": 3 120 | }, 121 | "file_extension": ".py", 122 | "mimetype": "text/x-python", 123 | "name": "python", 124 | "nbconvert_exporter": "python", 125 | "pygments_lexer": "ipython3", 126 | "version": "3.8.5" 127 | } 128 | }, 129 | "nbformat": 4, 130 | "nbformat_minor": 4 131 | } 132 | -------------------------------------------------------------------------------- /visualizing_point_cloud_mayavi.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:bd1fb351343a9526a9979147a28e303466c3b5713251f934ceef22152c216cb8" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "heading", 13 | "level": 1, 14 | "metadata": {}, 15 | "source": [ 16 | "Visualizing point clouds with Mayavi" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "This notebook will cover the basics of visualizing point clouds with Mayavi. Mayavi is a python codeable interface for VTK, which offers the possibility to plot scientific data as well as point clouds." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "collapsed": false, 29 | "input": [ 30 | "import numpy as np\n", 31 | "import mayavi.mlab as mlab\n", 32 | "from tvtk.api import tvtk\n", 33 | "from mayavi.modules.glyph import Glyph\n", 34 | "from mayavi.tools.sources import MGlyphSource\n", 35 | "from mayavi.modules.surface import Surface\n", 36 | "from mayavi.filters.mask_points import MaskPoints" 37 | ], 38 | "language": "python", 39 | "metadata": {}, 40 | "outputs": [ 41 | { 42 | "output_type": "stream", 43 | "stream": "stderr", 44 | "text": [ 45 | "WARNING:traits.has_traits:DEPRECATED: traits.has_traits.wrapped_class, 'the 'implements' class advisor has been deprecated. Use the 'provides' class decorator.\n" 46 | ] 47 | } 48 | ], 49 | "prompt_number": 1 50 | }, 51 | { 52 | "cell_type": "heading", 53 | "level": 3, 54 | "metadata": {}, 55 | "source": [ 56 | "Plotting the point cloud" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "Plotting the point cloud can be done very easy by using the mlab.mplot3d() command. It is that way however not easy to change the colors and add different modules to the pipeline. So this pipeline is what we will build manually. A pipeline is, quoting wikipedias definition: \n", 64 | "\n", 65 | "In 3D computer graphics, the graphics pipeline or rendering pipeline refers to the sequence of steps used to create a 2D raster representation of a 3D scene.\n", 66 | "\n", 67 | "So this is what we will do. But first import the data and create a data source:" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "collapsed": false, 73 | "input": [ 74 | "xyz = np.load(r'D:\\rongen\\xyz_delft_center.npy', mmap_mode = 'r')\n", 75 | "rgb = np.load(r'D:\\rongen\\rgb_delft_center.npy', mmap_mode = 'r')\n", 76 | "\n", 77 | "def create_data_source():\n", 78 | " '''\n", 79 | " Function to create a data source readible by mayavi/vtk\n", 80 | " '''\n", 81 | " # Create the datasource\n", 82 | " data_source = MGlyphSource()\n", 83 | " # Add the x, y and z data to it\n", 84 | " data_source.reset(x = xyz[:, 0], y = xyz[:, 1], z = xyz[:, 2])\n", 85 | " # Add a vtk_data_source to the pipeline\n", 86 | " vtk_data_source = mlab.pipeline.add_dataset(data_source.dataset)\n", 87 | " # To be able to change the content of the datasource afterwards, we state the following:\n", 88 | " data_source.m_data = vtk_data_source\n", 89 | " return vtk_data_source\n", 90 | "vtk_data_source = create_data_source()" 91 | ], 92 | "language": "python", 93 | "metadata": {}, 94 | "outputs": [ 95 | { 96 | "output_type": "stream", 97 | "stream": "stderr", 98 | "text": [ 99 | "C:\\Users\\rongen\\AppData\\Local\\Continuum\\Anaconda\\lib\\site-packages\\traits\\has_traits.py:1536: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.\n", 100 | " setattr( self, name, value )\n" 101 | ] 102 | } 103 | ], 104 | "prompt_number": 2 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": {}, 109 | "source": [ 110 | "The window has poppud up already, but we still need to do some steps before we can see the point cloud.\n", 111 | "\n", 112 | "Add the colors:" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "collapsed": false, 118 | "input": [ 119 | "def add_colors(vtk_data_source):\n", 120 | " '''\n", 121 | " Function to add colors to data source\n", 122 | " Input : the data source which has to be colored\n", 123 | " '''\n", 124 | " # Create an array which vtk can read\n", 125 | " col = tvtk.UnsignedCharArray()\n", 126 | " # Set color data to it\n", 127 | " col.from_array(rgb)\n", 128 | " # Change the scalar (color) data of the dataset to the color array\n", 129 | " vtk_data_source.mlab_source.dataset.point_data.scalars=col\n", 130 | "\n", 131 | "add_colors(vtk_data_source)" 132 | ], 133 | "language": "python", 134 | "metadata": {}, 135 | "outputs": [], 136 | "prompt_number": 3 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "Now it is possible to add a mask to the pipeline. The mask will prevent some points from being rendered, which can come in handy when you do not want to show all points, to save for example memory. In our case, if you have sufficient memory (> 4 GB) you can probably plot all points and skip the mask. In that case you can add the glyph directly to the vtk_data_source (next step)" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "collapsed": false, 148 | "input": [ 149 | "# Create an engine to which filters can be added\n", 150 | "engine = mlab.get_engine()\n", 151 | "\n", 152 | "def create_mask(npoints = 100000):\n", 153 | " '''\n", 154 | " Function to create a mask\n", 155 | " Input : the number of points which are visible\n", 156 | " '''\n", 157 | " # Create the mask\n", 158 | " mask = MaskPoints()\n", 159 | " engine.add_filter(mask, vtk_data_source)\n", 160 | " mask.filter.random_mode = True\n", 161 | " mask.filter.maximum_number_of_points = npoints\n", 162 | " return mask\n", 163 | "mask = create_mask()" 164 | ], 165 | "language": "python", 166 | "metadata": {}, 167 | "outputs": [], 168 | "prompt_number": 4 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "And add a filter which contains information on how to visualize the points." 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "collapsed": false, 180 | "input": [ 181 | "# Create the glyph with which the point cloud actually gets points\n", 182 | "def create_glyph(add_to = 'mask'):\n", 183 | " '''\n", 184 | " Function to add glyphs to the data\n", 185 | " '''\n", 186 | " glyph = Glyph()\n", 187 | " if add_to == 'mask':\n", 188 | " engine.add_filter(glyph, mask)\n", 189 | " else:\n", 190 | " engine.add_filter(glyph, vtk_data_source)\n", 191 | " glyph.glyph.glyph_source.glyph_source.glyph_type = 'vertex'\n", 192 | "\n", 193 | "glyph = create_glyph()\n", 194 | "# Show the figure\n", 195 | "mlab.show()" 196 | ], 197 | "language": "python", 198 | "metadata": {}, 199 | "outputs": [], 200 | "prompt_number": 5 201 | }, 202 | { 203 | "cell_type": "heading", 204 | "level": 3, 205 | "metadata": {}, 206 | "source": [ 207 | "Improve navigation" 208 | ] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "metadata": {}, 213 | "source": [ 214 | "The point cloud looks fine, but the navigation is still a bit annoying. The camera is rolling, which we do not want in our case. Also the focal point is fixed, so we can only look at one point. Lets improve these things, starting with the rolling." 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "collapsed": false, 220 | "input": [ 221 | "#-------------------------------------------------------------------------------\n", 222 | "# Add a terrain interactor style, which does not roll. For this we use the tvtk\n", 223 | "# module which has vtk objects as traits.\n", 224 | "\n", 225 | "# The interactor style had to be inserted before the mask or glyph is added to \n", 226 | "# the pipeline, so we create the animation again below (Close it first)\n", 227 | "\n", 228 | "# Set the interactor to the new style\n", 229 | "def change_interaction():\n", 230 | " '''\n", 231 | " Function to change the interaction style\n", 232 | " '''\n", 233 | " istyle = tvtk.InteractorStyleTerrain()\n", 234 | " iactor = fig.scene.interactor\n", 235 | " iactor.interactor_style = istyle\n", 236 | "\n", 237 | "# figure\n", 238 | "fig = mlab.gcf()\n", 239 | "\n", 240 | "# data_source\n", 241 | "vtk_data_source = create_data_source()\n", 242 | "add_colors(vtk_data_source)\n", 243 | "\n", 244 | "# interactorstyle\n", 245 | "change_interaction()\n", 246 | "\n", 247 | "# engine, mask and glyph\n", 248 | "engine = mlab.get_engine()\n", 249 | "mask = create_mask(200000)\n", 250 | "glyph = create_glyph()\n", 251 | "\n", 252 | "# show\n", 253 | "mlab.show()" 254 | ], 255 | "language": "python", 256 | "metadata": {}, 257 | "outputs": [], 258 | "prompt_number": 6 259 | }, 260 | { 261 | "cell_type": "markdown", 262 | "metadata": {}, 263 | "source": [ 264 | "The camera stopped rolling, but the zoom by scroll function has been disabled for some reason.. Let's build that one ourselves, while we our builing in key press event for moving around." 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "collapsed": false, 270 | "input": [ 271 | "# We will have to add observers for key press events and mouse wheel events.\n", 272 | "# Change the interaction function and add observers\n", 273 | "\n", 274 | "def change_interaction():\n", 275 | " '''\n", 276 | " Function to change the interaction style and adds observers\n", 277 | " '''\n", 278 | " istyle = tvtk.InteractorStyleTerrain()\n", 279 | " iactor = fig.scene.interactor\n", 280 | " iactor.interactor_style = istyle\n", 281 | " istyle.add_observer('KeyPressEvent', Callback)\n", 282 | " istyle.add_observer('MouseWheelBackwardEvent', Callback)\n", 283 | " istyle.add_observer('MouseWheelForwardEvent', Callback)\n", 284 | "\n", 285 | "# A callback function is needed to handle the events. The abbsorvers give two\n", 286 | "# arguments to the callback function: the object, with all the event traits\n", 287 | "# and the eventname itself, which is just a string.\n", 288 | "\n", 289 | "def Callback(obj, event):\n", 290 | " '''\n", 291 | " Callback function, handels the interaction events\n", 292 | " '''\n", 293 | " # Get the geometric properties (azimuth, elevation, distance, focal point)\n", 294 | " # This van easily be done be calling mlav.view() without arguments.\n", 295 | " # mlab.move() without argument gives the camera position and the focal point\n", 296 | " azm, elev, dist, fp = mlab.view()\n", 297 | " cam, fp = mlab.move()\n", 298 | " # Set the height of the focal point to 2.5 m.\n", 299 | " fp[2] = 2.5\n", 300 | " # Convert to radians\n", 301 | " azm = azm * 2 * np.pi / 360.\n", 302 | " \n", 303 | " # To move the camera we will use the numpad keys.\n", 304 | " if event == 'KeyPressEvent':\n", 305 | " # Get the pressed key\n", 306 | " key = obj.GetInteractor().GetKeyCode()\n", 307 | " \n", 308 | " # Let the moved distance be determined by the hieght of the camera (cam[2])\n", 309 | " step = cam[2]/50.+1\n", 310 | " \n", 311 | " if key == '8':\n", 312 | " mlab.view(focalpoint = fp + [-step*np.cos(azm),-step*np.sin(azm), 0], distance = dist)\n", 313 | " if key == '4':\n", 314 | " mlab.view(focalpoint = fp + [ step*np.sin(azm),-step*np.cos(azm), 0], distance = dist)\n", 315 | " if key == '5':\n", 316 | " mlab.view(focalpoint = fp + [ step*np.cos(azm), step*np.sin(azm), 0], distance = dist)\n", 317 | " if key == '6':\n", 318 | " mlab.view(focalpoint = fp + [-step*np.sin(azm), step*np.cos(azm), 0], distance = dist)\n", 319 | " \n", 320 | " # Make our own zoom function\n", 321 | " if event == 'MouseWheelForwardEvent':\n", 322 | " dist *= 0.9\n", 323 | " mlab.view(focalpoint = fp, distance = dist)\n", 324 | " if event == 'MouseWheelBackwardEvent':\n", 325 | " dist *= 1.111\n", 326 | " mlab.view(focalpoint = fp, distance = dist)" 327 | ], 328 | "language": "python", 329 | "metadata": {}, 330 | "outputs": [], 331 | "prompt_number": 7 332 | }, 333 | { 334 | "cell_type": "code", 335 | "collapsed": false, 336 | "input": [ 337 | "fig = mlab.gcf()\n", 338 | "vtk_data_source = create_data_source()\n", 339 | "add_colors(vtk_data_source)\n", 340 | "change_interaction()\n", 341 | "engine = mlab.get_engine()\n", 342 | "mask = create_mask(1000000)\n", 343 | "glyph = create_glyph()\n", 344 | "mlab.show()" 345 | ], 346 | "language": "python", 347 | "metadata": {}, 348 | "outputs": [], 349 | "prompt_number": 8 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": {}, 354 | "source": [ 355 | "That works fine! So we now have a detailed point cloud, which interacts fine." 356 | ] 357 | }, 358 | { 359 | "cell_type": "heading", 360 | "level": 2, 361 | "metadata": {}, 362 | "source": [ 363 | "Making a movie" 364 | ] 365 | }, 366 | { 367 | "cell_type": "markdown", 368 | "metadata": {}, 369 | "source": [ 370 | "Next thing we are going to do is create a sequence of png snapshots, which we can compile to a movie. We will add another key to our interaction function, which will rotate the camera and take a snapshot." 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "collapsed": false, 376 | "input": [ 377 | "import time\n", 378 | "\n", 379 | "def Callback(obj, event):\n", 380 | " '''\n", 381 | " Callback function, handels the interaction events\n", 382 | " '''\n", 383 | " # Get the geometric properties (azimuth, elevation, distance, focal point)\n", 384 | " # This van easily be done be calling mlav.view() without arguments.\n", 385 | " # mlab.move() without argument gives the camera position and the focal point\n", 386 | " azm, elev, dist, fp = mlab.view()\n", 387 | " cam, fp = mlab.move()\n", 388 | " # Set the height of the focal point to 2.5 m.\n", 389 | " fp[2] = 2.5\n", 390 | " # Convert to radians\n", 391 | " azm = azm * 2 * np.pi / 360.\n", 392 | " \n", 393 | " # To move the camera we will use the numpad keys.\n", 394 | " if event == 'KeyPressEvent':\n", 395 | " # Get the pressed key\n", 396 | " key = obj.GetInteractor().GetKeyCode()\n", 397 | " \n", 398 | " # Let the moved distance be determined by the hieght of the camera (cam[2])\n", 399 | " step = cam[2]/50.+1\n", 400 | " \n", 401 | " if key == '8':\n", 402 | " mlab.view(focalpoint = fp + [-step*np.cos(azm),-step*np.sin(azm), 0], distance = dist)\n", 403 | " if key == '4':\n", 404 | " mlab.view(focalpoint = fp + [ step*np.sin(azm),-step*np.cos(azm), 0], distance = dist)\n", 405 | " if key == '5':\n", 406 | " mlab.view(focalpoint = fp + [ step*np.cos(azm), step*np.sin(azm), 0], distance = dist)\n", 407 | " if key == '6':\n", 408 | " mlab.view(focalpoint = fp + [-step*np.sin(azm), step*np.cos(azm), 0], distance = dist)\n", 409 | " \n", 410 | " # Make a Movie\n", 411 | " if key == 'm':\n", 412 | " # Enable off screen rendering, which shortens the time to create snapshots greatly\n", 413 | " engine.current_scene.scene.off_screen_rendering = True\n", 414 | " # Loop through different azimuths (rotations)\n", 415 | " i = 0\n", 416 | " for azimuth in range(0,360,30):\n", 417 | " # Set the view:\n", 418 | " mlab.view(azimuth = azimuth, elevation = 75, distance = 500, focalpoint = np.array([84465, 447547, 2.5]))\n", 419 | " # Save the scene\n", 420 | " engine.scenes[0].scene.save(r'D:\\rongen\\snapshot{:03d}.png'.format(i))\n", 421 | " i += 1\n", 422 | " # Pause for a second, to avoid break downs\n", 423 | " time.sleep(1)\n", 424 | " # Disable off screen rendering again\n", 425 | " engine.current_scene.scene.off_screen_rendering = False\n", 426 | " \n", 427 | " # Make our own zoom function\n", 428 | " if event == 'MouseWheelForwardEvent':\n", 429 | " dist *= 0.9\n", 430 | " mlab.view(focalpoint = fp, distance = dist)\n", 431 | " if event == 'MouseWheelBackwardEvent':\n", 432 | " dist *= 1.111\n", 433 | " mlab.view(focalpoint = fp, distance = dist)" 434 | ], 435 | "language": "python", 436 | "metadata": {}, 437 | "outputs": [], 438 | "prompt_number": 15 439 | }, 440 | { 441 | "cell_type": "markdown", 442 | "metadata": {}, 443 | "source": [ 444 | "Pressing m will create a sequence of snapshots from different angles now. These snapshots will have to be combined with a movie maker program or ffmpeg or whatever you like." 445 | ] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "collapsed": false, 450 | "input": [ 451 | "fig = mlab.gcf()\n", 452 | "vtk_data_source = create_data_source()\n", 453 | "add_colors(vtk_data_source)\n", 454 | "change_interaction()\n", 455 | "engine = mlab.get_engine()\n", 456 | "mask = create_mask(100000)\n", 457 | "glyph = create_glyph()\n", 458 | "mlab.show()" 459 | ], 460 | "language": "python", 461 | "metadata": {}, 462 | "outputs": [], 463 | "prompt_number": 16 464 | }, 465 | { 466 | "cell_type": "heading", 467 | "level": 3, 468 | "metadata": {}, 469 | "source": [ 470 | "Adding model data" 471 | ] 472 | }, 473 | { 474 | "cell_type": "markdown", 475 | "metadata": {}, 476 | "source": [ 477 | "A way to add modeldata in Mayavi, is to create a tvtk unstructured grid, and add the data to it. The next section will explain how to do this.\n", 478 | "\n", 479 | "Note that a lot of data files have a different are build up differently. It is therefor hard to write a script which is applicable for all grids. The next cell will therefore not work, but should be applied to your specific dataset." 480 | ] 481 | }, 482 | { 483 | "cell_type": "code", 484 | "collapsed": false, 485 | "input": [ 486 | "# The trick to make an tvtk.Unstructuredgrid is to make an administration of the\n", 487 | "# cells in the grid. Per cell should be known which grid points surround the\n", 488 | "# cell. An index of each node per cell is needed.\n", 489 | "\n", 490 | "# Let's say we have a netcdf file with the following data:\n", 491 | "xnode = dataset.variables['FlowElemContour_x'][:] # (N,4)-array with the x-coordinates of the cell corners\n", 492 | "ynode = dataset.variables['FlowElemContour_y'][:] # (N,4)-array with the y-coordinates of the cell corners\n", 493 | "\n", 494 | "xcc = dataset.variables['FlowElem_xcc'][:] # (N,1)-array with the x-coordinates of the cell centers\n", 495 | "ycc = dataset.variables['FlowElem_ycc'][:] # (N,1)-array with the x-coordinates of the cell centers\n", 496 | "\n", 497 | "# First we need to create an array with points.\n", 498 | "points = np.c_[xnode.ravel(), ynode.ravel()]\n", 499 | "\n", 500 | "# We only need every point once, so sort out the unqie points:\n", 501 | "b = np.ascontiguousarray(points).view(np.dtype((np.void, points.dtype.itemsize * points.shape[1])))\n", 502 | "_, idx = np.unique(b, return_index=True)\n", 503 | "unique_points = points[idx]\n", 504 | "\n", 505 | "# For some reason creating a tvtk.UnstructuredGrid goes wrong when point 0 is\n", 506 | "# requested. Therefore we add a dummy point, which will not be requested\n", 507 | "unique_points = np.vstack((unique_points[0,:]+0.5, unique_points))\n", 508 | "\n", 509 | "# Write a function to check where a point is in the unique_points array\n", 510 | "def checkwhere(elm):\n", 511 | " c1 = np.where(elm[0] == unique_points[:,0])[0]\n", 512 | " c2 = np.where(elm[1] == unique_points[:,1])[0]\n", 513 | " return np.intersect1d(c1, c2)[0]\n", 514 | "\n", 515 | "# Create the indices of the cell corners for each cell\n", 516 | "indices = np.array([checkwhere(i) for i in np.c_[xnode.ravel(), ynode.ravel()]])\n", 517 | "indices = indices.reshape((len(indices)/4,4))\n", 518 | "\n", 519 | "# Number of cells\n", 520 | "n_cells = int(indices.shape[0])\n", 521 | "\n", 522 | "# Array with number of nodes per cell\n", 523 | "elemtype = np.sum(indices > 0, 1)\n", 524 | "\n", 525 | "# Array with cell types, these depend on the number of nodes per cell.\n", 526 | "# if these are not four per cell, script something to get the right cell\n", 527 | "# type for each quantity of nodes\n", 528 | "cell_types = np.ones(len(elemtype))*tvtk.Quad().cell_type\n", 529 | "\n", 530 | "# Array with number of nodes per cell, and index of nodes\n", 531 | "cells = np.c_[elemtype, indices].ravel()\n", 532 | "\n", 533 | "# Array with offset, needed to read out cells\n", 534 | "offsets = np.r_[[0], np.cumsum(elemtype + 1)]\n", 535 | "\n", 536 | "# Convert cells to tvtk CellArray\n", 537 | "cell_array = tvtk.CellArray()\n", 538 | "cell_array.set_cells(n_cells, cells)\n", 539 | "\n", 540 | "# Create the grid\n", 541 | "grid = tvtk.UnstructuredGrid(points = unique_points)\n", 542 | "grid.set_cells(cell_types, offsets, cell_array)\n", 543 | "\n", 544 | "# Now scalar values can be set to the cell centers or cell npoints (nodes)\n", 545 | "# If you have cell data available you might need to interpolate to \n", 546 | "# point data, or vice versa\n", 547 | "grid.point_data.scalars = your_point_data\n", 548 | "grid.point_data.scalars.name = 'my_data'\n", 549 | "grid.cell_data.scalars = your_point_data\n", 550 | "grid.cell_data.scalars.name = 'my_data'\n", 551 | "\n", 552 | "# Save the grid to an xml file\n", 553 | "w = tvtk.XMLUnstructuredGridWriter(input = grid, file_name = 'my_grid.xml')\n", 554 | "w.write()" 555 | ], 556 | "language": "python", 557 | "metadata": {}, 558 | "outputs": [], 559 | "prompt_number": 3 560 | }, 561 | { 562 | "cell_type": "markdown", 563 | "metadata": {}, 564 | "source": [ 565 | "When you have a grid created or saved, you can add it to Mayavi as follows:" 566 | ] 567 | }, 568 | { 569 | "cell_type": "code", 570 | "collapsed": false, 571 | "input": [ 572 | "# Load the grid data if it is not stored in memory\n", 573 | "read = tvtk.XMLUnstructuredGridReader(file_name = 'path\\to\\xml\\file.xml')\n", 574 | "grid = read.get_output()\n", 575 | "\n", 576 | "# Show the grid:\n", 577 | "fig = mlab.gcf()\n", 578 | "engine = mlab.get_engine()\n", 579 | "mlab.pipeline.add_dataset(grid)\n", 580 | "engine.add_module(Surface())\n", 581 | "mlab.show()" 582 | ], 583 | "language": "python", 584 | "metadata": {}, 585 | "outputs": [], 586 | "prompt_number": 18 587 | }, 588 | { 589 | "cell_type": "markdown", 590 | "metadata": {}, 591 | "source": [ 592 | "In Mayavi, a lot of properties can be changed for the appearance of your grid. This can be done by clicking the Mayavi icon, which opens the pipeline. A pro tip is to click the recording button. The code of the changes yo do after clicking the recording button will be shown in the recording window. This makes it easy to find out how to change certain properties of your grids in your script directly." 593 | ] 594 | } 595 | ], 596 | "metadata": {} 597 | } 598 | ] 599 | } --------------------------------------------------------------------------------