#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
SpectralGeometry:
Contains the class that handles spectral parameters and spectral transforms.
"""
import numpy
from footprints import FootprintBase, FPDict
from epygram import config, epygramError
from epygram.util import RecursiveObject
from epygram import arpifs4py
[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