diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9d73acd --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# ignore big data formats as +*.tif +*.tiff +*.nc +*.hdf +*.sa +*.pfb +*.pfsol +*.gdb +*.zip +*.tar + +# ignore shape files +*.shp +*.cpg +*.dbf +*.prj +*.shx + +# ignore images +*.png +*.jpeg +*.pdf + +# ignore swap files +*.swp + +# ignore error / log files +*.log +*.LOG +*err.* +*out.* +**/nohup.out + +# ignore compiled files +*.pyc +*.so + +# ignore MANIFEST +*MANIFEST* diff --git a/README.md b/README.md index 7d8d5d7..daae78b 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,13 @@ The generator incorporates steps from [the TSMP1 static file generator](https:// Instead of including raw input data in this repository, the repo is instead kept small. The static-files input data can be found [here](https://icg4geo.icg.kfa-juelich.de/ExternalReposPublic/tsmp2-static-files/grids_parflow_cordex-eur-11u). +We depend on the [SLOTH helper scripts](https://hpscterrsys.github.io/SLOTH/README.html), which can be installed through + +``` +cd $HOME/.local/share/ +git clone --recurse-submodules https://github.com/HPSCTerrSys/SLOTH.git +``` + If you are running this generator on a [JSC](https://www.fz-juelich.de/en/ias/jsc) machine, sourcing the provided environment file ``` @@ -14,6 +21,7 @@ source jsc.2025.gnu.psmpi makes the necessary utilities and libraries available. Otherwise you have to make sure that the respective software is installed or made available on your system. +On OpenBSD you need the packages `curl cmake eccodes gcc hdf5 ncview netcdf openmpi py3-{gdal,geopandas,h5py,matplotlib,netcdf4,scipy,xarray} tcl-8.6`. To create all static files needed to run ParFlow, you first need to download static input files: @@ -40,24 +48,110 @@ However, this classification process introduces some artifacts along the coastli To address these artifacts, we run an optimization loop that checks if lake pixels are neighbors of sea pixels. If they are, we treat them as sea pixels as well, ensuring a more accurate representation of the coastline. -It is important to note that COSMO also uses the `FR_LAND` variable as a land-sea mask with also a threshold of 0.5. +It is important to note that COSMO and ICON also use the `FR_LAND` variable as a land-sea mask with also a threshold of 0.5. This ensures that all components of TSMP share the same land-sea mask. Furthermore, special treatment is required due to the coarse horizontal resolution of our target grid. Some topographic formations, like the Bosporus connecting the Black Sea and the Mediterranean Sea, cannot be adequately resolved. -To address this, we modify the original `FR_LAND` variable by setting the value to 0, based on a predefined shape-files containing the coordinates of the Bosporus break through, effectively designating those areas as total water pixels. +To address this, we modify the original `FR_LAND` variable by setting the value to 0, based on a predefined shape-files containing the coordinates of the Bosporus breakthrough, effectively designating those areas as total water pixels. Above steps are performed by two scripts located in this directory: ``` cd mklandmask/ +pip3 install geopandas python3 Breakthrough-Bosporus.py python3 make_land_lake_sea_mask.py ``` ## Creation of the flow direction and slopes -## Creation of the mask solids mask +Using DEMs straight forward to calculate slopes for ParFlow could lead to smaller or bigger problems in river corridor placement. +In particular for coarse spatial resolutions this is easy to imagine as tight canyons are smoothed out. +For example a 12km resolution as for the EU11 domain does not see the breakthrough valley [`irongate` for donau river](https://de.wikipedia.org/wiki/Eisernes_Tor) leading to the result, that the donau is flowing around the related mountain range. +A further example are the Netherlands, where major parts of the land area are below sea level and rivers do not follow the ‘natural’ river-corridor but are forced to follow artificial canals. +To fix those and other issues / problems the real river-corridors are ‘burned’ to the DEM within this approach. + +Burning the correct river corridors is achieved in two steps: + +1) `burnShape2Topo.py` +The correct river positions are mapped to the target grid (in this case hydroSHEDS data were used) and then river pixels (and neighboring ones) are pushed down within the DEM. + +2) `modTopo.py` +Some pixels do need extra treatment, as for example the Elbe river in this setup. +Those need manual adjustment and are corrected ‘pixel-by-pixel’. + +The Python package *priority\_flow* is used to calculate flow direction and main river streams based on the burned DEM. +There are several other tools available, a couple of them also doing D4 slopes. +ParFlow author Reed Maxwell [recommended](https://github.com/parflow/parflow/issues/696#issuecomment-3920959452) to use [PriorityFlow](https://github.com/lecondon/PriorityFlow), which was since ported to Python as [priority\_flow](https://github.com/hydroframe/priority_flow), which we will use here. + +#### Usage +First extract and adjust the HydroSHEDS river data: + +``` +cd ../mkslopes +wget https://data.hydrosheds.org/file/HydroRIVERS/HydroRIVERS_v10_eu_shp.zip +wget https://data.hydrosheds.org/file/HydroRIVERS/HydroRIVERS_v10_af_shp.zip +unzip -u HydroRIVERS_v10_eu_shp.zip +unzip -u HydroRIVERS_v10_af_shp.zip +./burnShape2Topo.py +./modTopo.py +``` + +#### Optional / to be tested / unsure whether pysheds is needed +To keep the correct slope values, those are calculated based on the original DEM, but the flow direction, represented by the sign of the slope value, is taken from flow direction calculated by pysheds. +This way the slope values are in line with the origin DEM, but flow direction is according to the correct river-corridors. + +We use [pysheds](https://mattbartos.com/pysheds/) for pit filling, flooding depressions and resolving flats. +We use [PriorityFlow](https://github.com/lecondon/PriorityFlow) to calculate the D4 slopes. +The following script will install and run pysheds and PriorityFlow: + +``` +./create_pfl_slopes +``` + +pysheds uses XArray as an internal format and reads and writes to disk in GeoTIFF format. +We wrap around that by converting between netCDF and GeoTIFF. + +#### Usage of priority\_flow for calculating slopes + +``` +mkdir data +pip3 install priority_flow +./create_pfl_slopes.py +``` + +**N.B. Even though this can create D4 slopes, they are untested and may not be useful with ParFlow. +Further development and testing of the slopes generation is needed. +If you want to run TSPM2 with ParFlow, you may create the land mask, solids and textures with this generator, but for slopes it is probably best to rely on +[the existing slopes](https://gitlab.jsc.fz-juelich.de/detect/detect_z03_z04/constant_fields/TSMP_EUR-11/-/tree/main/static/parflow).** + +## Creation of the mask and solids files + +ParFlow requires a "solid file" to distinguish between active and inactive cells in the simulation. +In this case, active cells represent land areas, while inactive cells represent ocean areas. +To generate this solid file, we use the land-sea mask that was previously created. + +However, it is important to note that we want to preserve lakes in the simulation, as rivers should not disappear when they flow into a lake. +Therefore, the solid file is created based solely on the presence or absence of ocean areas, without masking out the lakes. + +The purpose of the solid file is to inform ParFlow that ocean areas should be treated as inactive cells, meaning they are not considered for computation. +On the other hand, land areas (including lakes) should be treated as active cells, allowing for proper simulation of water flow and interactions. + +#### Usage + +Set `PARFLOW_DIR` to your ParFlow installation prefix (the directory that contains ParFlow's `bin`, `lib` and such). +In the mask and solid files creation below, we exemplified this by assuming you are using the TSMP2 framework on JURECA: + +``` +cd ../mksolids +./createPfbMask.py +export PARFLOW_DIR="$TSMP2_DIR/bin/JURECADC_ParFlow" # modify to install prefix +$PARFLOW_DIR/bin/pfmask-to-pfsol --z-top 30 --z-bottom 0 --mask PfbMask4SolidFile.pfb --pfsol PfbMask4SolidFile.pfsol >PfbMask4SolidFile.log +``` + +You have to choose the value for `--z-top` according to `ComputationalGrid.DZ * ComputationalGrid.NZ`. +In the case of EUR-11 this comes down to $$z_\textrm{bottom} = 2 \cdot 15$$. ## Creation of the texture indicator diff --git a/mkslopes/BurnRiversAndCanyons_Vertices_EUR11.csv b/mkslopes/BurnRiversAndCanyons_Vertices_EUR11.csv new file mode 100644 index 0000000..870c0a4 --- /dev/null +++ b/mkslopes/BurnRiversAndCanyons_Vertices_EUR11.csv @@ -0,0 +1,1370 @@ +id,vertex_index,X,Y +"1","0",28.9761210258684,40.9353080511392 +"1","1",28.9773932226736,40.9414145958042 +"1","2",28.9786654194788,40.9444678681367 +"1","3",28.979937616284,40.9475211404692 +"1","4",28.9824820098944,40.9528643670511 +"1","5",28.9840086460607,40.9574442755499 +"1","6",28.986044160949,40.9622786234097 +"1","7",28.9880796758374,40.9666040925474 +"1","8",28.9896063120036,40.9724561978514 +"1","9",28.9921507056141,40.9805982574047 +"1","10",28.9934229024193,40.9846692871814 +"1","11",28.9949495385855,40.9897580744022 +"1","12",28.9952039779466,40.9956101797062 +"1","13",28.9954584173076,41.0045155573427 +"1","14",28.9959672960297,41.0111309807298 +"1","15",28.9964761747518,41.0180008434779 +"1","16",28.998002810918,41.0230896306988 +"1","17",29.0000383258064,41.0276695391975 +"1","18",29.0036004768609,41.0317405689742 +"1","19",29.0063993098324,41.0335216445015 +"1","20",29.0079259459987,41.0340305232236 +"1","21",29.0117425364143,41.0358115987509 +"1","22",29.0150502481078,41.0375926742782 +"1","23",29.0188668385235,41.0391193104444 +"1","24",29.0254822619106,41.0419181434159 +"1","25",29.0272633374379,41.042427022138 +"1","26",29.0308254884925,41.0436992189432 +"1","27",29.0359142757133,41.0459891731926 +"1","28",29.0397308661289,41.0480246880809 +"1","29",29.0417663810173,41.0495513242471 +"1","30",29.0450740927108,41.0528590359407 +"1","31",29.046091850155,41.0564211869953 +"1","32",29.0481273650433,41.0627821710213 +"1","33",29.0493995618485,41.0660898827149 +"1","34",29.0511806373758,41.0699064731305 +"1","35",29.05219839482,41.0732141848241 +"1","36",29.0547427884304,41.0770307752397 +"1","37",29.0575416214019,41.0798296082112 +"1","38",29.0590682575681,41.0813562443774 +"1","39",29.0598315756513,41.0823740018216 +"1","40",29.0600860150123,41.0841550773489 +"1","41",29.0611037724565,41.0887349858476 +"1","42",29.0613582118175,41.0905160613749 +"1","43",29.0618670905396,41.0981492422062 +"1","44",29.0621215299007,41.1060368623985 +"1","45",29.0636481660669,41.1093445740921 +"1","46",29.0669558777605,41.1126522857856 +"1","47",29.0722991043423,41.1159599974792 +"1","48",29.0771334522021,41.1195221485337 +"1","49",29.0796778458126,41.1218121027831 +"1","50",29.0812044819788,41.1235931783104 +"1","51",29.0814589213399,41.1261375719209 +"1","52",29.0776423309242,41.1317352378638 +"1","53",29.0750979373138,41.1335163133911 +"1","54",29.0725535437034,41.1363151463625 +"1","55",29.0697547107319,41.139368418695 +"1","56",29.0682280745657,41.1416583729444 +"1","57",29.0667014383994,41.1457294027211 +"1","58",29.0646659235111,41.1482737963315 +"1","59",29.0633937267059,41.1500548718588 +"1","60",29.0618670905396,41.1515815080251 +"1","61",29.0590682575681,41.1548892197186 +"1","62",29.0588138182071,41.157433613329 +"1","63",29.0631392873448,41.163285718633 +"1","64",29.0654292415942,41.1658301122434 +"1","65",29.0679736352046,41.1676111877707 +"1","66",29.0730624224255,41.1716822175474 +"1","67",29.0756068160359,41.1732088537137 +"1","68",29.0819678000619,41.1798242771007 +"1","69",29.088074344727,41.1849130643216 +"1","70",29.0921453745036,41.187457457932 +"1","71",29.0951986468361,41.1900018515424 +"1","72",29.0992696766128,41.193309563236 +"1","73",29.1035951457505,41.1953450781243 +"1","74",29.1076661755272,41.1976350323737 +"1","75",29.1119916446649,41.2017060621504 +"1","76",29.1152993563585,41.2047593344829 +"1","77",29.1178437499689,41.2080670461764 +"1","78",29.1234414159118,41.2154457876467 +"1","79",29.1270035669664,41.2200256961454 +"1","80",29.1323467935483,41.2279133163377 +"1","81",29.1354000658808,41.2335109822806 +"1","82",29.1415066105458,41.241398602473 +"1","83",29.142778807351,41.2431796780003 +"1","84",29.1443054435173,41.2449607535276 +"1","85",29.148376473294,41.2528483737199 +"1","86",29.1519386243485,41.2571738428576 +"1","87",29.1555007754031,41.2614993119953 +"1","88",29.1572818509304,41.2648070236888 +"5","0",27.9493843917162,40.7678714985037 +"5","1",27.9431425178787,40.7693401747008 +"5","2",27.9354319678441,40.7715431889964 +"5","3",27.9284557559081,40.7730118651935 +"5","4",27.9203780368242,40.7744805413905 +"5","5",27.9108316415433,40.7752148794891 +"5","6",27.9001837391146,40.7759492175876 +"5","7",27.8917388509815,40.7770507247354 +"5","8",27.8792551033064,40.7785194009325 +"5","9",27.8697087080255,40.7810895842773 +"5","10",27.8605294817939,40.7836597676222 +"5","11",27.8546547770056,40.78476127477 +"5","12",27.8447412126754,40.7854956128685 +"5","13",27.8311559578526,40.7865971200163 +"5","14",27.8150005196849,40.7899016414597 +"5","15",27.8080243077488,40.790268810509 +"5","16",27.7962748981723,40.790268810509 +"5","17",27.7881971790885,40.7913703176568 +"5","18",27.777916445709,40.791737486706 +"5","19",27.7687372194774,40.7921046557553 +"5","20",27.7588236551472,40.791737486706 +"5","21",27.7485429217678,40.7913703176568 +"5","22",27.7371606812405,40.790268810509 +"5","23",27.7276142859596,40.7895344724104 +"5","24",27.7232082573684,40.7888001343119 +"5","25",27.714396200186,40.7880657962134 +"5","26",27.6971392548705,40.7865971200163 +"5","27",27.6831868309984,40.78476127477 +"5","28",27.6758434500131,40.7843941057207 +"5","29",27.6655627166337,40.7832925985729 +"5","30",27.6582193356484,40.7836597676222 +"5","31",27.6446340808255,40.780722415228 +"5","32",27.6416967284314,40.7799880771295 +"5","33",27.6505087856138,40.7825582604744 +"5","34",27.6317831641012,40.779253739031 +"5","35",27.62737713551,40.779253739031 +"5","36",27.620400923574,40.7777850628339 +"5","37",27.6119560354409,40.7755820485383 +"5","38",27.6068156687511,40.7730118651935 +"5","39",27.6035111473077,40.7704416818486 +"5","40",27.5987379496673,40.7678714985037 +"5","41",27.5910273996327,40.7630983008633 +"5","42",27.5829496805489,40.7590594413214 +"5","43",27.5763406376621,40.757223596075 +"5","44",27.5708331019231,40.755754919878 +"5","45",27.5656927352334,40.7535519055824 +"5","46",27.5590836923466,40.7509817222375 +"5","47",27.5521074804105,40.7476772007941 +"5","48",27.5484357899179,40.7454741864985 +"5","49",27.5421939160803,40.7429040031537 +"5","50",27.533381858898,40.7395994817103 +"5","51",27.5245698017156,40.7362949602669 +"5","52",27.5190622659766,40.733724776922 +"5","53",27.5069456873508,40.7278500721338 +"5","54",27.5018053206611,40.7260142268874 +"5","55",27.4918917563309,40.7223425363948 +"5","56",27.4786736705573,40.715733493508 +"5","57",27.4720646276706,40.7109602958675 +"5","58",27.4672914300301,40.7065542672763 +"5","59",27.4617838942911,40.7014139005866 +"5","60",27.4555420204536,40.6962735338969 +"5","61",27.4529718371087,40.693703350552 +"5","62",27.4463627942219,40.6863599695667 +"5","63",27.4426911037293,40.6804852647785 +"5","64",27.4390194132366,40.6753448980887 +"5","65",27.436816398941,40.6724075456946 +"5","66",27.4294730179557,40.6639626575615 +"5","67",27.4269028346109,40.6613924742166 +"5","68",27.4232311441182,40.6562521075269 +"5","69",27.4202937917241,40.6518460789357 +"5","70",27.4162549321821,40.6463385431967 +"5","71",27.413317579788,40.6430340217533 +"5","72",27.4089115511968,40.6397295003099 +"5","73",27.4056070297534,40.6375264860144 +"5","74",27.4000994940144,40.634221964571 +"5","75",27.3905530987335,40.62467556929 +"5","76",27.3901859296843,40.6224725549944 +"5","77",27.3865142391916,40.6191680335511 +"5","78",27.3813738725019,40.6151291740091 +"5","79",27.3743976605658,40.6059499477775 +"5","80",27.3681557867283,40.6000752429892 +"5","81",27.360812405743,40.594200538201 +"5","82",27.3567735462011,40.5879586643634 +"5","83",27.3483286580679,40.5806152833781 +"5","84",27.3409852770826,40.5762092547869 +"5","85",27.3321732199002,40.5729047333435 +"5","86",27.3240955008164,40.5696002119002 +"5","87",27.3174864579296,40.566662859506 +"5","88",27.3094087388458,40.5633583380626 +"5","89",27.3024325269097,40.5604209856685 +"5","90",27.2965578221215,40.5589523094714 +"5","91",27.2881129339883,40.5571164642251 +"5","92",27.2767306934611,40.5527104356339 +"5","93",27.2690201434265,40.5501402522891 +"5","94",27.2642469457861,40.548671576092 +"5","95",27.2583722409978,40.5468357308457 +"5","96",27.2499273528647,40.5442655475008 +"5","97",27.244786986175,40.5435312094023 +"5","98",27.2367092670911,40.5420625332052 +"5","99",27.2260613646624,40.5405938570081 +"5","100",27.21724930748,40.5391251808111 +"5","101",27.2066014050513,40.5383908427126 +"5","102",27.1988908550167,40.5365549974662 +"5","103",27.1849384311446,40.5339848141214 +"5","104",27.1775950501593,40.5328833069736 +"5","105",27.1629082881887,40.532148968875 +"5","106",27.1474871881195,40.5314146307765 +"5","107",27.1397766380849,40.5303131236287 +"5","108",27.1291287356562,40.5295787855302 +"5","109",27.1225196927694,40.5281101093331 +"5","110",27.113707635587,40.5270086021853 +"5","111",27.106731423651,40.5259070950375 +"5","112",27.095716352173,40.5222354045449 +"5","113",27.0883729711877,40.5192980521507 +"5","114",27.0799280830546,40.5156263616581 +"5","115",27.0707488568229,40.5126890092639 +"5","116",27.0641398139361,40.5104859949683 +"5","117",27.0549605877045,40.5068143044757 +"5","118",27.0428440090787,40.5024082758845 +"5","119",27.0366021352412,40.5002052615889 +"5","120",27.0285244161574,40.4965335710963 +"5","121",27.0178765137286,40.4917603734558 +"5","122",27.0068614422507,40.4884558520124 +"5","123",26.997682216019,40.485151330569 +"5","124",26.9899716659844,40.4825811472241 +"5","125",26.9811596088021,40.4800109638793 +"5","126",26.9730818897182,40.4781751186329 +"5","127",26.963168325388,40.4756049352881 +"5","128",26.9528875920086,40.474136259091 +"5","129",26.9348963085945,40.4700973995491 +"5","130",26.9224125609195,40.4653242019087 +"5","131",26.9095616441952,40.4609181733175 +"5","132",26.8989137417665,40.4587151590219 +"5","133",26.8937733750768,40.4583479899726 +"5","134",26.8812896274017,40.4565121447263 +"5","135",26.8728447392686,40.4550434685292 +"5","136",26.865134189234,40.4539419613814 +"5","137",26.8552206249038,40.4513717780365 +"5","138",26.8456742296229,40.4477000875439 +"5","139",26.8353934962435,40.4454970732483 +"5","140",26.8232769176177,40.4418253827556 +"5","141",26.8140976913861,40.4403567065586 +"5","142",26.7990437603662,40.4370521851152 +"5","143",26.7942705627257,40.4359506779674 +"5","144",26.7854585055433,40.4337476636718 +"5","145",26.7737090959668,40.432646156524 +"5","146",26.7615925173411,40.4297088041299 +"5","147",26.7538819673065,40.4260371136372 +"5","148",26.7443355720255,40.4230997612431 +"5","149",26.736625021991,40.4190609017011 +"5","150",26.7267114576608,40.4135533659622 +"5","151",26.7167978933306,40.4058428159276 +"5","152",26.7098216813946,40.4014367873364 +"5","153",26.7050484837541,40.3977650968437 +"5","154",26.6947677503747,40.3922575611047 +"5","155",26.6866900312908,40.3867500253657 +"5","156",26.6775108050592,40.3805081515282 +"5","157",26.6716361002709,40.3764692919863 +"5","158",26.6650270573841,40.3713289252966 +"5","159",26.6598866906944,40.3665557276561 +"5","160",26.6503402954135,40.3577436704737 +"5","161",26.6470357739701,40.352603303784 +"5","162",26.6411610691818,40.3496659513899 +"5","163",26.6356535334428,40.3452599227987 +"5","164",26.6297788286546,40.3397523870597 +"5","165",26.6246384619649,40.3349791894193 +"5","166",26.6202324333737,40.3313074989266 +"5","167",26.6147248976347,40.3272686393847 +"5","168",26.6081158547479,40.3243312869905 +"5","169",26.6037098261567,40.3195580893501 +"5","170",26.6000381356641,40.3169879060052 +"5","171",26.5956321070729,40.3133162155126 +"5","172",26.5886558951368,40.3085430178721 +"5","173",26.580578176053,40.3030354821331 +"5","174",26.5728676260184,40.2967936082956 +"5","175",26.5633212307375,40.2905517344581 +"5","176",26.5592823711955,40.2879815511132 +"5","177",26.5537748354566,40.2854113677684 +"5","178",26.5442284401756,40.2795366629801 +"5","179",26.540556749683,40.2747634653396 +"5","180",26.5321118615499,40.2666857462558 +"5","181",26.5266043258109,40.2619125486153 +"5","182",26.5203624519734,40.2564050128763 +"5","183",26.5122847328895,40.2505303080881 +"5","184",26.5064100281013,40.2464914485462 +"5","185",26.4983323090174,40.2413510818565 +"5","186",26.4898874208843,40.2362107151667 +"5","187",26.4829112089482,40.2318046865755 +"5","188",26.4752006589137,40.2266643198858 +"5","189",26.4689587850761,40.224094136541 +"5","190",26.4564750374011,40.220055276999 +"5","191",26.4520690088099,40.218586600802 +"5","192",26.4403195992334,40.2138134031615 +"5","193",26.4337105563466,40.213079065063 +"5","194",26.4212268086716,40.209040205521 +"5","195",26.4131490895877,40.2064700221762 +"5","196",26.4069072157502,40.2046341769299 +"5","197",26.4013996800112,40.2027983316835 +"5","198",26.3929547918781,40.2002281483387 +"5","199",26.3881815942376,40.1954549506982 +"5","200",26.3870800870898,40.1888459078114 +"5","201",26.3856114108928,40.1822368649246 +"5","202",26.3856114108928,40.1748934839393 +"5","203",26.3848770727942,40.167550102954 +"5","204",26.3852442418435,40.1616753981658 +"5","205",26.3874472561391,40.1554335243282 +"5","206",26.3881815942376,40.1484573123922 +"5","207",26.3856114108928,40.1345048885201 +"5","208",26.3819397204001,40.1264271694362 +"5","209",26.3731276632177,40.1183494503524 +"5","210",26.367987296528,40.1143105908105 +"5","211",26.3613782536412,40.1099045622193 +"5","212",26.3503631821632,40.1010925050369 +"5","213",26.3411839559316,40.0937491240516 +"5","214",26.3316375606507,40.086038574017 +"5","215",26.3246613487146,40.0801638692287 +"5","216",26.3173179677293,40.0753906715883 +"5","217",26.304467051005,40.0676801215537 +"5","218",26.2985923462168,40.0651099382088 +"5","219",26.2875772747388,40.0610710786669 +"5","220",26.2776637104086,40.057032219125 +"5","221",26.2692188222755,40.0522590214845 +"5","222",26.2648127936843,40.0504231762382 +"5","223",26.2534305531571,40.0441813024007 +"5","224",26.240946805482,40.0375722595139 +"5","225",26.2358064387923,40.0368379214153 +"5","226",26.2266272125606,40.0339005690212 +"5","227",26.2240570292158,40.0331662309227 +"5","228",26.2178151553783,40.0309632166271 +"5","229",26.2097374362944,40.0283930332822 +"5","230",26.2020268862598,40.0272915261344 +"5","231",26.1932148290774,40.0261900189866 +"5","232",26.1785280671068,40.0250885118388 +"5","233",26.1697160099244,40.0236198356418 +"5","234",26.1513575574611,40.0199481451491 +"5","235",26.1403424859832,40.0181122999028 +"5","236",26.1289602454559,40.0159092856072 +"5","237",26.1157421596823,40.011503257016 +"5","238",26.1058285953522,40.0085659046219 +"5","239",26.0940791857757,40.005995721277 +"5","240",26.0837984523962,40.0052613831785 +"5","241",26.0702131975734,40.0019568617351 +"5","242",26.0665415070807,40.0012225236366 +"5","243",26.0562607737013,39.9993866783902 +"5","244",26.0430426879277,39.9975508331439 +"5","245",26.0254185735629,39.9931448045527 +"5","246",26.0147706711342,39.9909417902571 +"5","247",26.0041227687055,39.9887387759615 +"5","248",25.9890688376856,39.9861685926167 +"5","249",25.9692417090252,39.9810282259269 +"5","250",25.9685073709267,39.9810282259269 +"5","251",25.9629998351877,39.9795595497299 +"5","252",25.9519847637098,39.9755206901879 +"5","253",25.945375720823,39.9744191830401 +"5","254",25.9281187755075,39.9707474925475 +"5","255",25.910861830192,39.9681773092026 +"5","256",25.9057214635023,39.9670758020548 +"5","257",25.8980109134677,39.9648727877592 +"5","258",25.8906675324824,39.9626697734636 +"5","259",25.8818554753,39.9608339282173 +"5","260",25.8767151086102,39.9597324210695 +"5","261",25.8634970228367,39.9567950686754 +"5","262",25.852849120408,39.9538577162812 +"5","263",25.84183404893,39.9512875329364 +"5","264",25.8311861465013,39.9490845186408 +"5","265",25.8223740893189,39.947983011493 +"5","266",25.8179680607277,39.9472486733945 +"6","0",3.79397518634937,51.9880986827578 +"6","1",3.80572459592588,51.9814896398711 +"6","2",3.81894268169945,51.9734119207872 +"6","3",3.83436378176862,51.9623968493092 +"6","4",3.84684752944366,51.9521161159298 +"6","5",3.8549252485275,51.9462414111415 +"6","6",3.86373730570989,51.9411010444518 +"6","7",3.87768972958199,51.9352263396636 +"6","8",3.89311082965116,51.9271486205797 +"6","9",3.91660964880417,51.9124618586091 +"6","10",3.94818618704104,51.8911660537516 +"6","11",3.96213861091314,51.8860256870619 +"6","12",3.9819657395735,51.8786823060766 +"6","13",4.00179286823386,51.8661985584016 +"6","14",4.0120736016133,51.8610581917118 +"6","15",4.028229039781,51.8522461345295 +"6","16",4.04585315414576,51.84196540115 +"6","17",4.06788329710172,51.8302159915735 +"6","18",4.08257005907235,51.8199352581941 +"6","19",4.09652248294445,51.8140605534058 +"6","20",4.11781828780188,51.8045141581249 +"6","21",4.12516166878719,51.8030454819278 +"6","22",4.13397372596957,51.8023111438293 +"6","23",4.14058276885636,51.8015768057308 +"6","24",4.16848761660057,51.7905617342528 +"6","25",4.18023702617708,51.7868900437601 +"6","26",4.20447018342862,51.7773436484792 +"6","27",4.22209429779339,51.7663285770012 +"6","28",4.24412444074934,51.7553135055233 +"6","29",4.25734252652291,51.7450327721438 +"6","30",4.28818472666125,51.7303460101732 +"6","31",4.30287148863188,51.7252056434835 +"6","32",4.30507450292748,51.7244713053849 +"6","33",4.31682391250398,51.7215339529908 +"6","34",4.34913478883938,51.7156592482026 +"6","35",4.35354081743057,51.7163935863011 +"6","36",4.36602456510561,51.7163935863011 +"6","37",4.38291434137184,51.7163935863011 +"6","38",4.42183426059403,51.7083158672172 +"6","39",4.43138065587494,51.7068471910202 +"6","40",4.4350523463676,51.7068471910202 +"6","41",4.44533307974704,51.7046441767246 +"6","42",4.47397226558978,51.6958321195422 +"6","43",4.49379939425014,51.6943634433451 +"6","44",4.50481446572811,51.6936291052466 +"6","45",4.51729821340315,51.6928947671481 +"6","46",4.54079703255617,51.6928947671481 +"6","47",4.56943621839891,51.6950977814437 +"6","48",4.5899976851578,51.703909838626 +"6","49",4.60321577093137,51.7061128529216 +"6","50",4.61276216621228,51.7090502053158 +"6","51",4.62451157578879,51.7127218958084 +"6","52",4.64801039494181,51.7193309386952 +"6","53",4.65975980451832,51.7244713053849 +"6","54",4.67004053789776,51.7274086577791 +"6","55",4.67811825698161,51.7281429958776 +"6","56",4.68546163796693,51.7303460101732 +"6","57",4.69353935705078,51.7347520387644 +"6","58",4.70528876662729,51.7406267435526 +"6","59",4.7126321476126,51.7457671102424 +"6","60",4.71630383810526,51.7487044626365 +"6","61",4.72070986669645,51.7501731388335 +"6","62",4.72658457148471,51.7545791674247 +"6","63",4.73759964296268,51.7648599008042 +"6","64",4.74274000965241,51.7685315912968 +"6","65",4.7471460382436,51.771468943691 +"6","66",4.75302074303185,51.7766093103807 +"6","67",4.76036412401717,51.7824840151689 +"6","68",4.77358220979074,51.7890930580557 +"6","69",4.78386294317018,51.7927647485484 +"6","70",4.79708102894376,51.7971707771396 +"6","71",4.81029911471733,51.7993737914352 +"6","72",4.8396726386586,51.8008424676322 +"6","73",4.84554734344685,51.8008424676322 +"6","74",4.85509373872777,51.8030454819278 +"6","75",4.86317145781161,51.8067171724205 +"6","76",4.8837329245705,51.8140605534058 +"6","77",4.88446726266904,51.8147948915043 +"6","78",4.88887329126023,51.8162635677014 +"6","79",4.89695101034408,51.8192009200955 +"6","80",4.91530946280737,51.8228726105882 +"6","81",4.92485585808828,51.8250756248838 +"6","82",4.94101129625598,51.8258099629823 +"6","83",4.95790107252221,51.8258099629823 +"6","84",4.97405651068991,51.8258099629823 +"6","85",4.98800893456201,51.8265443010809 +"6","86",4.99755532984293,51.8250756248838 +"6","87",5.01150775371503,51.8206695962926 +"6","88",5.02325716329154,51.8199352581941 +"6","89",5.04234995385336,51.8199352581941 +"6","90",5.06291142061225,51.8214039343911 +"6","91",5.0731921539917,51.8250756248838 +"6","92",5.07833252068142,51.8250756248838 +"6","93",5.09301928265206,51.8272786391794 +"6","94",5.1033000160315,51.8280129772779 +"6","95",5.12753317328305,51.8199352581941 +"6","96",5.13193920187424,51.8177322438985 +"6","97",5.14001692095809,51.8155292296029 +"6","98",5.15470368292872,51.8155292296029 +"6","99",5.16278140201257,51.8169979057999 +"6","100",5.16498441630817,51.8169979057999 +"6","101",5.18260853067293,51.8147948915043 +"6","102",5.19876396884063,51.8133262153073 +"6","103",5.21051337841714,51.8118575391102 +"6","104",5.22079411179658,51.8111232010117 +"6","105",5.22887183088043,51.8111232010117 +"6","106",5.23548087376722,51.8125918772087 +"6","107",5.23694954996428,51.8133262153073 +"6","108",5.2442929309496,51.8162635677014 +"6","109",5.27072910249674,51.818466581997 +"6","110",5.29202490735416,51.8236069486867 +"6","111",5.30230564073361,51.8250756248838 +"6","112",5.32800747418222,51.8192009200955 +"6","113",5.33167916467488,51.8169979057999 +"6","114",5.33608519326607,51.8118575391102 +"6","115",5.34710026474404,51.8067171724205 +"6","116",5.35517798382789,51.805982834322 +"6","117",5.36031835051762,51.8089201867161 +"6","118",5.36545871720734,51.8147948915043 +"6","119",5.37794246488238,51.8221382724897 +"6","120",5.38895753636036,51.829481653475 +"6","121",5.39556657924714,51.8360906963618 +"6","122",5.4014412840354,51.8412310630515 +"6","123",5.41392503171044,51.8537148107265 +"6","124",5.42494010318841,51.8691359107957 +"6","125",5.43008046987813,51.8735419393869 +"6","126",5.43889252706052,51.8801509822737 +"6","127",5.44843892234143,51.8852913489634 +"6","128",5.4638600224106,51.8882287013575 +"6","129",5.48074979867683,51.8896973775546 +"6","130",5.49837391304159,51.8904317156531 +"6","131",5.51085766071663,51.8904317156531 +"6","132",5.52334140839167,51.8911660537516 +"6","133",5.5380281703623,51.8948377442443 +"6","134",5.54610588944615,51.8963064204414 +"6","135",5.55858963712119,51.9014467871311 +"6","136",5.57107338479623,51.9058528157223 +"6","137",5.59236918965365,51.9051184776238 +"6","138",5.60705595162429,51.9029154633282 +"6","139",5.62027403739786,51.9014467871311 +"6","140",5.63128910887584,51.9007124490326 +"6","141",5.64303851845235,51.899978110934 +"6","142",5.65258491373326,51.8977750966384 +"6","143",5.67167770429508,51.8955720823428 +"6","144",5.70031689013782,51.8926347299487 +"6","145",5.71867534260112,51.8904317156531 +"6","146",5.73997114745854,51.8852913489634 +"6","147",5.75245489513358,51.8830883346678 +"6","148",5.76346996661155,51.8816196584707 +"6","149",5.79724951914402,51.876479291781 +"6","150",5.80459290012933,51.8750106155839 +"6","151",5.82735738118382,51.8691359107957 +"6","152",5.83249774787354,51.8669328965001 +"6","153",5.83984112885886,51.8625268679089 +"6","154",5.85159053843537,51.8595895155148 +"6","155",5.85599656702656,51.8566521631206 +"6","156",5.86333994801187,51.8522461345295 +"6","157",5.86921465280013,51.8507774583324 +"6","158",5.87435501948985,51.8515117964309 +"6","159",5.87655803378545,51.8573865012192 +"6","160",5.88096406237664,51.8625268679089 +"6","161",5.89418214815021,51.8684015726972 +"6","162",5.90299420533259,51.8706045869928 +"6","163",5.91033758631791,51.8720732631898 +"6","164",5.92722736258414,51.8728076012884 +"6","165",5.93824243406211,51.8698702488942 +"6","166",5.9448514769489,51.8661985584016 +"6","167",5.95292919603275,51.8617925298104 +"6","168",5.96174125321513,51.8559178250221 +"6","169",5.96835029610192,51.8537148107265 +"6","170",5.97275632469311,51.8537148107265 +"6","171",5.97569367708723,51.8551834869236 +"6","172",5.98009970567843,51.8595895155148 +"6","173",5.98156838187549,51.8617925298104 +"6","174",5.98817742476227,51.8684015726972 +"6","175",5.99552080574759,51.8757449536825 +"6","176",6.00066117243731,51.8794166441751 +"6","177",6.0072702153241,51.8816196584707 +"6","178",6.01755094870354,51.8823539965693 +"6","179",6.01975396299914,51.8823539965693 +"6","180",6.03223771067418,51.8757449536825 +"6","181",6.03590940116684,51.8735419393869 +"6","182",6.03811241546243,51.8728076012884 +"6","183",6.04692447264481,51.8713389250913 +"6","184",6.05867388222132,51.8661985584016 +"6","185",6.06161123461545,51.8647298822045 +"6","186",6.07850101088168,51.8588551774162 +"6","187",6.08657872996553,51.8551834869236 +"6","188",6.09098475855672,51.8537148107265 +"6","189",6.09685946334497,51.852980472628 +"6","190",6.10053115383763,51.8507774583324 +"6","191",6.1137492396112,51.8485744440368 +"6","192",6.12035828249799,51.8478401059383 +"6","193",6.12917033968037,51.8478401059383 +"6","194",6.1321076920745,51.8478401059383 +"6","195",6.15487217312898,51.8441684154456 +"6","196",6.16148121601577,51.84196540115 +"6","197",6.16882459700109,51.8397623868544 +"6","198",6.17323062559228,51.8375593725588 +"6","199",6.18498003516879,51.8324190058691 +"6","200",6.1945264304497,51.8316846677706 +"6","201",6.20333848763208,51.830950329672 +"6","202",6.21435355911006,51.8302159915735 +"6","203",6.23050899727775,51.829481653475 +"6","204",6.23418068777041,51.829481653475 +"6","205",6.24666443544545,51.8258099629823 +"6","206",6.25767950692343,51.8236069486867 +"6","207",6.26796024030287,51.8199352581941 +"6","208",6.27750663558379,51.8162635677014 +"6","209",6.28631869276617,51.8111232010117 +"6","210",6.28999038325883,51.8096545248146 +"6","211",6.30027111663827,51.8067171724205 +"6","212",6.30614582142653,51.8045141581249 +"6","213",6.31055185001772,51.7986394533366 +"6","214",6.3171608929045,51.7912960723513 +"6","215",6.32156692149569,51.7868900437601 +"6","216",6.32597295008688,51.7795466627748 +"6","217",6.32891030248101,51.7751406341836 +"6","218",6.33258199297367,51.7677972531983 +"6","219",6.33772235966339,51.760453872213 +"7","0",3.78589746726552,52.1180765261979 +"7","1",3.81233363881266,52.1063271166214 +"7","2",3.82188003409357,52.0997180737347 +"7","3",3.84170716275393,52.0916403546508 +"7","4",3.85419091042897,52.0879686641581 +"7","5",3.86520598190695,52.0806252831728 +"7","6",3.87842406768052,52.074016240286 +"7","7",3.89017347725703,52.0703445497934 +"7","8",3.9033915630306,52.0630011688081 +"7","9",3.92395302978949,52.0527204354286 +"7","10",3.94378015844985,52.0417053639506 +"7","11",3.95332655373076,52.0372993353595 +"7","12",3.97682537288378,52.0255499257829 +"7","13",3.98637176816469,52.0204095590932 +"7","14",3.99444948724854,52.016003530502 +"7","15",4.01280793971183,52.0049884590241 +"7","16",4.02161999689421,52.0020511066299 +"7","17",4.05539954942667,51.9969107399402 +"7","18",4.07522667808703,51.9897509434795 +"7","19",4.08183572097382,51.9862628375115 +"7","20",4.0895462710084,51.9833254851174 +"7","21",4.09431946864886,51.9820403934449 +"7","22",4.10001058891248,51.980020963674 +"7","23",4.10404944845441,51.9790112487885 +"7","24",4.11010773776729,51.9776802609849 +"7","25",4.11474324701428,51.9768082344929 +"7","26",4.12392247324592,51.9735037130495 +"7","27",4.12993486642765,51.9711630103604 +"7","28",4.13470806406811,51.9687764115402 +"7","29",4.1438413941686,51.9644162790801 +"7","30",4.15067991771117,51.9611117576368 +"7","31",4.15508594630236,51.9587251588166 +"7","32",4.15967555941818,51.956522144521 +"7","33",4.16371441896011,51.9546862992746 +"7","34",4.17197572256859,51.9511981933066 +"7","35",4.17472949043809,51.9497295171095 +"7","36",4.17950268807854,51.947526502814 +"7","37",4.18152211784951,51.946103722748 +"7","38",4.184275885719,51.944956319469 +"7","39",4.18721323811313,51.9438548123212 +"7","40",4.19024238276957,51.9418812786815 +"7","41",4.19689732178751,51.9398618489105 +"7","42",4.20281792270693,51.9377965230084 +"7","43",4.211538187627,51.9341707286469 +"7","44",4.21594421621819,51.9325184679252 +"7","45",4.22145175195717,51.9298105961868 +"7","46",4.22870334068017,51.9236605146117 +"7","47",4.2316406930743,51.9216410848407 +"7","48",4.23719412494445,51.9169137833314 +"7","49",4.24293114133923,51.9147107690358 +"7","50",4.24651103956957,51.9132879889699 +"7","51",4.25036631458686,51.9120946895597 +"7","52",4.25596564258817,51.9100752597888 +"7","53",4.26303364678653,51.9076886609686 +"7","54",4.26835759800089,51.905485646673 +"7","55",4.27459947183841,51.9032826323774 +"7","56",4.27868422751149,51.9017680600491 +"7","57",4.28299846384037,51.9004829683767 +"7","58",4.28855189571051,51.8990601883109 +"7","59",4.2935086778756,51.8979586811631 +"7","60",4.29773112194216,51.8975915121138 +"7","61",4.30250431958261,51.8972243430645 +"7","62",4.30782827079697,51.8966735894906 +"7","63",4.31407014463449,51.8959392513921 +"7","64",4.31902692679958,51.8952049132936 +"7","65",4.32857332208049,51.8942869906704 +"7","66",4.33408085781948,51.894470575195 +"7","67",4.33885405545993,51.8946541597197 +"7","68",4.34555489060904,51.8965817972283 +"7","69",4.35110832247919,51.8983258502123 +"7","70",4.35739609244786,51.8988766037862 +"7","71",4.36051702936663,51.8992437728354 +"7","72",4.3659327728433,51.8991519805731 +"7","73",4.37428586871409,51.8988766037862 +"7","74",4.37832472825602,51.8986930192616 +"7","75",4.38236358779795,51.8977750966384 +"7","76",4.38695320091377,51.8972702391956 +"7","77",4.39048720301295,51.8969489662775 +"7","78",4.39778468786711,51.8974079275892 +"7","79",4.40421014622926,51.8988766037862 +"7","80",4.41302220341164,51.9003452799833 +"7","81",4.41871332367526,51.9016303716557 +"7","82",4.42440444393888,51.9021811252296 +"7","83",4.43211499397347,51.9025482942789 +"7","84",4.43762252971246,51.9023647097543 +"7","85",4.44166138925438,51.9018139561804 +"7","86",4.4462510023702,51.9005288645079 +"7","87",4.45272235686352,51.8996568380159 +"7","88",4.45965267266841,51.8996109418847 +"7","89",4.46607813103056,51.9007124490325 +"7","90",4.46993340604785,51.9010796180818 +"7","91",4.47204462808114,51.9017680600491 +"7","92",4.47369688880283,51.9026859826723 +"7","93",4.47599169536074,51.9036498014267 +"7","94",4.48204998467363,51.9065871538208 +"7","95",4.48406941444459,51.9076886609686 +"7","96",4.48810827398651,51.9115439359859 +"7","97",4.49086204185601,51.9133797812322 +"7","98",4.49306505615161,51.9150320419539 +"7","99",4.49591061628342,51.917097367856 +"7","100",4.50040843713692,51.9176022252988 +"7","101",4.50224428238325,51.9181529788727 +"7","102",4.50426371215421,51.917969394348 +"7","103",4.50775181812224,51.9172350562495 +"7","104",4.51123992409027,51.9157663800524 +"7","105",4.51472803005829,51.9122782740844 +"7","106",4.51541647202567,51.9104883249692 +"7","107",4.5161508101242,51.9084229990671 +"7","108",4.51693104435389,51.9048889969679 +"7","109",4.51913405864949,51.902318813623 +"7","110",4.52289754140446,51.9006665529013 +"7","111",4.52739536225796,51.9003452799833 +"7","112",4.53143422179989,51.9010796180818 +"7","113",4.53327006704622,51.901997540705 +"7","114",4.53565666586645,51.9027318788035 +"7","115",4.53694175753888,51.9029154633281 +"7","116",4.54116420160543,51.903466216902 +"7","117",4.54795682901685,51.9043841395252 +"7","118",4.55364794928047,51.9049348930991 +"7","119",4.5582375623963,51.9045677240498 +"7","120",4.56282717551212,51.9042005550006 +"7","121",4.56594811243088,51.9042005550006 +"7","122",4.56980338744817,51.9036498014267 +"7","123",4.5738422469901,51.903466216902 +"7","124",4.57769752200739,51.902869567197 +"7","125",4.58237892738553,51.9014926832622 +"7","126",4.58706033276367,51.8983717463434 +"7","127",4.59279734915845,51.8951131210312 +"7","128",4.59995714561914,51.8931395873914 +"7","129",4.60652029237476,51.8921757686371 +"7","130",4.61358829657313,51.8907988847023 +"7","131",4.62038092398455,51.8896514814234 +"7","132",4.62689817460902,51.8895137930299 +"7","133",4.63332363297117,51.8907988847024 +"7","134",4.63974909133332,51.8911660537516 +"7","135",4.64539431546579,51.8902022349973 +"7","136",4.65154439704099,51.8897432736857 +"7","137",4.65829112832125,51.8898809620792 +"7","138",4.66324791048634,51.8896514814234 +"7","139",4.67284020189841,51.8895137930299 +"7","140",4.67811825698161,51.8919462879813 +"7","141",4.6830750391467,51.8933231719161 +"7","142",4.68858257488569,51.8941034061458 +"7","143",4.69500803324784,51.8953884978182 +"7","144",4.69941406183903,51.8962605243102 +"7","145",4.70221372583968,51.8967194856218 +"7","146",4.70671154669319,51.8972243430645 +"7","147",4.71437620059662,51.8968112778841 +"7","148",4.72034269764719,51.8972243430645 +"7","149",4.72621740243544,51.8990601883108 +"7","150",4.73154135364979,51.9012632026064 +"7","151",4.73851756558585,51.9036498014267 +"7","152",4.74145491797997,51.9047513085745 +"7","153",4.74641170014506,51.9067707383454 +"7","154",4.75155206683479,51.908973752641 +"7","155",4.75444352309775,51.9109013901497 +"7","156",4.759446201394,51.9132879889699 +"7","157",4.76825825857638,51.9157663800524 +"7","158",4.77137919549514,51.9166843026756 +"7","159",4.77707031575876,51.9174645369053 +"7","160",4.78092559077606,51.9176481214299 +"7","161",4.78349577412092,51.9181529788727 +"7","162",4.78514803484261,51.9183365633973 +"7","163",4.79138990868013,51.9198052395944 +"7","164",4.79653027536986,51.9209067467422 +"7","165",4.80217549950232,51.921732877103 +"7","166",4.80722407392972,51.9232474494312 +"7","167",4.81144651799628,51.9245325411037 +"7","168",4.81543948140705,51.9269650360551 +"7","169",4.8182391454077,51.9291680503506 +"7","170",4.82140597845762,51.9310497917281 +"7","171",4.82535304573723,51.9332069098926 +"7","172",4.82718889098356,51.9343084170404 +"7","173",4.82851987878715,51.9360524700244 +"7","174",4.83044751629579,51.9373834578279 +"7","175",4.83232925767328,51.9387603417627 +"7","176",4.83466996036235,51.939724160517 +"7","177",4.83861702764196,51.9405043947467 +"7","178",4.84628168154538,51.9411010444518 +"7","179",4.85068771013657,51.9416517980257 +"7","180",4.85908670213853,51.940871563796 +"7","181",4.86330914620509,51.9400913295663 +"7","182",4.86597112181227,51.9396782643859 +"7","183",4.86941333164913,51.9389439262873 +"7","184",4.87459959447001,51.9380718997953 +"7","185",4.88354934004587,51.9384849649757 +"7","186",4.88749640732548,51.9390357185497 +"7","187",4.89025017519497,51.939127510812 +"7","188",4.89621667224554,51.9401831218286 +"7","189",4.90062270083673,51.9405502908779 +"7","190",4.90649740562499,51.9411010444518 +"7","191",4.91026088837996,51.9417894864192 +"7","192",4.92155133664489,51.9448186310756 +"7","193",4.92522302713755,51.9484444254371 +"7","194",4.92825217179399,51.9530340385529 +"7","195",4.93137310871275,51.9572564826195 +"7","196",4.9347235262873,51.9609740692433 +"7","197",4.93857880130459,51.96322297967 +"7","198",4.94156204982988,51.9639573177686 +"7","199",4.94688600104423,51.9642326945555 +"7","200",4.95193457547164,51.9629934990143 +"7","201",4.95597343501356,51.9616166150795 +"7","202",4.96152686688371,51.960010250489 +"7","203",4.96694261036038,51.9593218085216 +"7","204",4.97038482019725,51.9603774195382 +"7","205",4.97391882229643,51.9618919918665 +"7","206",4.97772820118257,51.9642326945555 +"7","207",4.97993121547816,51.9664357088511 +"7","208",4.98176706072449,51.9686387231467 +"7","209",4.98580592026642,51.9719432445901 +"7","210",4.98929402623444,51.9746511163284 +"7","211",4.99535231554733,51.9770836112799 +"7","212",5.00058447449937,51.9781851184276 +"7","213",5.00526587987751,51.9774507803291 +"7","214",5.01283874151862,51.9741921550169 +"7","215",5.01715297784749,51.9717596600655 +"7","216",5.02247692906185,51.9698320225568 +"7","217",5.02633220407914,51.9691894767206 +"7","218",5.03119719398191,51.9694189573764 +"7","219",5.03459350768762,51.9703827761307 +"7","220",5.03808161365565,51.9728611672133 +"7","221",5.03964208211503,51.9759362080009 +"7","222",5.04271712290263,51.980020963674 +"7","223",5.04804107411698,51.9841975116094 +"7","224",5.05336502533134,51.9866759026919 +"7","225",5.05882666493917,51.9889707092498 +"7","226",5.06382934323542,51.991908061644 +"7","227",5.06915329444977,51.9954420637431 +"7","228",5.07218243910621,51.9961764018417 +"7","229",5.07429366113949,51.9966353631533 +"7","230",5.07585412959887,51.9970943244649 +"7","231",5.07833252068142,51.998012247088 +"7","232",5.08090270402628,51.9987465851866 +"7","233",5.08292213379724,51.9992973387605 +"7","234",5.08512514809284,51.9998480923344 +"7","235",5.08732816238843,52.0005824304329 +"7","236",5.09063268383183,52.0016839375807 +"7","237",5.0927439058651,52.0022346911546 +"7","238",5.09577305052155,52.0026018602038 +"7","239",5.10357539281845,52.0031526137777 +"7","240",5.10467689996625,52.0031526137777 +"7","241",5.10687991426184,52.0029690292531 +"7","242",5.10871575950817,52.0026018602038 +"7","243",5.11101056606608,52.0021428988923 +"7","244",5.11761960895287,52.0008578072198 +"7","245",5.11876701223182,52.0002611575147 +"7","246",5.12064875360931,51.9995727155474 +"7","247",5.1234025214788,51.9986547929242 +"7","248",5.12542195124977,51.9970943244648 +"7","249",5.1272577964961,51.9960846095793 +"7","250",5.12891005721779,51.9950748946939 +"7","251",5.13102127925107,51.9936980107591 +"7","252",5.13248995544814,51.9921375422998 +"7","253",5.13377504712057,51.9911737235454 +"7","254",5.13496834653068,51.9899804241353 +"7","255",5.13643702272774,51.9887871247252 +"7","256",5.13808928344944,51.9869053833477 +"7","257",5.13960385577766,51.9854826032818 +"7","258",5.14061357066314,51.9842893038717 +"7","259",5.14203635072905,51.9827747315435 +"7","260",5.1428624810899,51.9813978476087 +"7","261",5.14368861145074,51.9805717172479 +"7","262",5.14488191086086,51.9793784178378 +"7","263",5.14598341800866,51.9783687029523 +"7","264",5.14699313289414,51.9771754035422 +"7","265",5.14928793945205,51.9747888047219 +"7","266",5.15002227755058,51.974238051148 +"7","267",5.15176633053459,51.9728611672133 +"7","268",5.15488726745335,51.9718514523278 +"7","269",5.15658542430621,51.9709794258358 +"7","270",5.15924739991339,51.9707040490488 +"7","271",5.16190937552056,51.9705663606554 +"7","272",5.16507620857048,51.9703827761307 +"7","273",5.16782997643998,51.9701991916061 +"7","274",5.17214421276885,51.9698320225569 +"7","275",5.17361288896591,51.9695566457699 +"7","276",5.17613717617962,51.9689599960648 +"7","277",5.17985476280343,51.9677208005236 +"7","278",5.18095626995123,51.967261839212 +"7","279",5.18233315388598,51.9666192933758 +"7","280",5.1838477262142,51.9657013707526 +"7","281",5.1854999869359,51.9647834481294 +"7","282",5.18719814378875,51.9639573177686 +"7","283",5.18862092385466,51.9633606680635 +"7","284",5.19059445749446,51.9626722260961 +"7","285",5.19334822536395,51.9616625112107 +"7","286",5.19591840870882,51.9612035498991 +"7","287",5.19738708490588,51.9607445885875 +"7","288",5.19931472241452,51.9604692118006 +"7","289",5.20115056766085,51.960010250489 +"7","290",5.2030782051695,51.9594594969151 +"7","291",5.20564838851436,51.9594594969151 +"7","292",5.20693348018679,51.9595053930462 +"7","293",5.20817267572807,51.9596430814397 +"7","294",5.20991672871208,51.9598266659643 +"7","295",5.21161488556493,51.9601479388824 +"7","296",5.21427686117211,51.9609281731122 +"7","297",5.21629629094307,51.9619378879976 +"7","298",5.21767317487782,51.9626722260962 +"7","299",5.21996798143573,51.9642326945556 +"7","300",5.22171203441974,51.9657013707526 +"7","301",5.22354787966607,51.9679043850482 +"7","302",5.22446580228924,51.9689140999337 +"7","303",5.22639343979788,51.9713924910162 +"7","304",5.22822928504421,51.9734119207872 +"7","305",5.22978975350359,51.9750641815089 +"7","306",5.23135022196297,51.976257480919 +"7","307",5.23208456006151,51.9768082344929 +"7","308",5.2342875743571,51.978001533903 +"7","309",5.23722492675123,51.9788276642639 +"7","310",5.23906077199756,51.9791948333131 +"7","311",5.24016227914535,51.9791948333131 +"7","312",5.24337500832643,51.9787358720016 +"7","313",5.24585339940898,51.9781851184277 +"7","314",5.24814820596689,51.9769000267552 +"7","315",5.249341505377,51.9760738963944 +"7","316",5.2504430125248,51.9749723892465 +"7","317",5.25159041580376,51.9740544666234 +"7","318",5.25305909200082,51.9729529594756 +"7","319",5.25503262564062,51.9718514523278 +"7","320",5.25888790065791,51.9700156070815 +"7","321",5.25998940780571,51.9695566457699 +"7","322",5.26154987626509,51.9687305154091 +"7","323",5.26490029383964,51.9671241508185 +"7","324",5.26728689265987,51.9664357088511 +"7","325",5.27091268702137,51.9654259939657 +"7","326",5.2738500394155,51.9645998636048 +"7","327",5.27623663823573,51.9640491100309 +"7","328",5.27825606800669,51.9638655255063 +"7","329",5.28114752426966,51.9633147719324 +"7","330",5.28449794184421,51.9630393951454 +"7","331",5.28927113948467,51.9626722260962 +"7","332",5.29083160794405,51.9625804338338 +"7","333",5.29477867522365,51.9623050570469 +"7","334",5.298358573454,51.9619378879976 +"7","335",5.30046979548727,51.961478926686 +"7","336",5.30414148597993,51.9602856272759 +"7","337",5.30643629253785,51.9594594969151 +"7","338",5.30776728034144,51.9586333665542 +"7","339",5.3103374636863,51.957394171013 +"7","340",5.31267816637537,51.956246767734 +"7","341",5.31488118067096,51.9556042218978 +"7","342",5.31763494854046,51.9550534683239 +"7","343",5.32029692414763,51.9548698837992 +"7","344",5.32277531523018,51.9548698837992 +"7","345",5.32548318696852,51.9554665335043 +"7","346",5.32855822775612,51.9560631832094 +"7","347",5.33232171051109,51.9569811058325 +"7","348",5.33525906290522,51.9578990284557 +"7","349",5.33801283077471,51.9598266659643 +"7","350",5.34150093674274,51.962626329965 +"7","351",5.34443828913686,51.9648752403917 +"7","352",5.34755922605563,51.9673536314743 +"7","353",5.35292907340114,51.969602541901 +"7","354",5.35774816717275,51.9706581529177 +"7","355",5.36197061123931,51.9709794258358 +"7","356",5.36752404310946,51.9704745683931 +"7","357",5.37321516337308,51.9695566457699 +"7","358",5.37752939970195,51.9693271651141 +"7","359",5.38221080508009,51.9692812689829 +"7","360",5.38523994973654,51.9696943341634 +"7","361",5.3881314059995,51.9701532954749 +"7","362",5.39120644678711,51.9708876335735 +"7","363",5.3950617218044,51.9720350368524 +"7","364",5.39781548967389,51.9728152710821 +"7","365",5.40125769951076,51.9734578169183 +"7","366",5.40502118226574,51.9743298434103 +"7","367",5.40837159984029,51.9744675318038 +"7","368",5.411767913546,51.97511007764 +"7","369",5.41502653885823,51.9758444157386 +"7","370",5.41906539840016,51.9769000267552 +"7","371",5.4215437894827,51.9780933261653 +"7","372",5.42457293413914,51.9792866255754 +"7","373",5.42585802581157,51.9802045481986 +"7","374",5.42870358594339,51.9823157702319 +"7","375",5.43237527643604,51.9843352000029 +"7","376",5.4354962133548,51.9851613303637 +"7","377",5.43687309728955,51.985528499413 +"7","378",5.43962686515905,51.9858956684622 +"7","379",5.4455015699473,51.9857579800688 +"7","380",5.44981580627617,51.9849777458391 +"7","381",5.45390056194926,51.9836926541666 +"7","382",5.45651664142528,51.9836926541666 +"7","383",5.45991295513098,51.9836467580355 +"7","384",5.46404360693523,51.983509069642 +"7","385",5.46716454385399,51.9830501083304 +"7","386",5.47074444208433,51.9828665238058 +"7","387",5.47340641769151,51.9828665238058 +"7","388",5.4781337192008,51.9836467580355 +"7","389",5.48185130582462,51.9838762386913 +"7","390",5.4845132814318,51.9838303425601 +"7","391",5.48671629572739,51.983233692855 +"7","392",5.48891931002299,51.9830501083304 +"7","393",5.49148949336785,51.9823157702319 +"7","394",5.49350892313881,51.981489639871 +"7","395",5.49630858713947,51.9802045481986 +"7","396",5.49920004340243,51.9791030410508 +"7","397",5.50296352615741,51.9775425725914 +"7","398",5.50557960563343,51.9759821041321 +"7","399",5.50929719225725,51.9743298434103 +"7","400",5.51159199881516,51.9732283362625 +"7","401",5.51466703960276,51.9725398942952 +"7","402",5.51792566491499,51.9716678678032 +"7","403",5.52026636760406,51.9713924910162 +"7","404",5.52283655094893,51.9708417374423 +"7","405",5.52609517626116,51.9704286722619 +"7","406",5.53017993193424,51.9696943341634 +"7","407",5.53353034950879,51.9690976844583 +"7","408",5.53711024773914,51.9684092424909 +"7","409",5.53926736590357,51.9675372159989 +"7","410",5.54169986085496,51.9664357088511 +"7","411",5.54399466741287,51.9636819409816 +"7","412",5.54537155134762,51.9626722260962 +"7","413",5.54702381206932,51.9611117576368 +"7","414",5.54840069600406,51.9602856272759 +"7","415",5.55060371029966,51.9589087433412 +"7","416",5.55216417875904,51.957990820718 +"7","417",5.55790119515382,51.955374741242 +"7","418",5.56262849666312,51.9540437534384 +"7","419",5.56740169430357,51.9537683766515 +"7","420",5.57061442348465,51.9533094153399 +"7","421",5.5745155946331,51.9528963501595 +"7","422",5.57786601220765,51.9522997004544 +"7","423",5.58075746847062,51.9519325314051 +"7","424",5.58318996342201,51.9513817778312 +"7","425",5.58608141968497,51.9508310242573 +"7","426",5.58947773339068,51.9501884784211 +"7","427",5.59246098191597,51.948995179011 +"7","428",5.59649984145789,51.9471593337647 +"7","429",5.59815210217959,51.9464249956661 +"7","430",5.59980436290129,51.9457824498299 +"7","431",5.6015484158853,51.9449563194691 +"7","432",5.60402680696784,51.9443137736328 +"7","433",5.60650519805039,51.9431204742227 +"7","434",5.60953434270683,51.9423402399931 +"7","435",5.61288476028138,51.9416976941569 +"7","436",5.61522546297045,51.9413764212387 +"7","437",5.61908073798774,51.9411928367141 +"7","438",5.62422110467747,51.9416517980257 +"7","439",5.62513902730063,51.941743590288 +"7","440",5.62770921064549,51.9422025515996 +"7","441",5.63197755084321,51.943487643272 +"7","442",5.6347313187127,51.9448186310756 +"7","443",5.63642947556556,51.9459660343545 +"7","444",5.63817352854957,51.9475265028139 +"7","445",5.6405601273698,51.9493623480602 +"7","446",5.64303851845234,51.9509228165196 +"7","447",5.64441540238709,51.9516571546182 +"7","448",5.64758223543701,51.9530799346841 +"7","449",5.65171288724125,51.9535847921268 +"7","450",5.65442075897959,51.9534012076022 +"7","451",5.65992829471857,51.9528045578972 +"7","452",5.66359998521123,51.9526209733725 +"7","453",5.66667502599883,51.9531258308153 +"7","454",5.66965827452412,51.9539519611761 +"7","455",5.67222845786898,51.9553288451108 +"7","456",5.67332996501678,51.9558795986847 +"7","457",5.67489043347616,51.9567975213079 +"7","458",5.67626731741091,51.9573482748818 +"7","459",5.67883750075577,51.9585415742919 +"7","460",5.6815453724941,51.9594136007839 +"7","461",5.68292225642885,51.9596889775709 +"7","462",5.68498758233097,51.9599184582267 +"7","463",5.68700701210193,51.9601479388825 +"7","464",5.69008205288953,51.9604233156694 +"7","465",5.69416680856262,51.9609281731121 +"7","466",5.695727277022,51.9612953421614 +"7","467",5.69802208357991,51.9613871344237 +"7","468",5.70183146246604,51.9622591609157 +"7","469",5.7040803728928,51.9625345377027 +"7","470",5.70830281695935,51.9629934990143 +"7","471",5.71270884555054,51.9631311874078 +"7","472",5.71688539348594,51.9633606680635 +"7","473",5.72069477237208,51.9635901487193 +"7","474",5.72298957892999,51.9641409022932 +"7","475",5.72597282745527,51.9652883055722 +"7","476",5.7283594262755,51.9667110856381 +"7","477",5.73115909027615,51.9675372159989 +"7","478",5.73161805158774,51.9675372159989 +"7","479",5.73336210457175,51.9683633463598 +"7","480",5.73593228791661,51.969005892196 +"7","481",5.73822709447452,51.9693730612452 +"7","482",5.73942039388464,51.969877918688 +"7","483",5.74125623913097,51.9701073993438 +"7","484",5.74281670759035,51.9701991916061 +"7","485",5.74520330641058,51.9700156070815 +"7","486",5.74740632070617,51.9700156070815 +"7","487",5.74919626982134,51.9694648535076 +"7","488",5.75080263441188,51.969005892196 +"7","489",5.75273027192053,51.9685010347533 +"7","490",5.75516276687191,51.967261839212 +"7","491",5.7581460153972,51.9656095784903 +"7","492",5.76016544516816,51.9645080713425 +"7","493",5.76255204398839,51.96322297967 +"7","494",5.76604014995641,51.9618460957353 +"7","495",5.76815137198969,51.9613871344237 +"7","496",5.76989542497371,51.9607445885875 +"7","497",5.77255740058088,51.960010250489 +"7","498",5.77641267559817,51.9595512891774 +"7","499",5.77944182025462,51.9590005356035 +"7","500",5.78201200359948,51.9590005356035 +"7","501",5.78467397920666,51.9591841201281 +"7","502",5.788253877437,51.9601020427513 +"7","503",5.79059458012607,51.9611576537679 +"7","504",5.79325655573325,51.9615248228172 +"7","505",5.79568905068463,51.9618460957353 +"7","506",5.79880998760339,51.9619378879976 +"7","507",5.8016555477352,51.9623509531781 +"7","508",5.80450110786702,51.9629934990143 +"7","509",5.80771383704809,51.9639573177686 +"7","510",5.81028402039295,51.9651506171787 +"7","511",5.81248703468855,51.9660226436707 +"7","512",5.81459825672183,51.9671700469497 +"7","513",5.81914197370649,51.9696484380322 +"7","514",5.82272187193684,51.9714383871474 +"7","515",5.82570512046212,51.9723563097706 +"7","516",5.82992756452868,51.9732742323937 +"7","517",5.83258954013585,51.9735955053118 +"7","518",5.83378283954597,51.9736872975741 +"7","519",5.83626123062851,51.9736872975741 +"7","520",5.83901499849801,51.9735037130495 +"7","521",5.84309975417109,51.9729988556068 +"7","522",5.84709271758186,51.9718514523278 +"7","523",5.84897445895934,51.9713006987539 +"7","524",5.85039723902525,51.9706581529177 +"7","525",5.85310511076359,51.9702909838684 +"7","526",5.85691448964972,51.9696025419011 +"7","527",5.86026490722427,51.9696025419011 +"7","528",5.86306457122492,51.9701073993438 +"7","529",5.86471683194662,51.9706581529177 +"7","530",5.8679295611277,51.9724022059017 +"7","531",5.86893927601318,51.9729529594756 +"7","532",5.86985719863634,51.9737790898364 +"7","533",5.87288634329278,51.9767164422306 +"7","534",5.8746303962768,51.9783687029523 +"7","535",5.87697109896587,51.9800668598051 +"7","536",5.87908232099915,51.9808011979037 +"7","537",5.88197377726212,51.9821321857072 +"7","538",5.88610442906636,51.9829124199369 +"7","539",5.89156606867419,51.9831877967239 +"7","540",5.89542134369148,51.9819486011826 +"7","541",5.89776204638055,51.9807553017725 +"7","542",5.90037812585657,51.9791030410508 +"7","543",5.90437108926733,51.9776343648537 +"7","544",5.90886891012084,51.9757526234763 +"7","545",5.91332083484319,51.9737790898365 +"7","546",5.91584512205689,51.9719891407213 +"7","547",5.91795634409017,51.9713006987539 +"7","548",5.92025115064808,51.97074994518 +"7","549",5.92309671077989,51.9699238148192 +"7","550",5.92566689412476,51.9691894767206 +"7","551",5.9281452852073,51.9683633463598 +"7","552",5.93025650724058,51.9675372159989 +"7","553",5.93108263760143,51.9668946701627 +"7","554",5.93264310606081,51.9657013707526 +"7","555",5.9342953667825,51.9640491100309 +"7","556",5.93548866619262,51.9623050570469 +"7","557",5.93741630370126,51.9590923278658 +"7","558",5.93870139537369,51.9578072361934 +"7","559",5.94108799419392,51.956246767734 +"7","560",5.94301563170257,51.9549616760616 +"7","561",5.94448430789963,51.9539519611761 +"7","562",5.94650373767059,51.9525750772413 +"7","563",5.94833958291692,51.9517489468805 +"7","564",5.94953288232704,51.9511981933066 +"7","565",5.95127693531105,51.9505556474704 +"7","566",5.95338815734433,51.9494541403226 +"7","567",5.95568296390224,51.9481690486502 +"7","568",5.9593546543949,51.9459660343546 +"7","569",5.96091512285428,51.9447727349444 +"7","570",5.96128229190355,51.9439466045836 +"7","571",5.96174125321513,51.9425697206488 +"7","572",5.96220021452671,51.9398159527793 +"7","573",5.96256738357598,51.9364196390736 +"7","574",5.96311813714988,51.9352263396635 +"7","575",5.96394426751072,51.9332987021549 +"7","576",5.96522935918315,51.9312792723839 +"7","577",5.9688092574135,51.9288008813014 +"7","578",5.96945180324971,51.9285255045144 +"7","579",5.97082868718446,51.9277911664159 +"7","580",5.9738578318409,51.925220983071 +"7","581",5.97615263839881,51.9236605146117 +"7","582",5.97872282174368,51.9219164616276 +"7","583",5.98055866699,51.9198970318567 +"7","584",5.98193555092475,51.9189791092335 +"7","585",5.98487290331888,51.9153992110032 +"7","586",5.98854459381154,51.9130126121829 +"7","587",5.99028864679555,51.9120946895598 +"7","588",5.99184911525493,51.910717805625 +"7","589",5.99386854502589,51.9094327139526 +"7","590",5.99607155932149,51.9083312068048 +"7","591",5.99818278135477,51.907505076444 +"7","592",6.00020221112573,51.9064035692962 +"7","593",6.00240522542132,51.9055774389353 +"7","594",6.00525078555313,51.9046595163121 +"7","595",6.00736200758641,51.9039251782136 +"7","596",6.01103369807907,51.9023647097542 +"7","597",6.01415463499783,51.9013549948687 +"7","598",6.01654123381806,51.9000699031963 +"7","599",6.02058009335998,51.8974997198515 +"7","600",6.02388461480338,51.8945623674573 +"7","601",6.02489432968886,51.8936444448342 +"7","602",6.02590404457434,51.8888712471937 +"7","603",6.02819885113225,51.8849241799141 +"7","604",6.03131978805101,51.8809771126345 +"7","605",6.03232950293649,51.8792330596505 +"7","606",6.03590940116684,51.8766628763056 +"7","607",6.03829599998706,51.8743680697477 +"7","608",6.04013184523339,51.8730829780753 +"7","609",6.04361995120142,51.8721650554521 +"8","0",7.91352012685023,54.4086147439119 +"8","1",7.95611173656507,54.386584600956 +"8","2",7.97373585092983,54.3704291627883 +"8","3",8.01192143205349,54.3439929912411 +"8","4",8.04276363219182,54.3249002006793 +"8","5",8.08241788951254,54.2911206481469 +"8","6",8.08829259430079,54.2881832957527 +"8","7",8.11472876584793,54.2690905051909 +"8","8",8.14703964218333,54.2455916860379 +"8","9",8.1764131661246,54.2338422764614 +"8","10",8.21019271865706,54.2162181620966 +"8","11",8.23516021400714,54.203000076323 +"8","12",8.27922049991905,54.178032580973 +"8","13",8.31593740484564,54.156002438017 +"8","14",8.36146636695461,54.1354409712581 +"8","15",8.40201559883291,54.1133419841054 +"8","16",8.43636885300485,54.0913806853462 +"8","17",8.45399296736961,54.0796312757697 +"8","18",8.49952192947858,54.0546637804196 +"8","19",8.54211353919342,54.0370396660549 +"8","20",8.57442441552882,54.0238215802813 +"8","21",8.60379793947009,54.0150095230989 +"8","22",8.62582808242604,54.0047287897195 +"8","23",8.66548233974675,53.9826986467635 +"8","24",8.70676590972359,53.9602324905615 +"8","25",8.74091263130532,53.9400381928519 +"8","26",8.77489871642799,53.925420275078 +"8","27",8.79913187367953,53.9180768940927 +"8","28",8.83050187932619,53.9095631617629 +"8","29",8.86134407946453,53.9007511045805 +"8","30",8.889616096258,53.8930405545459 +"8","31",8.9046700272779,53.8893688640532 +"8","32",8.91678660590368,53.8860643426098 +"8","33",8.92890318452945,53.883494159265 +"8","34",8.93865611240057,53.8795241439198 +"8","35",8.94636666243516,53.8791569748705 +"8","36",8.96142059345506,53.8786062212966 +"8","37",8.9722520804084,53.8773211296242 +"8","38",8.98014621496762,53.8762196224764 +"8","39",8.98767318047757,53.8754852843779 +"8","40",8.99428222336435,53.8751181153286 +"8","41",9.003461449596,53.8751181153286 +"8","42",9.01206697418817,53.8769310125094 +"8","43",9.02402291635489,53.8786062212966 +"8","44",9.03503798783287,53.8800748974937 +"8","45",9.04256495334282,53.8802584820183 +"8","46",9.0497247498035,53.8802584820183 +"8","47",9.05449794744396,53.8802584820183 +"8","48",9.05706813078882,53.8798913129691 +"8","49",9.0636771736756,53.8798913129691 +"8","50",9.07230564633335,53.8798913129691 +"8","51",9.0803833654172,53.8798913129691 +"8","52",9.095988050011,53.8795241439198 +"8","53",9.10626878339045,53.8795241439198 +"8","54",9.11673310129452,53.8795241439198 +"8","55",9.12554515847691,53.8795241439198 +"8","56",9.13527513828245,53.8787898058213 +"8","57",9.14904397762992,53.8789733903459 +"8","58",9.16391432412519,53.8789733903459 +"8","59",9.17548014917707,53.8789733903459 +"8","60",9.18392503731018,53.8787898058213 +"8","61",9.18649522065504,53.8787898058213 +"8","62",9.19716607114933,53.8789045461492 +"8","63",9.21111849502144,53.8785373770999 +"8","64",9.22100911128603,53.8773211296242 +"8","65",9.23131279273106,53.8752328556565 +"8","66",9.23991831732323,53.8727315165084 +"8","67",9.2503826352273,53.8707120867374 +"8","68",9.25882752336042,53.8690598260157 +"8","69",9.27186202460936,53.8668568117201 +"8","70",9.28049049726711,53.8648373819492 +"8","71",9.28838463182632,53.8630015367028 +"8","72",9.29554442828701,53.8607985224073 +"8","73",9.31225062002861,53.8545566485697 +"8","74",9.3150043878981,53.8532715568973 +"8","75",9.31812532481686,53.8507013735524 +"8","76",9.32418361412975,53.8472132675844 +"8","77",9.32730455104851,53.8444594997149 +"8","78",9.33850320705112,53.8347295199094 +"8","79",9.3451122499379,53.8299563222689 +"8","80",9.3596154273839,53.8138008841012 +"8","81",9.36200202620413,53.8119650388549 +"8","82",9.36732597741849,53.8070082566898 +"8","83",9.38146198581522,53.7895677268497 +"8","84",9.38752027512811,53.7814900077658 +"8","85",9.393578564441,53.7746973803544 +"8","86",9.39853534660609,53.7688226755661 +"8","87",9.40202345257411,53.7647838160242 +"8","88",9.40624589664067,53.7594598648099 +"8","89",9.41762813716791,53.7466089480856 +"8","90",9.42185058123447,53.7429372575929 +"8","91",9.42570585625176,53.7401834897234 +"8","92",9.43286565271245,53.735410292083 +"8","93",9.43965828012387,53.731371432541 +"8","94",9.45416145756987,53.7245788051296 +"8","95",9.46187200760445,53.7209071146369 +"8","96",9.46958255763903,53.7166846705704 +"8","97",9.47582443147656,53.7124622265038 +"8","98",9.48041404459238,53.7087905360112 +"8","99",9.48518724223283,53.7049352609939 +"8","100",9.49399929941522,53.6986933871564 +"8","101",9.49858891253104,53.6957560347622 +"8","102",9.50464720184393,53.6904320835479 +"8","103",9.50795172328732,53.686393224006 +"8","104",9.51070549115681,53.682354364464 +"8","105",9.51364284355094,53.6781319203975 +"8","106",9.51543279266611,53.6740930608556 +"8","107",9.51823245666677,53.6700542013136 +"8","108",9.52465791502892,53.6616093131805 +"8","109",9.52722809837378,53.6568361155401 +"8","110",9.5318177114896,53.646371797636 +"8","111",9.53420431030983,53.6410478464216 +"8","112",9.53640732460543,53.6344388035348 +"8","113",9.53952826152419,53.6294820213697 +"8","114",9.54191486034442,53.6265446689756 +"8","115",9.54613730441097,53.6223222249091 +"8","116",9.55091050205143,53.6186505344164 +"8","117",9.5579785062498,53.6132806870709 +"8","118",9.56183378126709,53.6113989456934 +"8","119",9.5663316021206,53.6094713081848 +"8","120",9.57257347595812,53.6059832022167 +"8","121",9.57840228461521,53.6029999536915 +"8","122",9.58377213196072,53.6004756664777 +"8","123",9.58946325222434,53.5982726521821 +"8","124",9.59552154153723,53.5958860533619 +"8","125",9.60011115465306,53.593866623591 +"8","126",9.60488435229351,53.5922143628693 +"8","127",9.61369640947589,53.589827764049 +"8","128",9.61865319164098,53.5879919188027 +"8","129",9.62360997380607,53.5861560735564 +"8","130",9.62801600239726,53.5846873973593 +"8","131",9.63875569708829,53.5810616029978 +"8","132",9.64472219413886,53.5789962770957 +"8","133",9.65472755073136,53.5750492098161 +"8","134",9.663034750471,53.5715152077169 +"8","135",9.66730309066871,53.5700006353887 +"8","136",9.67299421093234,53.5677976210931 +"8","137",9.68221933329514,53.5659158797156 +"8","138",9.68836941487034,53.5652733338794 +"8","139",9.69708967979041,53.5642636189939 +"8","140",9.70498381434962,53.5639423460758 +"8","141",9.71453020963054,53.5631621118461 +"8","142",9.72077208346806,53.5626572544034 +"8","143",9.72820725671569,53.5619229163048 +"8","144",9.7377536519966,53.5617852279114 +"8","145",9.74523472137539,53.5612344743375 +"8","146",9.75441394760704,53.5605460323701 +"8","147",9.75937072977213,53.5601788633208 +"8","148",9.77052348964358,53.5587101871238 +"8","149",9.77887658551438,53.5574709915825 +"8","150",9.79177339836984,53.5554974579427 +"8","151",9.79842833738779,53.5543041585326 +"8","152",9.81114156571862,53.5522847287616 +"8","153",9.82316635208208,53.5494391686298 +"8","154",9.82683804257474,53.5488884150559 +"8","155",9.83454859260932,53.5479704924327 +"8","156",9.83913820572515,53.5472361543342 +"8","157",9.84400319562792,53.5466395046291 +"8","158",9.85240218762987,53.5455838936125 +"8","159",9.86300419392743,53.5435644638415 +"8","160",9.87126549753591,53.5424629566937 +"8","161",9.87714020232416,53.5420957876445 +"8","162",9.89210234108175,53.5413614495459 +"8","163",9.89898676075548,53.5415450340706 +"8","164",9.91036900128272,53.5416368263329 +"8","165",9.92381656771209,53.5415450340706 +"8","166",9.92946179184455,53.5413614495459 +"8","167",9.9391917716501,53.5413614495459 +"8","168",9.93992610974863,53.5413614495459 +"8","169",9.94621387971731,53.5420957876445 +"8","170",9.95277702647294,53.5429678141365 +"8","171",9.96021219972057,53.543977529022 +"8","172",9.9662245929023,53.543977529022 +"8","173",9.97278773965793,53.5433808793169 +"8","174",9.97889192510197,53.5411778650213 +"8","175",9.98439946084096,53.5391584352504 +"8","176",9.99068723080964,53.5378274474468 +"8","177",9.99757165048337,53.5375061745287 +"8","178",10.006750876715,53.536450563512 +"8","179",10.0112028014374,53.5357621215446 +"8","180",10.0159301029467,53.5349359911838 +"8","181",10.0216212232103,53.5334673149867 +"8","182",10.0260272518015,53.5319986387897 diff --git a/mkslopes/burnShape2Topo.py b/mkslopes/burnShape2Topo.py new file mode 100755 index 0000000..d040cf6 --- /dev/null +++ b/mkslopes/burnShape2Topo.py @@ -0,0 +1,366 @@ +#!/usr/bin/env python3 +''' +author: Niklas WAGNER +e-mail: n.wagner@fz-juelich.de +version: 2021-03-18 + +Description: +burnShape2Topo.py is aimed to burn the 'correct' river-corridors on top of a +given topography. +This is needed because coarse topography resolutions poorly reflect the correct +river streams and is done in two steps: + 1) mapping the ‘correct’ river-corridors provided by official river-network + datasets (as e.g. HydroSHEDS) from shape-files onto the topography raster. + 2) lowering the topography for pixels where a river stream is detected as + well as surrounding pixel, to force the model to drain towards the correct + river-stream. + +Usage: +INPUT FILES: +- HSURF (height of surface = topo) file to burn river on +- Shapefiles holding the correct river-network (multiple files posible) +- land-lake-see mask +- target Grid (lats, lons) + +OUTPUT FILES: +- HSURF used to burn rivers on +- HSURF with burned rivers +''' +import numpy as np +import netCDF4 as nc +import sys +import os +import fiona +import datetime + +from shapely.geometry import shape +import sloth.IO + +############################################################################### +#### START OF: stuff you need to adjust! +############################################################################### +# Target grid +# - this file should contian the correct lat/lon values of the target grid +# - def the file as well the name of lat and lon variables inside +rawdata_dir = os.environ['RAWDATA_DIR'] +with nc.Dataset(f'{rawdata_dir}/EUR-11_TSMP_FZJ-IBG3_CLMPFLDomain_444x432_gridfile.nc','r') as nc_trgGridFile: + lons = nc_trgGridFile.variables['lon'][...] + lats = nc_trgGridFile.variables['lat'][...] +# - `griddesFileName` is the CDO griddes files from the .nc file above +griddesFileName = f'{rawdata_dir}/EUR-11_TSMP_FZJ-IBG3_CLMPFLDomain_444x432_griddes.txt' + +# River network shape file to burn to DEM +shapefiles = [ + f'HydroRIVERS_v10_eu_shp', + f'HydroRIVERS_v10_af_shp', + ] + +# Origin topo +# - Def how many pixels to cut from the boundary (NBCCUT) +# - - This is e.g. needed, if you take the topo or lon/lat values from COSMO, but +# - this files should contain the original topot you want to burn rivers in +# - define also the name of the topo var +# - if this file holdes you lan/lot values also, simple define the file twice +NBCCUT = 10 +nc_HSURF = nc.Dataset(f'../mklandmask/EUR-11_TSMP_FZJ-IBG3_464x452_EXTPAR.nc') +HSURF = nc_HSURF.variables['HSURF'][NBCCUT:-NBCCUT,NBCCUT:-NBCCUT] +print(f'HSURF.shape: {HSURF.shape}') +# Lans-Lake-Sea mask (LLSM) +with nc.Dataset(f'../mklandmask/EUR-11_TSMP_FZJ-IBG3_444x432_LAND-LAKE-SEA-MASK.nc', 'r') as nc_indic: + LLSM = nc_indic.variables['LLSM'][0,...] + print(f'LLSM.shape: {LLSM.shape}') +mask_lsm = np.where(LLSM<2, True, False) +############################################################################### +#### END OF: stuff you need to adjust! +############################################################################### + +def get_majorRivers(rec): + ''' filter records of shp for major rivers only. + + ORD_FLOW is a indicator within HydroSHEDS data, to distinguish rivers + into logarithmic size classes based on averaged flowrates. + This may varrii for different datasets, but should be easily adjustable. + + Important is, that this function returns the needed records of the shp + of interest only. + + INPUT: records of a shp opend with the py-lib fiona + RETURN: filtered records. + ''' + propertie = 'ORD_FLOW' + validValues = [1,2,3,4] + return rec['properties'].get(f'{propertie}') in validValues + +def spher_dist_v1(lon1, lat1, lon2, lat2, Rearth=6373): + """ calculate the spherical / haversine distance + + Source: https://www.kompf.de/gps/distcalc.html + This function is supposed to proper handle different shaped coords + latX and lonX is supposed to be passed in rad + + return 2D ndarray + """ + term1 = np.sin(lat1) * np.sin(lat2) + term2 = np.cos(lat1) * np.cos(lat2) + term3 = np.cos(lon2 - lon1) + return Rearth * np.arccos(term1+term2*term3) + +def smothFct_v1(x, strength): + ''' calculating the smooth coefficient to burn rivers. + + This function is a simple helper function for BurnRiversSmoth(). + The idea of BurnRiversSmoth() is, to push down the topography fo + rivers location and sorounding pixels. For the actual river-corridor + this effect of pushing down should be strongest and decrease with each + pixel further away from river-corridor, to 'fade the effect out'. + + INPUT + x: count of pixels away from actuall river-coridor + strength: a factor controling how strong to push topo down + RETURN + factor of reducing / pushing down topo in % (0-1) of total hight + ''' + return (1-(strength/x)) + +def smothFct_v2(denominator, nominator=2.): + ''' calculating the smooth coefficient to burn rivers. + + This function is a simple helper function for BurnRiversSmoth(). + The idea of BurnRiversSmoth() is, to push down the topography fo + rivers location and sorounding pixels. For the actual river-corridor + this effect of pushing down should be strongest and decrease with each + pixel further away from river-corridor, to 'fade the effect out'. + + INPUT + x: count of pixels away from actuall river-coridor + nominator: a factor controling how strong this fades out with x + RETURN + factor of reducing / pushing down topo in % (0-1) of fix burn-depth + ''' + return (float(nominator)/denominator) + +def extendNPix(data, N=1): + ''' simple function to increase river width + + By shiftig a binary array (a mask indicating river or not) 1-pixel north, + south, west, and east and sum up all five arrays, I do recieve an binary + array where each line (river) is 2 pixel bigger. + + INPUT + data: the binary array (rivers) + N=1 : amount of shifting the array - should be one! + RETURN + binary array (river mask) with extendes lines (rivers) + ''' + noth = np.roll(data, N, axis=0) + east = np.roll(data, N, axis=1) + south = np.roll(data, -N, axis=0) + west = np.roll(data, -N, axis=1) + data += noth + east + south + west + data[data != 0] = 1 + return data + +def BurnRiversSmoth(topo, rivers, strength=0.2, radius=10): + ''' burn rivers based on pixels actual topo height + + INPUT + topo: ndarray in target raster with topo + rivers: ndarray with binary river mask in same shape as topo (1=river; 0=no river) + strength: initial strength of burning rivers (0.1= push down river-coridors by 10% initially) + radius: number of pixel around rivers to also push down (decreased intensity) + RETURN + topo with 'burned' rivers in same shape as topo input + ''' + # copy input array to not change the original + rivers_smoth = rivers.copy() + out_topo = topo.copy() + + # actuall burning + # repeat the actuall 'burning' (reduzing of topo) for 'radius' + # with each itteration (1 pixel further away from river-corridor) + # the intensity of 'burning' is reduced by smothFct(). + for i in range(1,radius+1): + out_topo[rivers_smoth==1] *= smothFct_v1(x=i, strength=strength) + print(f'smothFct_v1: {smothFct_v1(x=i, strength=strength)}') + rivers_smoth = extendNPix(rivers_smoth, N=1) + return out_topo + +def BurnRiversSmoth_v2(topo, rivers, baseBurnDepth=10, radius=10): + ''' burn rivers by fix 'brun-depth' + + INPUT + topo: ndarray in target raster with topo + rivers: ndarray with binary river mask in same shape as topo (1=river; 0=no river) + baseBurnDepth: initial depth of burning rivers (10= push down river-coridors by 10[L] (L depends on topo units)) + radius: number of pixel around rivers to also push down (decreased intensity) + RETURN + topo with 'burned' rivers in same shape as topo input + ''' + # copy input array to not change the original + rivers_smoth = rivers.copy() + out_topo = topo.copy() + + # actuall burning + # repeat the actuall 'burning' (reduzing of topo) for 'radius' + # with each itteration (1 pixel further away from river-corridor) + # the intensity of 'burning' is reduced by smothFct(). + for i in range(1,radius+1): + out_topo[rivers_smoth==1] -= baseBurnDepth * smothFct_v2(denominator=i, nominator=2) + print(f'smothFct_v2: {smothFct_v2(denominator=i, nominator=2)}') + rivers_smoth = extendNPix(rivers_smoth, N=1) + return out_topo + +def getShapefileOnGrid(shp_file, RiverMaskIn, target_lats, target_lons): + ''' function to get shapfile entries on target grid / raster + + This is a brutforce function to bring river location from shp-file + on target raster. Therefore each entry / record of the shapefile is + itterated and marked as 'river' on a binary array (0,1) of the same shape + as to topo. The related pixel index is found via minimum spheric distance + between each record and the target lan/lot grids. + 'Riverpixel' may be marked multiple times and got overwritten if. + Depending on the nuber of rivers this may take a while! + + INPUT + shp_file: full path to shp-file (or dir/zip holding the shp-file with same name) + RiverMask: the array to be filled (have to have same shape as target_lats and target_lons) + target_lats: array of same shape as topo holding lat values for each pixel + target_lons: array of same shape as topo holding lon values for each pixel + RETURN + filled RiverMask + ''' + # init RiverMask in shape of target grid + RiverMask = RiverMaskIn + # need min/max lon/lat values to exclude shp-records outside the domain + minLon = np.nanmin(target_lons) + maxLon = np.nanmax(target_lons) + minLat = np.nanmin(target_lats) + maxLat = np.nanmax(target_lats) + + # open shp-file + with fiona.open(f'{shp_file}') as src: + # keep a filtered set of rivers only (see get_majorRivers() for details) + hits = filter(get_majorRivers, src) + + counter = 0 + # itterate ofer all records (stream segments in our case) + for ssmt in hits: + # coordinates are stored in (lon, lat) + for Plon, Plat in ssmt['geometry']['coordinates']: + # check if ssmt is in domain + # if all or msot river are inside the domain, this slows stuff + # done, but keep things faster is many rivers are outside the domain. + if not ( (minLon <= Plon <= maxLon) and (minLat <= Plat <= maxLat) ): + continue + # calculate spheric distance to all points in target grid + dist = spher_dist_v1(np.deg2rad(lons), + np.deg2rad(lats), + np.deg2rad(Plon), + np.deg2rad(Plat)) + # get index with min distance + mapped_idx = np.unravel_index(np.argmin(dist, axis=None),dist.shape) + # mark found point as river + RiverMask[mapped_idx[0], mapped_idx[1]] = 1 + # some print-steatments to let the user know the program is running... + print(f'handled point {counter:05d}: ({Plat}, {Plon})') + print(f'mapped_idx: ({mapped_idx[0]},{mapped_idx[1]})') + counter += 1 + return RiverMask + + + + +# as bringing shp file to target raster may take some time, the river-mask +# is dumped to 'RiverMask.npy' after calculation. So if you run the script +# again, it is frist tryed to open this dumped file to save some calculatio +# time. If this file is not found -> recalculate +RiverMaskFileName = './RiverMask.nc' +try: + with nc.Dataset(RiverMaskFileName, 'r') as nc_file: + RiverMask = nc_file.variables['RiverMask'][...] + print(f'RiverMask.shape: {RiverMask.shape}') +except FileNotFoundError: + RiverMask = np.zeros_like(lons.filled()) + #shapefiles are defined at the top + for shapefile in shapefiles: + RiverMask = getShapefileOnGrid(shp_file=shapefile, RiverMaskIn=RiverMask, target_lats=lats, target_lons=lons) + + descriptor = [ + f'RiverMask -- add some extra info here!', + ] + netCDFFileName = sloth.IO.createNetCDF(RiverMaskFileName, domain=griddesFileName, + author='Niklas WAGNER', contact='n.wagner@fz-juelich.de', + institution='FZJ/IBG-3', history=f'Created: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M")}', + description=' '.join(descriptor), + source='') + + with nc.Dataset(netCDFFileName, 'a') as nc_file: + nc_RiverMakse = nc_file.createVariable('RiverMask', 'i4', ('rlat', 'rlon'), + zlib=True) + nc_RiverMakse.standard_name = "RiverMask" + nc_RiverMakse.long_name = "RiverMask" + nc_RiverMakse.units = "--" + nc_RiverMakse.coordinates = "lon lat" + nc_RiverMakse.grid_mapping = "rotated_pole" + print(f'nc_RiverMakse.shape: {nc_RiverMakse.shape}') + print(f'RiverMask.shape: {RiverMask.shape}') + nc_RiverMakse[...] = RiverMask[...] + +# open HSURFBurned.nc to write new topo with burned river into +descriptor = [ + f'HSURFBurned -- original HSURF with burned major rivers', + f'Add more description here', + ] +netCDFFileName_HSURFBurned = sloth.IO.createNetCDF('./HSURFBurned.nc', domain=griddesFileName, + calcLatLon=True, + author='Niklas WAGNER', contact='n.wagner@fz-juelich.de', + institution='FZJ/IBG-3', history=f'Created: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M")}', + description=' '.join(descriptor), + source='') +netCDFFileName_HSURF = sloth.IO.createNetCDF('./HSURF.nc', domain=griddesFileName, + author='Niklas WAGNER', contact='n.wagner@fz-juelich.de', + institution='FZJ/IBG-3', history=f'Created: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M")}', + description='The origin HSURF used to burn in rivers', + source='') + +# working copys +tmp_HSURF = HSURF.copy() +tmp_HSURFBurned = HSURF.copy() +# Ofset-adjustment to avoid negativ height (lowering the topo by % is hard for negativ values) +tmp_offset = 999 +tmp_HSURFBurned[mask_lsm==False] += tmp_offset + +# Simplest way to burn rivers: set rivers to fix height. +# However this does not work well, and I guess this is because of +# how the GRAS algo in sva*-script works. +#burnHeight = 0.0 +#tmp_HSURFBurned[Rivers==1] = burnHeight +# the bit mor complex way to 'burn' rivers tot topo. For details see BurnRiversSmoth() +# and BurnRiversSmoth_v2() above +tmp_HSURFBurned = BurnRiversSmoth(topo=tmp_HSURFBurned, rivers=RiverMask, strength=0.3, radius=3) +#tmp_HSURFBurned = BurnRiversSmoth_v2(topo=tmp_HSURFBurned, rivers=RiverMask, baseBurnDepth=10, radius=10) + +# redo offset-adjustment +tmp_HSURFBurned[mask_lsm==False] -= tmp_offset +# make sure ocean is lowest point! +tmp_HSURFBurned[mask_lsm==True] = -tmp_offset - 50 + +# write results to netCDF object +with nc.Dataset(netCDFFileName_HSURFBurned, 'a') as nc_file: + nc_HSURFBurned = nc_file.createVariable('HSURFBurned', 'f8', ('rlat', 'rlon'), + zlib=True) + nc_HSURFBurned.standard_name = "HSURFBurned" + nc_HSURFBurned.long_name = "HSURFBurned" + nc_HSURFBurned.units = "m" + nc_HSURFBurned.coordinates = "lon lat" + nc_HSURFBurned.grid_mapping = "rotated_pole" + nc_HSURFBurned[...] = tmp_HSURFBurned +with nc.Dataset(netCDFFileName_HSURF, 'a') as nc_file: + nc_HSURF = nc_file.createVariable('HSURF', 'f8', ('rlat', 'rlon'), + zlib=True) + nc_HSURF.standard_name = "HSURF" + nc_HSURF.long_name = "HSURF" + nc_HSURF.units = "m" + nc_HSURF.coordinates = "lon lat" + nc_HSURF.grid_mapping = "rotated_pole" + nc_HSURF[...] = HSURF[...] diff --git a/mkslopes/create_pfl_slopes.py b/mkslopes/create_pfl_slopes.py new file mode 100755 index 0000000..9939dbc --- /dev/null +++ b/mkslopes/create_pfl_slopes.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +''' +author: Marco VAN HULTEN +e-mail: Marco.van.Hulten@uni-bonn.de +version: 2026-05-29 + +Description: +create_pfl_slopes.py creates slopes from a Digital Elevation Model (DEM). + +Usage: + ./create_pfl_slopes.py + +INPUT FILES: +- DEM (topography, HSURF) +- Shapefiles holding the correct river-network (multiple files posible) +- land-lake-see mask +- target Grid (lats, lons) + +OUTPUT FILES: +- x and y slopes +''' +import sys +from pathlib import Path +import numpy as np +import netCDF4 as nc +import priority_flow as prf +import matplotlib.pyplot as plt + +# Read into array +ncin = nc.Dataset("HSURF.nc", "r") +data = ncin.variables['HSURF'][:] +np.shape(data) + +# Write to a npy data file +np.save('data/DEM_tsmp.npy', np.array(data)) +ncin.close() + +# Load TSMP data +exec( open("tsmp_data_loader.py").read() ) +DEM_tsmp = load_dem() +DEM=DEM_tsmp[::-1] # so DEM is our direction-corrected DEM! +np.shape(DEM) +exec( open("plotting.py").read() ) + +nc_watershed_mask = nc.Dataset("../mklandmask/EUR-11_TSMP_FZJ-IBG3_444x432_LAND-LAKE-SEA-MASK.nc") +watershed_mask = nc_watershed_mask.variables['LLSM'][0,:,:] +watershed_mask[watershed_mask==2] = 1. +watershed_mask2 = watershed_mask[::-1] +_plot_inputs(watershed_mask2) + +# Flow direction +init = prf.init_queue(DEM) +trav_hs = prf.d4_traverse_b( DEM, init["queue"].copy(), + init["marked"].copy(), + basins=init["basins"].copy(), + epsilon=0, + n_chunk=10, +) +dem_diff = trav_hs["dem"] - DEM +dem_diff[dem_diff==0] - np.nan +targets = init["marked"].copy() +targets[targets==0] = np.nan +_plot_step1(trav_hs, dem_diff, targets, watershed_mask2) + +np.save("data/flow_direction.npy", trav_hs["direction"]) + +# Create the slopes +# TODO: use prf.slope_calc_upwind() for downwinding (needed in TSMP2) +slopes_std = prf.slope_calc_standard( + dem=DEM_tsmp.copy()[::-1], + direction=trav_hs["direction"], + mask=watershed_mask2.copy(), + minslope=1e-5, + maxslope=1, + dx=12000, dy=12000, + secondary_th=-1, +) +slopex = slopes_std["slopex"] +slopey = slopes_std["slopey"] +_plot_slopes(slopex, slopey) + +# Write the slope files to ParFlow pfb format +from parflow.tools.io import read_pfb, write_pfb +write_pfb("slopex.pfb", slopex) +write_pfb("slopey.pfb", slopey) +write_pfb("flow_direction.pfb", trav_hs["direction"]) diff --git a/mkslopes/modTopo.py b/mkslopes/modTopo.py new file mode 100755 index 0000000..591e16c --- /dev/null +++ b/mkslopes/modTopo.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +''' +author: Niklas WAGNER +e-mail: n.wagner@fz-juelich.de +version: 2021-03-19 + +It could be needed, that some pixel got 'adjustet' to correctly place river +streams. The thing is, that the GRASS algo in later sva* script is trying +(or forcing) to route water out of the domain. If now rivers do flow e.g. +to the blacksea, and the blacksea is (for coarse resolved topos) not +connected to the mediteraniensea, than GRASS will route water through another +way e.g. through a big river in eastern europe. Saying the flow dir of this river +is getting reverted in order to route water out of the blacksea (even ocean +pixel are masked within ParFlow). To solve this one can 'break through' the +land pixel between black and mediteraniensea, that GRAS is routing water this +way. One can think of other needed 'adjustments' which gets defined below. +''' +import numpy as np +import netCDF4 as nc +import sys +import os +import csv +from shapely.geometry import shape +import sloth.mapper +import datetime + +############################################################################### +#### START OF: stuff you need to adjust! +############################################################################### +# Topo to 'adjust' +with nc.Dataset(f'./HSURFBurned.nc', 'r') as nc_file: + HSURFin = nc_file.variables['HSURFBurned'][...] + lon2D = nc_file.variables['lon'][...] + lat2D = nc_file.variables['lat'][...] + +rawdata_dir = os.environ['RAWDATA_DIR'] +griddesFileName = f'{rawdata_dir}/EUR-11_TSMP_FZJ-IBG3_CLMPFLDomain_444x432_griddes.txt' + +netCDFFileName_HSURFBurnedAndMod = sloth.IO.createNetCDF('./HSURFBurnedAndMod.nc', + domain=griddesFileName, + calcLatLon=True, + author='Marco VAN HULTEN', + contact='Marco.van.Hulten@uni-bonn.de', + institution='Uni Bonn', + history=f'Created: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M")}', + description='HSURF with major rivers burnt and certain pixels modified', + source='') + +# pixel to adjust +# Read in vertices of regions to adjust +with open("./BurnRiversAndCanyons_Vertices_EUR11.csv", "r") as f: + ToAdjust = {} + reader = csv.reader(f, delimiter=",") + next(reader, None) # skip the headers + for line in reader: + regionID = line[0] + # check that regionID is a key in ToAdjust dict and if not create + if regionID not in ToAdjust.keys(): + ToAdjust[regionID] = {'id': [], 'lon':[], 'lat':[], + 'lonIdx':[], 'latIdx':[]} + ToAdjust[regionID]['id'].append(line[1]) + ToAdjust[regionID]['lon'].append(float(line[2])) + ToAdjust[regionID]['lat'].append(float(line[3])) + +# Initialize mapper from SLOTH +Mapper = sloth.mapper.mapper(SimLons=lon2D, SimLats=lat2D) +for regionID in ToAdjust.keys(): + Mapper.ObsLons = np.array(ToAdjust[regionID]['lon']) + Mapper.ObsLats = np.array(ToAdjust[regionID]['lat']) + Mapper.ObsIDs = np.array(ToAdjust[regionID]['id']) + # Map points to sim coords / get array index of points in sim coords + Mapper.MapRaw() + print(f'Found for regionID {regionID}:') + print(f'Mapped x index: {Mapper.MapXIdx_raw}') + print(f'Mapped y index: {Mapper.MapYIdx_raw}') + ToAdjust[regionID]['lonIdx'] = Mapper.MapXIdx_raw.tolist() + ToAdjust[regionID]['latIdx'] = Mapper.MapYIdx_raw.tolist() +# simple pass one list per 'region' to adjust with a leading ref-pixel. +# lets say you need to break through land pixel between blacksea and +# mediteraniensea. 'breaking' through is done by setting topo height of the +# pixels to break through to a ref hight - the sea hight. +#ToAdjust = [ +# [(138,339), (137,339), (136,339)], +# [(246,221),(246,220),(247,220),(247,219),(248,219),(248,218),(249,218),(249,217),(250,217),(250,216)] +# ] +############################################################################### +#### END OF: stuff you need to adjust! +############################################################################### + +tmp_out_HSURF = HSURFin.copy() +for regionID in ToAdjust: + print(f'handling regionID {regionID}') + CoordIdx = list(zip(ToAdjust[regionID]['latIdx'], ToAdjust[regionID]['lonIdx'])) + LATref, LONref = CoordIdx[0] + for Plat, Plon in CoordIdx[1:]: + print(f'handling: {Plat} | {Plon}') + tmp_out_HSURF[Plat, Plon] = tmp_out_HSURF[LATref,LONref] + +# write results to netCDF object +with nc.Dataset(netCDFFileName_HSURFBurnedAndMod, 'a') as nc_file: + nc_HSURFBurnedAndMod = nc_file.createVariable('HSURFBurnedAndMod', 'f8', ('rlat', 'rlon'), zlib=True) + nc_HSURFBurnedAndMod.standard_name = "HSURFBurnedAndMod" + nc_HSURFBurnedAndMod.long_name = "HSURFBurnedAndMod" + nc_HSURFBurnedAndMod.units = "m" + nc_HSURFBurnedAndMod.coordinates = "lon lat" + nc_HSURFBurnedAndMod.grid_mapping = "rotated_pole" + nc_HSURFBurnedAndMod[...] = tmp_out_HSURF diff --git a/mkslopes/netCDF2simpleASCII.py b/mkslopes/netCDF2simpleASCII.py new file mode 100755 index 0000000..97a7e91 --- /dev/null +++ b/mkslopes/netCDF2simpleASCII.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +from netCDF4 import Dataset +import numpy as np +import sys + +try: + fname = sys.argv[1] +except IndexError: + sys.exit(f"File and variable names needed: '{sys.argv[0]} FILE VARIABLE'") + +try: + vname = sys.argv[2] +except IndexError: + sys.exit(f"File and variable names needed: '{sys.argv[0]} FILE VARIABLE'") + +nc = Dataset(f"{fname}.nc", 'r') +var = nc.variables[f"{vname}"][:] +nc.close() +var_fortran = np.array(var, order='F') +with open(f"{fname}.sa", 'w') as f: + f.write(f"{var.shape[1]} {var.shape[1]} {var.shape[0]}\n1\n") + for val in var_fortran.flatten(): + f.write(f"{val}\n") diff --git a/mkslopes/plotting.py b/mkslopes/plotting.py new file mode 100644 index 0000000..762c92b --- /dev/null +++ b/mkslopes/plotting.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +""" +Priority Flow Workflow Example + +This script walks through a typical workflow for processing a DEM to ensure a fully +connected hydrologic drainage network. For more details on the Priority Flow tool +refer to Condon and Maxwell (2019): https://doi.org/10.1016/j.cageo.2019.01.020 + +This is a Python translation of the R vignette Workflow_Example.Rmd from the +PriorityFlow R package (https://github.com/lecondon/PriorityFlow). + +The example uses the sample watershed from Condon and Maxwell (2019). The DEM and +mask files are provided with the PriorityFlow library. +""" + +# Plot inputs (optional - requires matplotlib) +def _plot_inputs(watershed_mask): + """Plot the three input datasets.""" + fig, axes = plt.subplots(1, 3, figsize=(12, 4)) + im0 = axes[0].imshow(DEM, cmap='RdBu' ) + axes[0].set_title("Elevation") + plt.colorbar(im0, ax=axes[0]) + im1 = axes[1].imshow(watershed_mask, cmap='RdBu' ) + axes[1].set_title("Watershed Mask") + plt.colorbar(im1, ax=axes[1]) + #im2 = axes[2].imshow(river_mask, cmap='RdBu' ) + #axes[2].set_title("River Network") + #plt.colorbar(im2, ax=axes[2]) + plt.tight_layout() + plt.savefig("workflow_inputs.png", dpi=150) + plt.close() + + +def _plot_step1(trav_hs, dem_diff, targets, watershed_mask): + """Plot DEM processing results.""" + fig, axes = plt.subplots(2, 2, figsize=(10, 8)) + axes[0, 0].imshow(np.where(np.isnan(targets), 0, 1)) + axes[0, 0].set_title("Target Points") + im1 = axes[0, 1].imshow(trav_hs["dem"]) + axes[0, 1].set_title("Processed DEM") + plt.colorbar(im1, ax=axes[0, 1]) + im2 = axes[1, 0].imshow(dem_diff) + axes[1, 0].set_title("DEM differences") + plt.colorbar(im2, ax=axes[1, 0]) + im3 = axes[1, 1].imshow(trav_hs["direction"]/watershed_mask) + axes[1, 1].set_title("Flow Direction") + plt.colorbar(im3, ax=axes[1, 1]) + plt.tight_layout() + plt.savefig("workflow_step1.png", dpi=150) + plt.close() + + +def _plot_stream_network( + subbasin: dict, + stream_order: dict, +) -> None: + """Plot stream segments, stream order, and subbasins (like R par(mfrow=c(1,3))).""" + fig, axes = plt.subplots(1, 3, figsize=(14, 5)) + im0 = axes[0].imshow(subbasin["segments"], cmap="nipy_spectral") + axes[0].set_title("Stream Segments") + plt.colorbar(im0, ax=axes[0], label="Segment ID") + im1 = axes[1].imshow(stream_order["order_mask"], cmap="viridis") + axes[1].set_title("Stream Order") + plt.colorbar(im1, ax=axes[1], label="Strahler order") + im2 = axes[2].imshow(subbasin["subbasins"], cmap="nipy_spectral") + axes[2].set_title("Subbasins") + plt.colorbar(im2, ax=axes[2], label="Subbasin ID") + plt.tight_layout() + plt.savefig("workflow_stream_network.png", dpi=150) + plt.close() + +# Plot elevation differences from river smoothing +def _plot_step2(): + """Plot river smoothing results.""" + dif = riv_smooth_result["dem.adj"] - trav_hs["dem"] + riv_mask = np.where(subbasin["segments"] > 0, 1, 0) + hill_mask = 1 - riv_mask + dif_hill = dif * hill_mask + dif_riv = dif * riv_mask + + dif_plot = np.where(dif == 0, np.nan, dif) + dif_riv_plot = np.where(dif_riv == 0, np.nan, dif_riv) + dif_hill_plot = np.where(dif_hill == 0, np.nan, dif_hill) + + fig, axes = plt.subplots(1, 3, figsize=(12, 4)) + im0 = axes[0].imshow(dif_plot) + axes[0].set_title("All Elev. Diffs") + plt.colorbar(im0, ax=axes[0]) + im1 = axes[1].imshow(dif_riv_plot) + axes[1].set_title("Stream Cell Diffs") + plt.colorbar(im1, ax=axes[1]) + if np.any(~np.isnan(dif_hill_plot)): + im2 = axes[2].imshow(dif_hill_plot) + axes[2].set_title("Non-Stream Cell Diffs") + plt.colorbar(im2, ax=axes[2]) + plt.tight_layout() + plt.savefig("workflow_step2_smoothing.png", dpi=150) + plt.close() + + +def _plot_path_transect( + transect_old: np.ndarray, + transect_new: np.ndarray, + transect_riv: np.ndarray, + subbasin: dict, + streamline_riv: dict, + segment: int, +) -> None: + """ + Plot elevation transects and path map along a selected stream segment + (Python analogue of the R PathExtract plotting block). + """ + nstep = len(transect_riv) + x = np.arange(1, nstep + 1) + + # Find breaks between stream segments along the path + if nstep > 1: + tr = np.asarray(transect_riv).ravel() + diff_mask = tr[1:] != tr[:-1] + slist = np.where(diff_mask)[0] + 1.5 # between steps k and k+1 + else: + slist = [] + + # Elevation limits across old/new transects + all_vals = np.concatenate( + [np.asarray(transect_old).ravel(), np.asarray(transect_new).ravel()] + ) + vmin = np.nanmin(all_vals) + vmax = np.nanmax(all_vals) + + fig, axes = plt.subplots(1, 2, figsize=(12, 4)) + + # Left: elevation transects + ax0 = axes[0] + ax0.plot(x, transect_old, color="C0", lw=2, label="Old Elevations") + ax0.plot(x, transect_new, color="C2", lw=2, label="New Elevations") + ax0.set_xlim(1, max(1, nstep)) + ax0.set_ylim(vmin, vmax) + for s in slist: + ax0.axvline(s, color="k", linestyle="--", linewidth=1) + ax0.set_xlabel("Step") + ax0.set_ylabel("Elevation") + ax0.legend(loc="lower left", frameon=False) + + # Right: path map over stream network + ax1 = axes[1] + segment_plot = np.where(subbasin["segments"] > 0, 1, 0) + ax1.imshow(segment_plot, cmap="gray_r", vmin=0, vmax=1) + ax1.set_title(f"Path Map (segment {segment + 1})") + + path_mask = streamline_riv["path_mask"] + path_overlay = np.where(path_mask == 0, np.nan, path_mask) + ax1.imshow(path_overlay, cmap="Reds", alpha=0.8) + + plt.tight_layout() + plt.savefig("workflow_path_transect.png", dpi=150) + plt.close() + + +def _plot_slopes(slopex: np.ndarray, slopey: np.ndarray) -> None: + """ + Plot resulting slopes in x and y directions (R analogue: image.plot of sxplot, syplot). + """ + sxplot = np.where(slopex == 0, np.nan, slopex) + syplot = np.where(slopey == 0, np.nan, slopey) + + fig, axes = plt.subplots(1, 2, figsize=(10, 4)) + + im0 = axes[0].imshow(sxplot, cmap="RdBu") + axes[0].set_title("SlopeX (primary & secondary)") + plt.colorbar(im0, ax=axes[0]) + + im1 = axes[1].imshow(syplot, cmap="RdBu") + axes[1].set_title("SlopeY (primary & secondary)") + plt.colorbar(im1, ax=axes[1]) + + plt.tight_layout() + plt.savefig("workflow_slopes.png", dpi=150) + plt.close() + +def write_parflow_ascii(data: np.ndarray, filepath: str) -> None: + """ + Write a 2D array in ParFlow ASCII format. + Format: header line with nx, ny, 1 followed by flattened data. + """ + nx, ny = data.shape + flat = np.zeros(nx * ny) + jj = 0 + for j in range(ny): + for i in range(nx): + flat[jj] = data[i, j] + jj += 1 + with open(filepath, "w") as f: + f.write(f"{nx} {ny} 1\n") + for val in flat: + f.write(f"{val}\n") + diff --git a/mkslopes/simpleASCII2netCDF.py b/mkslopes/simpleASCII2netCDF.py new file mode 100755 index 0000000..52956c8 --- /dev/null +++ b/mkslopes/simpleASCII2netCDF.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +from netCDF4 import Dataset +import numpy as np +import sys + +try: + sa_file = sys.argv[1] +except IndexError: + sys.exit(f"File and variable names needed: '{sys.argv[0]} FILE VARIABLE'") + +try: + vname = sys.argv[2] +except IndexError: + sys.exit(f"File and variable names needed: '{sys.argv[0]} FILE VARIABLE'") + +# Load ParFlow simple ASCII data +with open(sa_file, 'r') as f: + nx, ny, nz = map(int, f.readline().split()) +var = np.loadtxt(sa_file, skiprows=1) +myvar = var.reshape((nx, ny, nz), order='C') + +# Write to netCDF +nc_file = f"{vname}.nc" +with Dataset(nc_file, 'w', format='NETCDF4') as nc: + nc.createDimension('lon', nx) + nc.createDimension('lat', ny) + nc.createDimension('time', nz) + nc.description = 'Converted from ParFlow simple ASCII to netCDF' + var = nc.createVariable(f'{vname}', 'f4', ('time', 'lat', 'lon')) + var[:] = myvar diff --git a/mkslopes/tsmp_data_loader.py b/mkslopes/tsmp_data_loader.py new file mode 100644 index 0000000..f394843 --- /dev/null +++ b/mkslopes/tsmp_data_loader.py @@ -0,0 +1,141 @@ +""" +Data loading functions for PriorityFlow package. + +This module provides functions to load the test data files that were converted +from the R package's TestDomain_Inputs directory. +""" + +import numpy as np +import os +from pathlib import Path + +# Get the directory where this module is located +_MODULE_DIR = Path(__file__).parent +_DATA_DIR = Path("./data") + +def load_dem(): + """ + Load the Digital Elevation Model (DEM) EUR-11 data. + + Returns + ------- + numpy.ndarray + A 2D array of elevation values with shape (432, 444). + + Examples + -------- + >>> import priority_flow.data_loader as dl + >>> dem = dl.load_dem() + >>> print(f"DEM shape: {dem.shape}") + >>> print(f"Elevation range: {dem.min():.2f} to {dem.max():.2f}") + """ + data_path = _DATA_DIR / "DEM_tsmp.npy" + if not data_path.exists(): + raise FileNotFoundError(f"DEM data file not found at {data_path}") + + return np.load(data_path) + +def load_watershed_mask(): + """ + Load the watershed mask test data. + + A mask showing the watershed drainage area for the test domain. + + Returns + ------- + numpy.ndarray + A 2D array of 0's and 1's showing the watershed extent + (1=inside the watershed, 0=outside the watershed) with shape (215, 172). + + Examples + -------- + >>> import priority_flow.data_loader as dl + >>> mask = dl.load_watershed_mask() + >>> print(f"Watershed mask shape: {mask.shape}") + >>> print(f"Watershed cells: {np.sum(mask)}") + """ + data_path = _DATA_DIR / "watershed_mask_tsmp.npy" + if not data_path.exists(): + raise FileNotFoundError(f"Watershed mask data file not found at {data_path}") + + return np.load(data_path) + +def load_river_mask(): + """ + Load the river mask test data. + + A mask showing an example river network for the test domain. + + Returns + ------- + numpy.ndarray + A 2D array of 0's and 1's showing the location of river cells + (1=river, 0=non-river) with shape (215, 172). + + Examples + -------- + >>> import priority_flow.data_loader as dl + >>> river_mask = dl.load_river_mask() + >>> print(f"River mask shape: {river_mask.shape}") + >>> print(f"River cells: {np.sum(river_mask)}") + """ + data_path = _DATA_DIR / "river_mask_tsmp.npy" + if not data_path.exists(): + raise FileNotFoundError(f"River mask data file not found at {data_path}") + + return np.load(data_path) + +def load_all_test_data(): + """ + Load all test data files at once. + + Returns + ------- + dict + A dictionary containing all test data arrays with keys: + - 'dem': Digital Elevation Model + - 'watershed_mask': Watershed drainage area mask + - 'river_mask': River network mask + + Examples + -------- + >>> import priority_flow.data_loader as dl + >>> data = dl.load_all_test_data() + >>> print(f"Available data: {list(data.keys())}") + >>> print(f"DEM shape: {data['dem'].shape}") + """ + return { + 'dem': load_dem(), + 'watershed_mask': load_watershed_mask(), + 'river_mask': load_river_mask() + } + +def get_data_info(): + """ + Get information about the available test data files. + + Returns + ------- + dict + A dictionary containing metadata about each data file. + """ + info = {} + + for name, load_func in [('DEM', load_dem), + ('Watershed Mask', load_watershed_mask), + ('River Mask', load_river_mask)]: + try: + data = load_func() + info[name] = { + 'shape': data.shape, + 'dtype': str(data.dtype), + 'min': float(data.min()), + 'max': float(data.max()), + 'size': data.size + } + except FileNotFoundError as e: + info[name] = {'error': str(e)} + + return info + + diff --git a/mksolids/createPfbMask.py b/mksolids/createPfbMask.py new file mode 100755 index 0000000..2dd67a5 --- /dev/null +++ b/mksolids/createPfbMask.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +import netCDF4 as nc +import numpy as np +import matplotlib as mpl +import matplotlib.pyplot as plt + +import sloth.IO + +LLSMFileName = '../mklandmask/EUR-11_TSMP_FZJ-IBG3_444x432_LAND-LAKE-SEA-MASK.nc' +LLSMVarName = 'LLSM' + +with nc.Dataset(LLSMFileName, "r") as nc_file: + LLSM = nc_file.variables[LLSMVarName][0,...] + +ny, nx = LLSM.shape +nz = 15 +dy = dx = 12500.0 +dz = 2.0 + +# write PFBMask: +# 0 where LLSM is land or leak +# 1 where LLSM is ocean +PFBMask = np.where((LLSM<1), 0, 1) +print(f'PFBMask.shape: {PFBMask.shape}') + +plt.imshow(PFBMask, origin='lower', interpolation='none') +plt.colorbar() +plt.savefig('./PFBMask.pdf') + +## Broadcast PFBMask from (y,x) to (z,y,x) +#PFBMask = np.broadcast_to(PFBMask, (nz, ny, nx)) +#print(f'PFBMask.shape: {PFBMask.shape}') + +# save as .pfb +PFBMaskFileName = './PfbMask4SolidFile.pfb' +#sloth.IO.create_pfb(PFBMaskFileName, PFBMask[...], delta=(dz,dy,dx)) +sloth.IO.create_pfb(PFBMaskFileName, PFBMask[np.newaxis,...], delta=(dz,dy,dx))