Skip to content

Commit

Permalink
add function to get the profile of any layer property. Prepare deprec…
Browse files Browse the repository at this point in the history
…iation of 'layer_depths' property.
  • Loading branch information
ghislainp committed Sep 8, 2020
1 parent 52f3c28 commit 26b7d81
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 3 deletions.
55 changes: 52 additions & 3 deletions smrt/core/snowpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@

import copy
import numpy as np
import warnings
import functools

from .error import SMRTError
from ..interface.flat import Flat # core should not depend on something defined in interface...
from .layer import Layer
from .interface import SubstrateBase

cached_property = getattr(functools, "cached_property", property) # use cached_propertity if it exists... otherwise, use property


class Snowpack(object):
"""holds the description of the snowpack, including the layers, interfaces, and the substrate
Expand All @@ -46,7 +50,7 @@ def nlayer(self):
"""
return len(self.layers)

@property
@cached_property
def layer_thicknesses(self):
"""return the thickness of each layer
"""
Expand All @@ -57,9 +61,34 @@ def layer_depths(self):
"""return the depth of the bottom of each layer
"""
return np.cumsum(self.layer_thicknesses) # TODO Ghi: caching
warnings.warn("layer_depths is ambiguous, use bottom_layer_depths, top_layer_depths or mid_layer_depths instead."
"This function will be removed in a next version",
DeprecationWarning)
return np.cumsum(self.layer_thicknesses)

@cached_property
def bottom_layer_depths(self):
"""return the depth of the bottom of each layer
"""
return np.cumsum(self.profile('thickness')) # TODO Ghi: caching

@property
def top_layer_depths(self):
"""return the depth of the bottom of each layer
"""
return self.z[:-1]

@cached_property
def mid_layer_depths(self):
"""return the depth of the bottom of each layer
"""
ld = self.z
return (ld[1:] + ld[:-1]) / 2

@cached_property
def z(self):
"""return the depth of each interface, that is, 0 and the depth of the bottom of each layer
Expand All @@ -70,8 +99,23 @@ def z(self):
def layer_densities(self):
"""return the density of each layer
"""
warnings.warn("layer_densities is ambiguous, use the profile('density') instead. This function will be removed in a next version",
DeprecationWarning)
return [lay.density for lay in self.layers] # TODO Ghi: caching

@functools.lru_cache()
def profile(self, property_name):
"""return the property of each layer as a list
"""
if property_name == "bottom_layer_depths":
return self.bottom_layer_depths
elif property_name == "top_layer_depths":
return self.top_layer_depths
elif property_name == "mid_layer_depths":
return self.mid_layer_depths
else:
return [getattr(lay, property_name) for lay in self.layers] # TODO Ghi: caching

def append(self, layer, interface=None):
"""append a new layer at the bottom of the stack of layers. The interface is that at the top of the appended layer.
Expand Down Expand Up @@ -102,13 +146,18 @@ def delete(self, ilayer):
def copy(self):
"""make a shallow copy of a snowpack by copying the list of layers and interfaces but not the layers and interfaces themselves which are still shared with the original snowpacl.
This method allows the user to create a new snowpack and remove, append or replace some layers or interfaces afterward. It does not allow to alter the layers or interfaces without
changing the original snowpack. In this latter case, use copy.deepcopy.
changing the original snowpack. See py:meth:~deepcopy.
"""
new_sp = copy.copy(self)
new_sp.layers = copy.copy(self.layers)
new_sp.interfaces = copy.copy(self.interfaces)
return new_sp

def deepcopy(self):
"""make a deep copy of a snowpack.
"""
return copy.deepcopy(self)

def basic_check(self):

if len(self.interfaces) != len(self.layers):
Expand Down
12 changes: 12 additions & 0 deletions smrt/core/test_snowpack.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@


import pytest
import numpy as np

from ..inputs.make_medium import make_snowpack
from .error import SMRTError
from .interface import Substrate
from .atmosphere import AtmosphereBase


def test_profile():

sp = make_snowpack([0.1, 0.2, 0.3], "exponential", density=[100, 200, 300], corr_length=200e-6)


assert np.allclose(sp.z, [0, 0.1, 0.3, 0.6])
assert np.allclose(sp.bottom_layer_depths, [0.1, 0.3, 0.6])
assert np.allclose(sp.top_layer_depths, [0.0, 0.1, 0.3])
assert np.allclose(sp.mid_layer_depths, [0.05, 0.2, 0.45])
assert np.allclose(sp.profile('density'), [100, 200, 300])

def test_addition():

sp1 = make_snowpack([0.1], "exponential", density=300, corr_length=200e-6)
Expand Down

0 comments on commit 26b7d81

Please sign in to comment.