/
cut_results.jl
209 lines (170 loc) · 6.14 KB
/
cut_results.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
function _inpolygon(X,(testx,testy))
c = false
nvert = size(X,1)
j = nvert
for i = 1:nvert
if ( ((X[i,2]>testy) != (X[j,2]>testy)) &&
(testx < (X[j,1]-X[i,1]) * (testy-X[i,2]) / (X[j,2]-X[i,2]) + X[i,1]) )
c = !c
end
j = i
end
return c
end
function inpolygon(polygon_lon,polygon_lat,lonr,latr)
sz = (length(lonr),length(latr))
maskkeep = trues(sz)
X = hcat(polygon_lon,polygon_lat)
for j = 1:sz[2]
for i = 1:sz[1]
maskkeep[i,j] = _inpolygon(X,(lonr[i],latr[j]))
end
end
return maskkeep
end
function _crop(maskkeep,field)
fieldsub = allowmissing(field[i,j])
fieldsub[.!maskkeepsub] .= missing
return fieldsub
end
function maskout!(dn,maskkeepsub,field)
if length(dn) >= 2
if dn[1:2] == ("lon","lat")
for ind in CartesianIndices((1:size(field,3), 1:size(field,4)))
tmp = @view field[:,:,ind]
tmp[.!maskkeepsub] .= missing
end
end
end
end
"""
DIVAnd.cut(filename,varname,filename_cut,polygon_lon,polygon_lat)
Exclude all grid cells points of the netcdf file `filename` with the
variable `varname` to the grid cell included in the polygon
whose vertices are defined by the vector of longitude values `polygon_lon`
and the vector of latitude values `polygon_lat`. Values outside of this polygone
will be croped (if possible) or masked (if croping is not possible).
Only the NetCDF variable with the dimensions `lon` and `lat` will be
modified. All other variarables (in particular `obslon`, `obslat`, ...)
will not be changed.
Example
```julia
filename2 = "Water_body_dissolved_oxygen_concentration_monthly.nc"
# polygon with the area to retain
polygon_lon = [-20., 20, 20, -19]
polygon_lat = [21, 21, 53., 52.]
varname = "Water body dissolved oxygen concentration"
filename_cut = "cut.nc"
DIVAnd.cut(filename2,varname,filename_cut,polygon_lon,polygon_lat)
```
"""
function cut(filename2,varname,filename_cut,
polygon_lon::AbstractVector,
polygon_lat::AbstractVector; kwargs...)
(lonr,latr) =
NCDataset(filename2) do ds
ds["lon"][:], ds["lat"][:]
end
maskkeep = inpolygon(polygon_lon,polygon_lat,lonr,latr)
@info "keeping: $(count(maskkeep))"
cut(filename2,varname,filename_cut,maskkeep; kwargs...)
end
function cut(filename2,varname,filename_cut,maskkeep::AbstractArray{Bool,2};
compress = true
)
NCDataset(filename2) do ds
lonr = ds["lon"][:]
latr = ds["lat"][:]
maskkeep1 = any(maskkeep,dims=2)[:,1]
i = findfirst(maskkeep1):findlast(maskkeep1)
maskkeep2 = any(maskkeep,dims=1)[1,:]
j = findfirst(maskkeep2):findlast(maskkeep2)
maskkeepsub = maskkeep[i,j]
#fieldkeep = _crop(maskkeep,field)
if isfile(filename_cut)
rm(filename_cut)
end
NCDataset(filename_cut,"c",attrib = ds.attrib) do ds_cut
# set dimenions
for (dimname,dimlen) in ds.dim
ds_cut.dim[dimname] =
if dimname == "lon"
length(i)
elseif dimname == "lat"
length(j)
else
dimlen
end
end
function slice_(dimname)
if dimname == "lon"
i
elseif dimname == "lat"
j
else
Colon()
end
end
function chunk(dimname)
if dimname == "lon"
100
elseif dimname == "lat"
100
else
1
end
end
for (varname,ncvar) in ds
dn = dimnames(ncvar)
@debug "varname: $varname"
@debug "compress: $compress"
kwargs = Dict()
if compress
storage,chunksizes = chunking(ncvar)
isshuffled,isdeflated,deflatelevel = deflate(ncvar)
sizecut = ntuple(i -> ds_cut.dim[dn[i]],length(dn))
@debug "sizecut: $(sizecut)"
chunksizes = min.(chunksizes,sizecut)
@debug "checksum: $(checksum(ncvar))"
@debug "chunksizes: $chunksizes"
@debug "storage: $chunksizes"
@debug "deflatelevel: $deflatelevel"
@debug "size(ncvar): $(size(ncvar))"
if !(varname in ["lon","lat","time","depth","climatology_bounds"])
kwargs[:checksum] = checksum(ncvar)
if storage == :chunked
kwargs[:chunksizes] = chunksizes
end
if isdeflated
kwargs[:deflatelevel] = deflatelevel
end
end
@debug "arguments: $(kwargs)"
end
#@show chunksizes,size(ncvar)
T = eltype(ncvar.var)
ncvar_cut = defVar(
ds_cut,varname,T,dn;
kwargs...,
# deflatelevel = deflatelevel,
# chunksizes = chunksizes,
# checksum = checksum(ncvar),
attrib = OrderedDict(ncvar.attrib))
indices = slice_.(dn)
indices_write = ntuple(i -> Colon(), length(dn))
@info "Slicing $varname[$indices]"
if "time" in dn
for n = 1:ds.dim["time"]
data = ncvar[indices[1:end-1]...,n]
maskout!(dn,maskkeepsub,data)
ncvar_cut[indices_write[1:end-1]...,n] = data
end
else
data = ncvar[indices...]
maskout!(dn,maskkeepsub,data)
ncvar_cut[indices_write...] = data
end
end
end
end
end