Page MenuHomec4science

netCDFController.py
No OneTemporary

File Metadata

Created
Wed, Sep 11, 16:14

netCDFController.py

###########################################################################
# #
# Copyright 2017 Andrea Cimatoribus #
# EPFL ENAC IIE ECOL #
# GR A1 435 (Batiment GR) #
# Station 2 #
# CH-1015 Lausanne #
# Andrea.Cimatoribus@epfl.ch #
# #
# Alexandre Serex #
# alexandre.serex@epfl.ch #
# #
# This file is part of ctracker #
# #
# ctracker is free software: you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# ctracker is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty #
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. #
# See the GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with ctracker. If not, see <http://www.gnu.org/licenses/>. #
# #
###########################################################################
import numpy as np
from netCDF4 import Dataset
from core.parameter import Parameter
from tools.CFunctions import loc_time_fast
class NetCDFController(Parameter):
def __init__(self, name, run, inout, ends, ntrackmax, gcmstart, complevel, chunk_id, chunk_time, *args, **kwargs):
super(NetCDFController, self).__init__(name, *args, **kwargs)
self.iendw = ends[0]
self.iende = ends[1]
self.jendn = ends[2]
self.jends = ends[3]
self.ntrackmax = ntrackmax
self.gcm_start = gcmstart
self.complevel = complevel
self.chunk_id = chunk_id
self.chunk_time = chunk_time
self.nc_time = np.array([], dtype="float64")
self.run = self.nc_init_run(run)
self.inout = self.nc_init_inout(inout)
self.inputs['default'] = [self.process_input]
self.inputs["sync"] = [self.sync]
def sync(self):
self.run.sync()
self.inout.sync()
def process_input(self, *args, **kwargs):
self.nc_write_one_time(*args, **kwargs)
def nc_init_inout(self, nc_f):
# store info on kill areas
nc_f.setncattr("i_endw", self.iendw)
nc_f.setncattr("i_ende", self.iende)
nc_f.setncattr("j_endn", self.jendn)
nc_f.setncattr("j_ends", self.jends)
# id
nc_f.createDimension("pid", size=self.ntrackmax)
nc_f.createVariable("pid", "int32", ("pid",))
ncvar = nc_f.variables["pid"]
ncvar[:] = np.arange(1, self.ntrackmax + 1)
ncvar.setncattr("long_name", "particle ID")
# exit code
nc_f.createVariable("outc", "i2", ("pid",))
ncvar = nc_f.variables["outc"]
ncvar.setncattr("code -1", "not released")
ncvar.setncattr("code 0", "still active")
ncvar.setncattr("code 1", "out of the horizontal domain")
ncvar.setncattr("code 2", "particle reached the surface")
ncvar.setncattr("code 10+N", "reached N-th kill region")
ncvar[:] = -1
# time of seeding
nc_f.createVariable("t_ini", "float64", ("pid",), fill_value=-1.0)
ncvar = nc_f.variables["t_ini"]
ncvar.setncattr("units", ("seconds since %s" %
self.gcm_start.astype("datetime64[s]"))
.replace("T", " "))
# end time
nc_f.createVariable("t_end", "float64", ("pid",), fill_value=-1.0)
ncvar = nc_f.variables["t_end"]
ncvar.setncattr("units", ("seconds since %s" %
self.gcm_start.astype("datetime64[s]"))
.replace("T", " "))
# i-position at seeding
nc_f.createVariable("i_ini", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["i_ini"]
ncvar.setncattr("units", "fractional cell_index")
# j-position at seeding
nc_f.createVariable("j_ini", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["j_ini"]
ncvar.setncattr("units", "fractional cell_index")
# k-position at seeding
nc_f.createVariable("k_ini", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["k_ini"]
ncvar.setncattr("units", "fractional cell_index")
# x-position at seeding
nc_f.createVariable("x_ini", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["x_ini"]
ncvar.setncattr("units", "GCM grid units")
# y-position at seeding
nc_f.createVariable("y_ini", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["y_ini"]
ncvar.setncattr("units", "GCM grid units")
# z-position at seeding
nc_f.createVariable("z_ini", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["z_ini"]
ncvar.setncattr("units", "GCM grid units")
# i-position at exit
nc_f.createVariable("i_end", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["i_end"]
ncvar.setncattr("units", "fractional cell_index")
# j-position at exit
nc_f.createVariable("j_end", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["j_end"]
ncvar.setncattr("units", "fractional cell_index")
# k-position at exit
nc_f.createVariable("k_end", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["k_end"]
ncvar.setncattr("units", "fractional cell_index")
# x-position at exit
nc_f.createVariable("x_end", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["x_end"]
ncvar.setncattr("units", "GCM grid units")
# y-position at exit
nc_f.createVariable("y_end", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["y_end"]
ncvar.setncattr("units", "GCM grid units")
# z-position at exit
nc_f.createVariable("z_end", "float32", ("pid",),
zlib=True, complevel=self.complevel,
shuffle=True)
ncvar = nc_f.variables["z_end"]
ncvar.setncattr("units", "GCM grid units")
return nc_f
def nc_init_run(self, nc_f):
# id
nc_f.createDimension("pid", size=self.ntrackmax)
nc_f.createVariable("pid", "int32", ("pid",))
ncvar = nc_f.variables["pid"]
ncvar[:] = np.arange(1, self.ntrackmax + 1)
ncvar.setncattr("long_name", "particle ID")
# time
nc_f.createDimension("time", size=None)
nc_f.createVariable("time", "float64", ("time",))
ncvar = nc_f.variables["time"]
ncvar.setncattr("units", ("seconds since %s" %
self.gcm_start.astype("datetime64[s]"))
.replace("T", " "))
# write times are highly dependent on the chunking in use
chunks = (self.chunk_id, self.chunk_time)
# itrack
nc_f.createVariable("itrack", "float32", ("pid", "time"),
zlib=True, complevel=self.complevel,
shuffle=True, chunksizes=chunks)
ncvar = nc_f.variables["itrack"]
ncvar.setncattr("units", "fractional cell_index")
# jtrack
nc_f.createVariable("jtrack", "float32", ("pid", "time"),
zlib=True, complevel=self.complevel,
shuffle=True, chunksizes=chunks)
ncvar = nc_f.variables["jtrack"]
ncvar.setncattr("units", "fractional cell_index")
# ktrack
nc_f.createVariable("ktrack", "float32", ("pid", "time"),
zlib=True, complevel=self.complevel,
shuffle=True, chunksizes=chunks)
ncvar = nc_f.variables["ktrack"]
ncvar.setncattr("units", "fractional cell_index")
# xtrack
nc_f.createVariable("xtrack", "float32", ("pid", "time"),
zlib=True, complevel=self.complevel,
shuffle=True, chunksizes=chunks)
ncvar = nc_f.variables["xtrack"]
ncvar.setncattr("units", "GCM grid units")
# ytrack
nc_f.createVariable("ytrack", "float32", ("pid", "time"),
zlib=True, complevel=self.complevel,
shuffle=True, chunksizes=chunks)
ncvar = nc_f.variables["ytrack"]
ncvar.setncattr("units", "GCM grid units")
# ztrack
nc_f.createVariable("ztrack", "float32", ("pid", "time"),
zlib=True, complevel=self.complevel,
shuffle=True, chunksizes=chunks)
ncvar = nc_f.variables["ztrack"]
ncvar.setncattr("units", "GCM grid units")
nc_f.sync()
return nc_f
def nc_write_one_time(self, *args, file="run",
outc=None, init=False):
# The particle ids start from 1, python index from 0
time, ids, ijk, xyz = args[0]
ids -= 1
nc_f = self.run
if file == "inout":
nc_f = self.inout
if init:
nc_f = self.inout
nc_f.variables["t_ini"][ids] = time
nc_f.variables["outc"][ids] = 0
nc_f.variables["i_ini"][ids] = ijk[:, 0]
nc_f.variables["j_ini"][ids] = ijk[:, 1]
nc_f.variables["k_ini"][ids] = ijk[:, 2]
nc_f.variables["x_ini"][ids] = xyz[:, 0]
nc_f.variables["y_ini"][ids] = xyz[:, 1]
nc_f.variables["z_ini"][ids] = xyz[:, 2]
elif np.any(outc > 0): # particles exit
nonzerooc = outc > 0
nc_f.variables["t_end"][ids[nonzerooc]] = time
nc_f.variables["outc"][ids[nonzerooc]] = outc[nonzerooc]
nc_f.variables["i_end"][ids] = ijk[:, 0]
nc_f.variables["j_end"][ids] = ijk[:, 1]
nc_f.variables["k_end"][ids] = ijk[:, 2]
nc_f.variables["x_end"][ids] = xyz[:, 0]
nc_f.variables["y_end"][ids] = xyz[:, 1]
nc_f.variables["z_end"][ids] = xyz[:, 2]
else:
tind = self.loc_time(nc_f, time)
nc_f.variables["itrack"][ids, tind] = ijk[:, 0]
nc_f.variables["jtrack"][ids, tind] = ijk[:, 1]
nc_f.variables["ktrack"][ids, tind] = ijk[:, 2]
nc_f.variables["xtrack"][ids, tind] = xyz[:, 0]
nc_f.variables["ytrack"][ids, tind] = xyz[:, 1]
nc_f.variables["ztrack"][ids, tind] = xyz[:, 2]
def loc_time(self, nc_f, time):
ind = loc_time_fast(self.nc_time, self.nc_time.size, time, False)
if ind >= 0:
return ind
else:
# We did not find the time we are looking for,
# so we add it to the time axis
# both in memory and on disk
self.nc_time = np.append(self.nc_time, time)
ind = self.nc_time.size - 1
nc_f.variables["time"][ind] = time
return ind
def dataset(file, *args, **kwargs):
return Dataset(file, *args, **kwargs)

Event Timeline