nfdata 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- config.create.example.yaml +228 -0
- config.edit.example.yaml +14 -0
- environment.yaml +13 -0
- nfdata/__init__.py +9 -0
- nfdata/compiler.py +700 -0
- nfdata/console.py +32 -0
- nfdata/land_use.default.yaml +58 -0
- nfdata/model_vars.yaml +224 -0
- nfdata/router.py +111 -0
- nfdata-0.1.0.dist-info/METADATA +104 -0
- nfdata-0.1.0.dist-info/RECORD +13 -0
- nfdata-0.1.0.dist-info/WHEEL +4 -0
- nfdata-0.1.0.dist-info/entry_points.txt +3 -0
nfdata/console.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""NanoFASE data is responsible for compiling and editing data for use in NanoFASE model."""
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
import argparse
|
|
6
|
+
import importlib.resources as pkg_resources
|
|
7
|
+
from .compiler import Compiler
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def run():
|
|
11
|
+
parser = argparse.ArgumentParser(description='Compile or edit data for the NanoFASE model.')
|
|
12
|
+
parser.add_argument('task',
|
|
13
|
+
help='do you wish to create from scratch, edit the data or create a constants file?',
|
|
14
|
+
choices=['create', 'edit', 'constants'])
|
|
15
|
+
parser.add_argument('file', help='path to the config file (create/edit tasks) or constants file (constants task)')
|
|
16
|
+
parser.add_argument('--output', '-o', help='where to create the new constants file (for constants task)')
|
|
17
|
+
args = parser.parse_args()
|
|
18
|
+
|
|
19
|
+
if args.task == 'constants':
|
|
20
|
+
# If we're just compiling the constants file, just call the static create_constants method
|
|
21
|
+
Compiler.create_constants(args.file, args.output)
|
|
22
|
+
else:
|
|
23
|
+
# Create the compiler. We use model_vars.yaml as included in the package
|
|
24
|
+
model_vars_path = pkg_resources.files(__package__).joinpath('model_vars.yaml')
|
|
25
|
+
compiler = Compiler(args.task, args.file, model_vars_path)
|
|
26
|
+
# Do we want to compile from scratch or edit a pre-exiting file?
|
|
27
|
+
if args.task == 'create':
|
|
28
|
+
# Run the data compilation
|
|
29
|
+
compiler.create()
|
|
30
|
+
elif args.task == 'edit':
|
|
31
|
+
# Edit the variables given in the config file
|
|
32
|
+
compiler.edit()
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
111: # Continuous urban fabric
|
|
2
|
+
- [ 'urban_no_soil', 0.7 ]
|
|
3
|
+
- [ 'urban_green_residential', 0.3 ]
|
|
4
|
+
112: # Discontinous urban fabric
|
|
5
|
+
- [ 'urban_no_soil', 0.4 ]
|
|
6
|
+
- [ 'urban_green_residential', 0.6 ]
|
|
7
|
+
121: # Industrial or commerical units
|
|
8
|
+
- [ 'urban_no_soil', 0.5 ]
|
|
9
|
+
- [ 'urban_industrial_soil', 0.5 ]
|
|
10
|
+
122: # Road and rail networks
|
|
11
|
+
- [ 'urban_no_soil', 0.4 ]
|
|
12
|
+
- [ 'urban_industrial_soil', 0.6 ]
|
|
13
|
+
123: # Port areas
|
|
14
|
+
- [ 'urban_no_soil', 0.6 ]
|
|
15
|
+
- [ 'urban_industrial_soil', 0.4 ]
|
|
16
|
+
124: # Airports
|
|
17
|
+
- ['urban_no_soil', 0.2]
|
|
18
|
+
- ['urban_industrial_soil', 0.8]
|
|
19
|
+
131: [ 'urban_industrial_soil' ] # Mineral extraction
|
|
20
|
+
132: [ 'urban_industrial_soil' ] # Dump sites
|
|
21
|
+
133: [ 'urban_industrial_soil' ] # Construction sites
|
|
22
|
+
141: [ 'urban_parks_leisure' ] # Green urban areas
|
|
23
|
+
142: [ 'urban_parks_leisure' ] # Sport and leisure facilities
|
|
24
|
+
211: [ 'arable' ] # Non-irrigated arable land
|
|
25
|
+
212: [ 'arable' ] # Permanently irrigated land
|
|
26
|
+
213: [ 'arable' ] # Rice fields
|
|
27
|
+
221: [ 'arable' ] # Vineyards
|
|
28
|
+
222: [ 'arable' ] # Fruit trees and berry plantations
|
|
29
|
+
223: [ 'arable' ] # Olive groves
|
|
30
|
+
231: [ 'arable' ] # Pastures
|
|
31
|
+
241: [ 'arable' ] # Annual crops associated with permanent crops
|
|
32
|
+
242: [ 'arable' ] # Complex cultivation patterns
|
|
33
|
+
243: [ 'arable' ] # Land principally occupied by agriculture, with significant areas of natural vegetation
|
|
34
|
+
244: [ 'arable' ] # Agro-forestry areas
|
|
35
|
+
311: [ 'deciduous' ] # Deciduous woodland
|
|
36
|
+
312: [ 'coniferous' ] # Coniferous woodland
|
|
37
|
+
313: # Mixed forests
|
|
38
|
+
- [ 'deciduous', 0.5 ]
|
|
39
|
+
- [ 'coniferous', 0.5 ]
|
|
40
|
+
321: [ 'grassland' ] # Natural grassland
|
|
41
|
+
322: [ 'heathland' ] # Moors and heathland
|
|
42
|
+
323: [ 'heathland' ] # Sclerophyllous vegetation
|
|
43
|
+
324: [ 'heathland' ] # Transitional woodland/scrub
|
|
44
|
+
331: [ 'desert' ] # Beaches, dunes, sands
|
|
45
|
+
332: [ 'other' ] # Bare rock
|
|
46
|
+
333: [ 'heathland' ] # Sparsely vegetated areas
|
|
47
|
+
334: [ 'heathland' ] # Burnt areas
|
|
48
|
+
335: [ 'other' ] # Glaciers and perpetual snow
|
|
49
|
+
411: [ 'other' ] # Inland marshes
|
|
50
|
+
412: [ 'heathland' ] # Peatbogs
|
|
51
|
+
421: [ 'other' ] # Salt marshes
|
|
52
|
+
422: [ 'other' ] # Salines
|
|
53
|
+
423: [ 'other' ] # Intertidal flats
|
|
54
|
+
511: [ 'water' ] # Water courses
|
|
55
|
+
512: [ 'water' ] # Water bodies
|
|
56
|
+
521: [ 'water' ] # Coastal lagoons
|
|
57
|
+
522: [ 'water' ] # Estuaries
|
|
58
|
+
523: [ 'water' ] # Sea and ocean
|
nfdata/model_vars.yaml
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# The model_vars.yaml file is an internal file that describes the input variables required by the
|
|
2
|
+
# NanoFASE model and those that should be compiled by the nanofase-data script. *You should not need
|
|
3
|
+
# to edit anything in this file*, but the standard_name, long_name and comment properties are passed
|
|
4
|
+
# as variable attributes to the compiled NetCDF file, so feel free to edit these. Editing other
|
|
5
|
+
# properties will likely break something.
|
|
6
|
+
|
|
7
|
+
# Meteorological and hydrological
|
|
8
|
+
dem:
|
|
9
|
+
standard_name: height_above_mean_sea_level
|
|
10
|
+
to_units: dm
|
|
11
|
+
dims: ['y', 'x']
|
|
12
|
+
vartype: int32
|
|
13
|
+
quickflow:
|
|
14
|
+
standard_name: surface_runoff_flux
|
|
15
|
+
to_units: m/timestep
|
|
16
|
+
fill_value: 0
|
|
17
|
+
clip: [0.0, None]
|
|
18
|
+
dims: ['t', 'y', 'x']
|
|
19
|
+
runoff:
|
|
20
|
+
standard_name: runoff_flux
|
|
21
|
+
to_units: m/timestep
|
|
22
|
+
fill_value: 0
|
|
23
|
+
clip: [0.0, None]
|
|
24
|
+
dims: ['t', 'y', 'x']
|
|
25
|
+
precip:
|
|
26
|
+
standard_name: rainfall_flux
|
|
27
|
+
to_units: m/timestep
|
|
28
|
+
comment: Rainfall amount (kg m-2) is equivalent to the rainfall depth (mm)
|
|
29
|
+
dims: ['t', 'y', 'x']
|
|
30
|
+
vartype: f8
|
|
31
|
+
|
|
32
|
+
# Soil
|
|
33
|
+
soil_bulk_density:
|
|
34
|
+
long_name: bulk density of soil
|
|
35
|
+
to_units: kg/m**3
|
|
36
|
+
dims: ['y', 'x']
|
|
37
|
+
soil_water_content_field_capacity:
|
|
38
|
+
standard_name: volume_fraction_of_condensed_water_in_soil_at_field_capacity
|
|
39
|
+
to_units: cm**3/cm**3
|
|
40
|
+
dims: ['y', 'x']
|
|
41
|
+
soil_water_content_saturation:
|
|
42
|
+
standard_name: volume_fraction_of_condensed_water_in_soil
|
|
43
|
+
long_name: water content of soil at saturation
|
|
44
|
+
to_units: cm**3/cm**3
|
|
45
|
+
dims: ['y', 'x']
|
|
46
|
+
soil_hydraulic_conductivity:
|
|
47
|
+
standard_name: soil_hydraulic_conductivity_at_saturation
|
|
48
|
+
to_units: m/s
|
|
49
|
+
dims: ['y', 'x']
|
|
50
|
+
soil_texture_clay_content:
|
|
51
|
+
standard_name: volume_fraction_of_clay_in_soil
|
|
52
|
+
to_units: kg/kg
|
|
53
|
+
dims: ['y', 'x']
|
|
54
|
+
soil_texture_sand_content:
|
|
55
|
+
standard_name: volume_fraction_of_sand_in_soil
|
|
56
|
+
to_units: kg/kg
|
|
57
|
+
dims: ['y', 'x']
|
|
58
|
+
soil_texture_silt_content:
|
|
59
|
+
standard_name: volume_fraction_of_silt_in_soil
|
|
60
|
+
to_units: kg/kg
|
|
61
|
+
dims: ['y', 'x']
|
|
62
|
+
soil_texture_coarse_frag_content:
|
|
63
|
+
long_name: coarse fragment content of soil
|
|
64
|
+
to_units: kg/kg
|
|
65
|
+
dims: ['y', 'x']
|
|
66
|
+
soil_attachment_rate:
|
|
67
|
+
long_name: rate of attachment of nanomaterial to soil matrix
|
|
68
|
+
to_units: s**-1
|
|
69
|
+
dims: ['y', 'x']
|
|
70
|
+
soil_usle_c_factor:
|
|
71
|
+
long_name: Universal Soil Loss Equation C-factor
|
|
72
|
+
to_units: ''
|
|
73
|
+
dims: ['y', 'x']
|
|
74
|
+
soil_usle_p_factor:
|
|
75
|
+
long_name: Universal Soil Loss Equation P-factor
|
|
76
|
+
to_units: ''
|
|
77
|
+
dims: ['y', 'x']
|
|
78
|
+
soil_usle_ls_factor:
|
|
79
|
+
long_name: Universal Soil Loss Equation LS-factor
|
|
80
|
+
to_units: ''
|
|
81
|
+
dims: ['y', 'x']
|
|
82
|
+
|
|
83
|
+
# Suspended sediment
|
|
84
|
+
bank_erosion_alpha:
|
|
85
|
+
long_name: linear calibration parameter controlling the rate of bank erosion
|
|
86
|
+
to_units: 'kg/m**5'
|
|
87
|
+
dims: ['y', 'x']
|
|
88
|
+
bank_erosion_beta:
|
|
89
|
+
long_name: calibration parameter controlling the rate of bank erosion
|
|
90
|
+
to_units: ''
|
|
91
|
+
dims: ['y', 'x']
|
|
92
|
+
deposition_alpha:
|
|
93
|
+
long_name: calibration parameter controlling the rate of sediment deposition
|
|
94
|
+
to_units: ''
|
|
95
|
+
dims: ['y', 'x']
|
|
96
|
+
deposition_beta:
|
|
97
|
+
long_name: calibration parameter controlling the rate of sediment deposition
|
|
98
|
+
to_units: ''
|
|
99
|
+
dims: ['y', 'x']
|
|
100
|
+
resuspension_alpha:
|
|
101
|
+
long_name: shear velocity calibration parameter controlling the rate of sediment resuspension
|
|
102
|
+
to_units: ''
|
|
103
|
+
dims: ['y', 'x']
|
|
104
|
+
resuspension_beta:
|
|
105
|
+
long_name: resuspension calibration parameter controlling the rate of sediment resuspension
|
|
106
|
+
to_units: 's**2/kg'
|
|
107
|
+
dims: ['y', 'x']
|
|
108
|
+
sediment_transport_a:
|
|
109
|
+
long_name: sediment transport capacity scaling factor
|
|
110
|
+
to_units: 'kg m**-2 km**-2'
|
|
111
|
+
dims: ['y', 'x']
|
|
112
|
+
sediment_transport_c:
|
|
113
|
+
long_name: sediment transport capacity non-linear coefficient
|
|
114
|
+
to_units: ''
|
|
115
|
+
dims: ['y', 'x']
|
|
116
|
+
|
|
117
|
+
# Land use
|
|
118
|
+
land_use:
|
|
119
|
+
long_name: land use categorised by NanoFASE model land use categories
|
|
120
|
+
to_units: ''
|
|
121
|
+
dims: ['l', 'y', 'x']
|
|
122
|
+
cats:
|
|
123
|
+
- urban_no_soil
|
|
124
|
+
- urban_parks_leisure
|
|
125
|
+
- urban_industrial_soil
|
|
126
|
+
- urban_green_residential
|
|
127
|
+
- arable
|
|
128
|
+
- grassland
|
|
129
|
+
- deciduous
|
|
130
|
+
- coniferous
|
|
131
|
+
- heathland
|
|
132
|
+
- water
|
|
133
|
+
- desert
|
|
134
|
+
- other
|
|
135
|
+
is_estuary:
|
|
136
|
+
long_name: is waterbody in this cell an estuary
|
|
137
|
+
to_units: ''
|
|
138
|
+
dims: ['y', 'x']
|
|
139
|
+
vartype: u1
|
|
140
|
+
clip: [None, 100]
|
|
141
|
+
|
|
142
|
+
# Emissions - areal
|
|
143
|
+
emissions_areal_soil_pristine:
|
|
144
|
+
long_name: mass flux of pristine nanomaterial into soil
|
|
145
|
+
to_units: kg/m**2/timestep
|
|
146
|
+
dims: ['y', 'x']
|
|
147
|
+
emissions_areal_soil_matrixembedded:
|
|
148
|
+
long_name: mass flux of matrix-embedded nanomaterial into soil
|
|
149
|
+
to_units: kg/m**2/timestep
|
|
150
|
+
dims: ['y', 'x']
|
|
151
|
+
emissions_areal_soil_transformed:
|
|
152
|
+
long_name: mass flux of transformed nanomaterial into soil
|
|
153
|
+
to_units: kg/m**2/timestep
|
|
154
|
+
dims: ['y', 'x']
|
|
155
|
+
emissions_areal_soil_dissolved:
|
|
156
|
+
long_name: mass flux of dissolved nanomaterial into soil
|
|
157
|
+
to_units: kg/m**2/timestep
|
|
158
|
+
dims: ['y', 'x']
|
|
159
|
+
emissions_areal_water_pristine:
|
|
160
|
+
long_name: mass flux of pristine nanomaterial into surface waters
|
|
161
|
+
to_units: kg/m**2/timestep
|
|
162
|
+
dims: ['y', 'x']
|
|
163
|
+
emissions_areal_water_matrixembedded:
|
|
164
|
+
long_name: mass flux of matrix-embedded nanomaterial into surface waters
|
|
165
|
+
to_units: kg/m**2/timestep
|
|
166
|
+
dims: ['y', 'x']
|
|
167
|
+
emissions_areal_water_transformed:
|
|
168
|
+
long_name: mass flux of transformed nanomaterial into surface waters
|
|
169
|
+
to_units: kg/m**2/timestep
|
|
170
|
+
dims: ['y', 'x']
|
|
171
|
+
emissions_areal_water_dissolved:
|
|
172
|
+
long_name: mass flux of dissolved nanomaterial into surface waters
|
|
173
|
+
to_units: kg/m**2/timestep
|
|
174
|
+
dims: ['y', 'x']
|
|
175
|
+
|
|
176
|
+
# Emissions - point
|
|
177
|
+
emissions_point_water_pristine:
|
|
178
|
+
long_name: mass transport of pristine nanomaterial into surface waters from point sources
|
|
179
|
+
to_units: kg/timestep
|
|
180
|
+
dims: ['p', 't', 'y', 'x']
|
|
181
|
+
emissions_point_water_matrixembedded:
|
|
182
|
+
long_name: mass transport of matrix-embedded nanomaterial into surface waters from point sources
|
|
183
|
+
to_units: kg/timestep
|
|
184
|
+
dims: ['p', 't', 'y', 'x']
|
|
185
|
+
emissions_point_water_transformed:
|
|
186
|
+
long_name: mass transport of pristine nanomaterial into surface waters from point sources
|
|
187
|
+
to_units: kg/timestep
|
|
188
|
+
dims: ['p', 't', 'y', 'x']
|
|
189
|
+
emissions_point_water_dissolved:
|
|
190
|
+
long_name: mass transport of pristine nanomaterial into surface waters from point sources
|
|
191
|
+
to_units: kg/timestep
|
|
192
|
+
dims: ['p', 't', 'y', 'x']
|
|
193
|
+
|
|
194
|
+
# Emissions - atmospheric
|
|
195
|
+
emissions_atmospheric_drydepo_pristine:
|
|
196
|
+
standard_name: tendency_of_atmosphere_mass_content_due_to_dry_deposition
|
|
197
|
+
long_name: tendency of atmosphere mass content of pristine nanomaterial due to dry deposition
|
|
198
|
+
to_units: kg/m**2/timestep
|
|
199
|
+
dims: ['t', 'y', 'x']
|
|
200
|
+
emissions_atmospheric_drydepo_matrixembedded:
|
|
201
|
+
standard_name: tendency_of_atmosphere_mass_content_due_to_dry_deposition
|
|
202
|
+
long_name: tendency of atmosphere mass content of matrix-embedded nanomaterial due to dry deposition
|
|
203
|
+
to_units: kg/m**2/timestep
|
|
204
|
+
dims: ['t', 'y', 'x']
|
|
205
|
+
emissions_atmospheric_drydepo_transformed:
|
|
206
|
+
standard_name: tendency_of_atmosphere_mass_content_due_to_dry_deposition
|
|
207
|
+
long_name: tendency of atmosphere mass content of transformed nanomaterial due to dry deposition
|
|
208
|
+
to_units: kg/m**2/timestep
|
|
209
|
+
dims: ['t', 'y', 'x']
|
|
210
|
+
emissions_atmospheric_wetdepo_pristine:
|
|
211
|
+
standard_name: tendency_of_atmosphere_mass_content_due_to_wet_deposition
|
|
212
|
+
long_name: tendency of atmosphere mass content of pristine nanomaterial due to wet deposition
|
|
213
|
+
to_units: kg/m**2/timestep
|
|
214
|
+
dims: ['t', 'y', 'x']
|
|
215
|
+
emissions_atmospheric_wetdepo_matrixembedded:
|
|
216
|
+
standard_name: tendency_of_atmosphere_mass_content_due_to_wet_deposition
|
|
217
|
+
long_name: tendency of atmosphere mass content of matrix-embedded nanomaterial due to wet deposition
|
|
218
|
+
to_units: kg/m**2/timestep
|
|
219
|
+
dims: ['t', 'y', 'x']
|
|
220
|
+
emissions_atmospheric_wetdepo_transformed:
|
|
221
|
+
standard_name: tendency_of_atmosphere_mass_content_due_to_wet_deposition
|
|
222
|
+
long_name: tendency of atmosphere mass content of transformed nanomaterial due to wet deposition
|
|
223
|
+
to_units: kg/m**2/timestep
|
|
224
|
+
dims: ['t', 'y', 'x']
|
nfdata/router.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Router:
|
|
5
|
+
"""The Router class is responsible for using the flow direction raster to route water bodies within the
|
|
6
|
+
model domain, setting variables required by the NanoFASE model, such as inflows, outflows and headwaters."""
|
|
7
|
+
|
|
8
|
+
def __init__(self, flow_dir):
|
|
9
|
+
"""Initiliase the routing class with the flow direction array."""
|
|
10
|
+
self.flow_dir = flow_dir
|
|
11
|
+
self.grid_mask = self.flow_dir.mask
|
|
12
|
+
|
|
13
|
+
def outflow_from_flow_dir(self, x, y):
|
|
14
|
+
"""Get the outflow cell reference given the current cell
|
|
15
|
+
reference and a flow direction."""
|
|
16
|
+
xy_out = {
|
|
17
|
+
1: [x+1, y],
|
|
18
|
+
2: [x+1, y+1],
|
|
19
|
+
4: [x, y+1],
|
|
20
|
+
8: [x-1, y+1],
|
|
21
|
+
16: [x-1, y],
|
|
22
|
+
32: [x-1, y-1],
|
|
23
|
+
64: [x, y-1],
|
|
24
|
+
128: [x+1, y-1]
|
|
25
|
+
}
|
|
26
|
+
return xy_out[self.flow_dir[y-1, x-1]]
|
|
27
|
+
|
|
28
|
+
def inflows_from_flow_dir(self, x, y):
|
|
29
|
+
"""Get the inflow cell references given the current cell
|
|
30
|
+
reference and a flow direction."""
|
|
31
|
+
j, i = y - 1, x - 1
|
|
32
|
+
# Flow direction that means the cell with indices inflows[j_n-j, i_n-i]
|
|
33
|
+
# flows into this cell
|
|
34
|
+
inflow_flow_dir = {
|
|
35
|
+
(-1, -1): 2,
|
|
36
|
+
(0, -1): 1,
|
|
37
|
+
(1, -1): 128,
|
|
38
|
+
(-1, 0): 4,
|
|
39
|
+
(0, 0): 0,
|
|
40
|
+
(1, 0): 64,
|
|
41
|
+
(-1, 1): 8,
|
|
42
|
+
(0, 1): 16,
|
|
43
|
+
(1, 1): 32
|
|
44
|
+
}
|
|
45
|
+
inflow_cells = []
|
|
46
|
+
# Loop through the neighbours and check if they're inflows to this cell
|
|
47
|
+
for j_n in range(j-1, j+2):
|
|
48
|
+
for i_n in range(i-1, i+2):
|
|
49
|
+
if self.in_model_domain(i_n, j_n):
|
|
50
|
+
if self.flow_dir[j_n, i_n] == inflow_flow_dir[(j_n-j, i_n-i)]:
|
|
51
|
+
inflow_cells.append([i_n+1, j_n+1])
|
|
52
|
+
# Create masked array from the inflow_cells list
|
|
53
|
+
inflow_cells_ma = np.ma.array(np.ma.empty((7,2), dtype=int), mask=True)
|
|
54
|
+
if len(inflow_cells) > 0: # Only fill if there are inflows
|
|
55
|
+
inflow_cells_ma[0:len(inflow_cells)] = inflow_cells
|
|
56
|
+
return inflow_cells_ma
|
|
57
|
+
|
|
58
|
+
def in_model_domain(self, i, j):
|
|
59
|
+
"""Check if index [j,i] is in model domain."""
|
|
60
|
+
i_in_domain = 0 <= i < self.grid_mask.shape[1]
|
|
61
|
+
j_in_domain = 0 <= j < self.grid_mask.shape[0]
|
|
62
|
+
not_masked = self.flow_dir[j, i] is not np.ma.masked if (i_in_domain and j_in_domain) else False
|
|
63
|
+
return i_in_domain and j_in_domain and not_masked
|
|
64
|
+
|
|
65
|
+
def n_waterbodies_from_inflows(self, x, y, outflow, inflows):
|
|
66
|
+
"""Calculate the number of waterbodies from the inflows to the cell."""
|
|
67
|
+
# j, i = y - 1, x - 1
|
|
68
|
+
j_out, i_out = outflow[1] - 1, outflow[0] - 1
|
|
69
|
+
n_inflows = inflows.count(axis=0)[0] # Count the unmasked elements to get n_inflows
|
|
70
|
+
# If there are no inflows but the outflow is to the model domain, it
|
|
71
|
+
# must be a headwater. Else, number of waterbodies is same as number of inflows
|
|
72
|
+
if n_inflows == 0 and self.in_model_domain(i_out, j_out):
|
|
73
|
+
n_waterbodies = 1
|
|
74
|
+
is_headwater = 1
|
|
75
|
+
else:
|
|
76
|
+
n_waterbodies = n_inflows
|
|
77
|
+
is_headwater = 0
|
|
78
|
+
return n_waterbodies, is_headwater
|
|
79
|
+
|
|
80
|
+
# def generate_waterbody_code(self, x, y, outflow, inflows, is_estuary, is_headwater):
|
|
81
|
+
# """Generates character code of the waterbodies of this cell, of the format
|
|
82
|
+
# <type><index>(<inflow_point>:<outflow_point>/<n_waterbodies_along_branch>)...
|
|
83
|
+
# where type = r,e,l,s (river, estuary, lake, sea), index is 1-indexed, inflow
|
|
84
|
+
# and outflow_side are integers representing the geometrical point of inflow
|
|
85
|
+
# (0 for centre, 1 for top-left, 2 for top centre, etc.) and n_waterbodies_along_branch
|
|
86
|
+
# is the number of waterbodies between inflow and outflow."""
|
|
87
|
+
# outflow_point = self.point_index(outflow[1]-x, outflow[0]-y)
|
|
88
|
+
# wb_type = 'e' if is_estuary > 0 else 'r'
|
|
89
|
+
# wb_char = ''
|
|
90
|
+
# for i, inflow in enumerate(inflows):
|
|
91
|
+
# if not inflow.mask.any(): # Only if this cell isn't masked
|
|
92
|
+
# inflow_point = self.point_index(inflow[1]-x, inflow[0]-y)
|
|
93
|
+
# wb_char = wb_char + '{0}{1}({2}:{3}/01)'.format(wb_type, i+1, inflow_point, outflow_point)
|
|
94
|
+
# # If this is a headwater, there must be a waterbody with inflow at centre of cell
|
|
95
|
+
# if is_headwater:
|
|
96
|
+
# wb_char = '{0}1(0:{1}/01)'.format(wb_type, outflow_point)
|
|
97
|
+
# return wb_char
|
|
98
|
+
|
|
99
|
+
# def point_index(self, di, dj):
|
|
100
|
+
# point_index = {
|
|
101
|
+
# (-1, -1): 1,
|
|
102
|
+
# (0, -1): 8,
|
|
103
|
+
# (1, -1): 7,
|
|
104
|
+
# (-1, 0): 2,
|
|
105
|
+
# (0, 0): 0,
|
|
106
|
+
# (1, 0): 6,
|
|
107
|
+
# (-1, 1): 3,
|
|
108
|
+
# (0, 1): 4,
|
|
109
|
+
# (1, 1): 5
|
|
110
|
+
# }
|
|
111
|
+
# return point_index[dj, di]
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: nfdata
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Compile and edit input data for the NanoFASE model
|
|
5
|
+
License: BSD-3-Clause
|
|
6
|
+
Author: Sam Harrison
|
|
7
|
+
Author-email: samharrison.xg@gmail.com
|
|
8
|
+
Requires-Python: >=3.10,<4.0
|
|
9
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Requires-Dist: Pint (>=0.24.1,<0.25.0)
|
|
14
|
+
Requires-Dist: f90nml (>=1.4.4,<2.0.0)
|
|
15
|
+
Requires-Dist: geopandas (>=1.0.0,<2.0.0)
|
|
16
|
+
Requires-Dist: netCDF4 (>=1.7.1.post1,<2.0.0)
|
|
17
|
+
Requires-Dist: numpy (>=2.0.0,<3.0.0)
|
|
18
|
+
Requires-Dist: pandas (>=2.2.2,<3.0.0)
|
|
19
|
+
Requires-Dist: rasterio (>=1.3.10,<2.0.0)
|
|
20
|
+
Requires-Dist: ruamel.yaml (>=0.18.6,<0.19.0)
|
|
21
|
+
Requires-Dist: shapely (>=2.0.4,<3.0.0)
|
|
22
|
+
Project-URL: Documentation, https://nerc-ceh.github.io/nanofase
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# NanoFASE Data
|
|
26
|
+
|
|
27
|
+
The NanoFASE Data module is a set of scripts to compile and edit input data for the [NanoFASE model](https://github.com/nerc-ceh/nanofase).
|
|
28
|
+
|
|
29
|
+
[See the NanoFASE documentation for full documentation](https://nerc-ceh.github.io/nanofase/users/nanofase-data.html).
|
|
30
|
+
|
|
31
|
+
*Still in development. Use with caution!*
|
|
32
|
+
|
|
33
|
+
## Getting started
|
|
34
|
+
|
|
35
|
+
The easiest way to get started is to create a Conda environment using the provided [environment.yaml](./environment.yaml) file:
|
|
36
|
+
|
|
37
|
+
```shell script
|
|
38
|
+
$ conda env create -f environment.yaml
|
|
39
|
+
$ activate nanofase-data
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
If you don't want to use Conda, then this [environment.yaml](./environment.yaml) file lists the packages that need to be installed.
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
usage: nanofase_data.py [-h] [--output OUTPUT] {create,edit,constants} file
|
|
48
|
+
|
|
49
|
+
Compile or edit data for the NanoFASE model.
|
|
50
|
+
|
|
51
|
+
positional arguments:
|
|
52
|
+
{create,edit,constants}
|
|
53
|
+
do you wish to create from scratch, edit the data or
|
|
54
|
+
create a constants file?
|
|
55
|
+
file path to the config file (create/edit tasks) or
|
|
56
|
+
constants file (constants task)
|
|
57
|
+
|
|
58
|
+
optional arguments:
|
|
59
|
+
-h, --help show this help message and exit
|
|
60
|
+
--output OUTPUT, -o OUTPUT
|
|
61
|
+
where to create the new constants file (for constants
|
|
62
|
+
task)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Creating a new dataset
|
|
66
|
+
|
|
67
|
+
Specifying the "create" option compiles a new NetCDF dataset and Fortran namelist constant file:
|
|
68
|
+
|
|
69
|
+
```shell script
|
|
70
|
+
$ python nanofase_data.py create /path/to/config.create.yaml
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
An annotated example config file is given: [`config.create.example.yaml`](config.create.example.yaml). The file is quite self-explanatory, but a few further explanations are provided in [this document](docs/config.md).
|
|
74
|
+
|
|
75
|
+
The two files will be output to the paths specified in the config file.
|
|
76
|
+
|
|
77
|
+
### Editing an existing dataset
|
|
78
|
+
|
|
79
|
+
To edit an existing NetCDF dataset, specify the "edit" option:
|
|
80
|
+
|
|
81
|
+
```shell script
|
|
82
|
+
$ python nanofase_data.py edit /path/to/config.edit.yaml
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
An annotated example config file is given: [`config.edit.example.yaml`](config.edit.example.yaml). This is similar (but not identical) in format to the creation config file, except only those variables you with to edit should be specified (all other variables are left as-is).
|
|
86
|
+
|
|
87
|
+
Certain variables can't be edited: `flow_dir`, `is_estuary`. Create a new dataset instead if you wish to change these variables.
|
|
88
|
+
|
|
89
|
+
The Fortran namelist file cannot be edited using this method and you should instead edit the file directly.
|
|
90
|
+
|
|
91
|
+
### Only creating a new constants file
|
|
92
|
+
|
|
93
|
+
To simply convert a constants YAML file to a Fortran namelist file, you can use the `constants` option:
|
|
94
|
+
|
|
95
|
+
```shell script
|
|
96
|
+
$ python nanofase_data.py constants /path/to/constants.yaml -o /path/to/constants.nml
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
No config file is required. The location of the newly created constants file is given by the `-o` or `--output` argument.
|
|
100
|
+
|
|
101
|
+
### Tips
|
|
102
|
+
- For the moment, all rasters must be the same CRS as the `flow_dir` raster, and this must be a projected raster. We recommend ESPG:27700 (British National Grid). In addition, all rasters except for `land_use` must be the same resolution as `flow_dir`. They can cover a large geographical region and the module will automatically clip them to the correct size.
|
|
103
|
+
- Support for different file types is a bit sporadic at the moment. I suggest sticking the raster files for spatial variables, raster or CSV files for spatiotemporal variables (with 1 file per timestep for raster files) and shapefiles for point sources. You will trigger errors if you use an unsupported file.
|
|
104
|
+
- Example input data files are given in `data.example/thames_tio2_2015/`. Running the model using the example config files uses these data.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
config.create.example.yaml,sha256=VrhOESh0SAT9XgfMzlsFHwZ9gdk33QKeQre7OAgkK2A,11022
|
|
2
|
+
config.edit.example.yaml,sha256=kftzvNc8CVF-Zpl0m4_Z7oImDOOcrwBMX1teSZQ4vfE,726
|
|
3
|
+
environment.yaml,sha256=gtWHLI-2OuMYHfkY-2ymte_7YZjU8dvk0AzlY6dYDoI,167
|
|
4
|
+
nfdata/__init__.py,sha256=CUCPni5-diJlQ8X6gu__U-BK9kqmWghdf86MCDhnPtc,228
|
|
5
|
+
nfdata/compiler.py,sha256=qwOOAUoFnKC9QS-Ow5Dky7GyKDhlHzzP--Q2xObQ2SA,38226
|
|
6
|
+
nfdata/console.py,sha256=RtufM-tHCRK9gX0DGEWLjQYnAm9Sy-v_Lrima2IVLJo,1536
|
|
7
|
+
nfdata/land_use.default.yaml,sha256=bpx-iDxsh3KVDqOLyCYCYBLrbUYTCFh2XqD0q3BCs1w,3049
|
|
8
|
+
nfdata/model_vars.yaml,sha256=TOitPec6u8vmwygv-G1wyrNXr68cp1C2XjYEyOKdnzg,7646
|
|
9
|
+
nfdata/router.py,sha256=S7IUL93ZaF91lSywImjD3KVBJaj2X0bW-yMrl9_a_IQ,4836
|
|
10
|
+
nfdata-0.1.0.dist-info/METADATA,sha256=owMUWrwKVDtQVwBVYaEx9CqfRFrSpxPu5NaytOSFg50,4632
|
|
11
|
+
nfdata-0.1.0.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
|
|
12
|
+
nfdata-0.1.0.dist-info/entry_points.txt,sha256=H_4636nsIrsy4hqa65cUq5uenq5AIGSOoq7tlEO3HRY,45
|
|
13
|
+
nfdata-0.1.0.dist-info/RECORD,,
|