#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy
from footprints import FootprintBase, FPDict
import arpifs4py
from epygram.util import RecursiveObject
from epygram import config, epygramError
[docs]class SpectralGeometry(RecursiveObject, FootprintBase):
"""
Handles the spectral geometry and transforms for a H2DField.
"""
_collector = ('geometry',)
_footprint = dict(
attr = dict(
space = dict(
access='rwx',
info = 'Name of spectral space.'),
truncation = dict(
type = FPDict,
access = 'rwx',
info = 'Handles the spectral truncation parameters.')
)
)
[docs] def sp2gp(self, data, gpdims):
"""
Makes the transform of the spectral data contained in *data* (assumed this spectral geometry is that of 'data')
to gridpoint space, defined by its dimensions contained in *gpdims*, and returns the gridpoint data.
Input and output data are both 1D.
"""
if self.space == 'bi-fourier':
gpdata = arpifs4py.w_spec2gpt_lam(gpdims['X'], gpdims['Y'],
gpdims['X_CIzone'], gpdims['Y_CIzone'],
self.truncation['in_X'], self.truncation['in_Y'],
config.KNUMMAXRESOL,
len(data), data)
elif self.space == 'legendre':
gpdata = arpifs4py.w_spec2gpt_gauss(gpdims['lat_number'], self.truncation['max'],
config.KNUMMAXRESOL,
sum(gpdims['lon_number_by_lat']),
len(gpdims['lon_number_by_lat']),
numpy.array(gpdims['lon_number_by_lat']),
len(data), data)
elif self.space == 'fourier':
if self.truncation['in_Y'] > 1:
gpdata = arpifs4py.w_spec2gpt_fft1d(len(data),
self.truncation['in_Y'],
data,
gpdims['Y'])
else:
gpdata = numpy.ones(gpdims['Y']) * data[0]
else:
raise epygramError("unknown spectral space:"+self.space+".")
return gpdata
[docs] def gp2sp(self, data, gpdims):
"""
Makes the transform of the gridpoint data contained in *data*
to the spectral space and truncation of this object, and returns the spectral data.
Input and output data are both 1D.
"""
if self.space == 'bi-fourier':
SPdatasize = arpifs4py.w_etrans_inq(gpdims['X'], gpdims['Y'],
gpdims['X_CIzone'], gpdims['Y_CIzone'],
self.truncation['in_X'], self.truncation['in_Y'],
config.KNUMMAXRESOL)[1]
spdata = arpifs4py.w_gpt2spec_lam(SPdatasize,
gpdims['X'], gpdims['Y'],
gpdims['X_CIzone'], gpdims['Y_CIzone'],
self.truncation['in_X'], self.truncation['in_Y'],
config.KNUMMAXRESOL,
data)
elif self.space == 'legendre':
SPdatasize = arpifs4py.w_trans_inq(gpdims['lat_number'], self.truncation['max'],
len(gpdims['lon_number_by_lat']),
numpy.array(gpdims['lon_number_by_lat']),
config.KNUMMAXRESOL)[1]
SPdatasize *= 2 # complex coefficients
spdata = arpifs4py.w_gpt2spec_gauss(SPdatasize,
gpdims['lat_number'], self.truncation['max'],
config.KNUMMAXRESOL,
len(gpdims['lon_number_by_lat']),
numpy.array(gpdims['lon_number_by_lat']),
len(data), data)
elif self.space == 'fourier':
# 1D case
SPdatasize = arpifs4py.w_etrans_inq(gpdims['X'], gpdims['Y'],
gpdims['X_CIzone'], gpdims['Y_CIzone'],
self.truncation['in_X'], self.truncation['in_Y'],
config.KNUMMAXRESOL)[1]
if self.truncation['in_Y'] <= 1:
spdata = numpy.zeros(SPdatasize)
spdata[0] = data[0]
else:
raise NotImplementedError("direct transform for 1D fourier transform.")
else:
raise epygramError("unknown spectral space:"+self.space+".")
return spdata