Source code for marble.components.decomposition

import numpy as np
from sympl import DiagnosticComponent
from marble.components.marble import pc_ds, name_feature_counts
from marble.docstrings import document_properties


[docs]@document_properties class InputHeightToPrincipalComponents(DiagnosticComponent): """ Converts MARBLE's vertically-resolved inputs from height coordinates to principal components. """ input_properties = { 'liquid_water_static_energy': { 'dims': ['*', 'z_star'], 'units': 'J/kg', 'alias': 'sl', }, 'total_water_mixing_ratio': { 'dims': ['*', 'z_star'], 'units': 'kg/kg', 'alias': 'rt', }, 'vertical_wind': { 'dims': ['*', 'z_star'], 'units': 'm/s', 'alias': 'w' }, } diagnostic_properties = { 'liquid_water_static_energy_components': { 'dims': ['*', 'sl_latent'], 'units': '', 'alias': 'sl_latent', }, 'total_water_mixing_ratio_components': { 'dims': ['*', 'rt_latent'], 'units': '', 'alias': 'rt_latent', }, 'vertical_wind_components': { 'dims': ['*', 'w_latent'], 'units': '', 'alias': 'w_latent' }, } def array_call(self, state): diagnostic_dict = {} for name in 'w', 'sl', 'rt': diagnostic_dict[f'{name}_latent'] = convert_height_to_principal_components(state[name], name, subtract_mean=True) return diagnostic_dict
[docs]def convert_height_to_principal_components(array, basis_name, subtract_mean=True): """ Converts a numpy array from height coordinates on a 20-point equidistant grid from 0 to 3km (inclusive) into principal components required by MARBLE. Args: array: numpy array whose final dimension is of size 20 basis_name: short alias name of the quantity whose principal components to use. For example, 'rt', 'sl', 'cld', 'rcld', 'rrain', or 'w'. subtract_mean: whether to subtract the mean vertical profile of the basis quantity from the numpy array before converting into principal components. Generally this is True if you are converting the basis quantity itself, and False if you are converting a difference to apply to the basis quantity (such as a tendency). Returns: return_array: numpy array whose final dimension length is equal to the number of principal components used for hte basis quantity. """ if subtract_mean: array = array - pc_ds[f'{basis_name}_mean'].values return np.dot( array, pc_ds[f'{basis_name}_principal_components'].values[:name_feature_counts[basis_name], :].T )
[docs]def convert_principal_components_to_height(array, basis_name, add_mean=True): """ Converts a numpy array from principal components as used by MARBLE to height coordinates on a 20-point equidistant grid from 0 to 3km (inclusive). Args: array: numpy array whose final dimension is principal component number basis_name: short alias name of the quantity whose principal components are used. For example, 'rt', 'sl', 'cld', 'rcld', 'rrain', or 'w'. add_mean: whether to add in the mean vertical profile of the basis quantity from the numpy array after converting to height coordinates. Generally this is True if you are converting the basis quantity itself, and False if you are converting a difference applied to the basis quantity (such as a tendency). Returns: return_array: numpy array whose final dimension length is 20. """ result = np.dot( array, pc_ds[f'{basis_name}_principal_components'].values[:name_feature_counts[basis_name], :] ) if add_mean: result += pc_ds[f'{basis_name}_mean'].values return result
[docs]@document_properties class InputPrincipalComponentsToHeight(DiagnosticComponent): """ Converts MARBLE's vertically-resolved inputs from principal components to height coordinates. """ input_properties = { 'liquid_water_static_energy_components': { 'dims': ['*', 'sl_latent'], 'units': '', 'alias': 'sl', }, 'total_water_mixing_ratio_components': { 'dims': ['*', 'rt_latent'], 'units': '', 'alias': 'rt', }, 'vertical_wind_components': { 'dims': ['*', 'w_latent'], 'units': '', 'alias': 'w' }, } diagnostic_properties = { 'liquid_water_static_energy': { 'dims': ['*', 'z_star'], 'units': 'J/kg', 'alias': 'sl', }, 'total_water_mixing_ratio': { 'dims': ['*', 'z_star'], 'units': 'kg/kg', 'alias': 'rt', }, 'vertical_wind': { 'dims': ['*', 'z_star'], 'units': 'm/s', 'alias': 'w' }, } def array_call(self, state): diagnostic_dict = {} for name in 'sl', 'rt', 'w': diagnostic_dict[name] = convert_principal_components_to_height( state[name], basis_name=name, add_mean=True ) return diagnostic_dict
[docs]@document_properties class DiagnosticPrincipalComponentsToHeight(DiagnosticComponent): """ Converts MARBLE's vertically-resolved diagnostic outputs from principal components to height coordinates. """ input_properties = { 'cloud_water_mixing_ratio_components': { 'dims': ['*', 'rcld_latent'], 'units': '', 'alias': 'rcld', }, 'rain_water_mixing_ratio_components': { 'dims': ['*', 'rrain_latent'], 'units': '', 'alias': 'rrain', }, 'cloud_fraction_components': { 'dims': ['*', 'cld_latent'], 'units': '', 'alias': 'cld', }, 'clear_sky_radiative_heating_rate_components': { 'dims': ['*', 'sl_latent'], 'units': 'hr^-1', 'alias': 'sl_rad_clr', }, } diagnostic_properties = { 'cloud_water_mixing_ratio': { 'dims': ['*', 'z_star'], 'units': '', 'alias': 'rcld', }, 'rain_water_mixing_ratio': { 'dims': ['*', 'z_star'], 'units': '', 'alias': 'rrain', }, 'cloud_fraction': { 'dims': ['*', 'z_star'], 'units': '', 'alias': 'cld', }, 'clear_sky_radiative_heating_rate': { 'dims': ['*', 'z_star'], 'units': 'degK hr^-1', 'alias': 'sl_rad_clr', }, } def array_call(self, state): diagnostic_dict = {} for name in 'rcld', 'rrain', 'cld': diagnostic_dict[name] = convert_principal_components_to_height( state[name], basis_name=name, add_mean=True, ) diagnostic_dict['sl_rad_clr'] = convert_principal_components_to_height( state['sl_rad_clr'], basis_name='sl', add_mean=False ) return diagnostic_dict