def test_basic(self):
     """Test method returns an array with correct data"""
     plugin = FallingSnowLevel()
     expected = np.array([[10.0, 7.5], [25.0, 20.5]])
     result = plugin.find_falling_level(self.wb_int_data, self.orog_data,
                                        self.height_points)
     self.assertIsInstance(result, np.ndarray)
     self.assertArrayEqual(result, expected)
 def test_land_points(self):
     """Test it returns arrays of zeros if points are land."""
     plugin = FallingSnowLevel()
     sea_points = np.ones((3, 3)) * False
     gradients, intercepts = plugin.linear_wet_bulb_fit(
         self.wet_bulb_temperature, self.heights, sea_points)
     self.assertArrayAlmostEqual(np.zeros((3, 3)), gradients)
     self.assertArrayAlmostEqual(np.zeros((3, 3)), intercepts)
 def test_basic(self):
     """Test it fills in the points it's meant to."""
     plugin = FallingSnowLevel()
     plugin.fill_in_sea_points(self.snow_falling_level, self.land_sea,
                               self.max_wb_integral,
                               self.wet_bulb_temperature, self.heights)
     self.assertArrayAlmostEqual(self.snow_falling_level.data,
                                 self.expected_snow_falling_level)
 def test_outside_range(self):
     """Test method returns an nan if data outside range"""
     plugin = FallingSnowLevel()
     wb_int_data = self.wb_int_data
     wb_int_data[2, 1, 1] = 70.0
     result = plugin.find_falling_level(wb_int_data, self.orog_data,
                                        self.height_points)
     self.assertTrue(np.isnan(result[1, 1]))
    def test_basic(self):
        """Test we find the correct gradient and intercepts for simple case"""
        plugin = FallingSnowLevel()

        gradients, intercepts = plugin.linear_wet_bulb_fit(
            self.wet_bulb_temperature, self.heights, self.sea_points)
        self.assertArrayAlmostEqual(self.expected_gradients, gradients)
        self.assertArrayAlmostEqual(self.expected_intercepts, intercepts)
 def test_no_sea(self):
     """Test it only fills in sea points, and ignores a land point"""
     plugin = FallingSnowLevel()
     expected = np.ones((3, 3)) * np.nan
     land_sea = np.ones((3, 3))
     plugin.fill_in_sea_points(self.snow_falling_level, land_sea,
                               self.max_wb_integral,
                               self.wet_bulb_temperature, self.heights)
     self.assertArrayAlmostEqual(self.snow_falling_level.data, expected)
예제 #7
0
    def test_basic(self):
        """Test we fill in the correct snow falling levels for a simple case"""
        plugin = FallingSnowLevel()

        plugin.find_extrapolated_falling_level(
            self.max_wb_integral, self.gradients, self.intercepts,
            self.snow_falling_level, self.sea_points)
        self.assertArrayAlmostEqual(self.expected_snow_falling_level,
                                    self.snow_falling_level)
 def setUp(self):
     """ Set up arrays for testing."""
     self.snow_level_data = np.array([[1.0, 1.0, 2.0], [1.0, np.nan, 2.0],
                                      [1.0, 2.0, 2.0]])
     self.orog_data = np.array([[6.0, 6.0, 6.0], [6.0, 7.0, 6.0],
                                [6.0, 6.0, 6.0]])
     self.max_in_nbhood_orog = np.array([[7.0, 7.0, 7.0], [7.0, 7.0, 7.0],
                                         [7.0, 7.0, 7.0]])
     self.plugin = FallingSnowLevel()
 def test_basic(self):
     """Test fills in missing data with orography + highest height"""
     plugin = FallingSnowLevel()
     self.highest_wb_int[1, 1] = 100.0
     expected = np.array([[1.0, 1.0, 2.0], [1.0, 301.0, 2.0],
                          [1.0, 2.0, 2.0]])
     plugin.fill_in_high_snow_falling_levels(self.snow_level_data,
                                             self.orog, self.highest_wb_int,
                                             self.highest_height)
     self.assertArrayEqual(self.snow_level_data, expected)
 def test_basic(self):
     """Test that process returns a cube with the right name and units."""
     result = FallingSnowLevel().process(
         self.temperature_cube, self.relative_humidity_cube,
         self.pressure_cube, self.orog)
     expected = np.ones((2, 3, 3)) * 66.88732723
     self.assertIsInstance(result, iris.cube.Cube)
     self.assertEqual(result.name(), "falling_snow_level_asl")
     self.assertEqual(result.units, Unit('m'))
     self.assertArrayAlmostEqual(result.data, expected)
예제 #11
0
 def test_gradients_zero(self):
     """Test we do nothing if all gradients are zero"""
     plugin = FallingSnowLevel()
     gradients = np.zeros((3, 3))
     plugin.find_extrapolated_falling_level(
         self.max_wb_integral, gradients, self.intercepts,
         self.snow_falling_level, self.sea_points)
     expected_snow_falling_level = np.ones((3, 3))*np.nan
     self.assertArrayAlmostEqual(expected_snow_falling_level,
                                 self.snow_falling_level)
예제 #12
0
 def test_no_fill_if_conditions_not_met(self):
     """Test it doesn't fill in NaN if the heighest wet bulb integral value
        is less than the threshold."""
     plugin = FallingSnowLevel()
     expected = np.array([[1.0, 1.0, 2.0], [1.0, np.nan, 2.0],
                          [1.0, 2.0, 2.0]])
     plugin.fill_in_high_snow_falling_levels(self.snow_level_data,
                                             self.orog, self.highest_wb_int,
                                             self.highest_height)
     self.assertArrayEqual(self.snow_level_data, expected)
예제 #13
0
 def test_basic(self):
     """Test method returns an array with correct data"""
     plugin = FallingSnowLevel()
     expected = np.array([[1.0, 1.0, 2.0], [1.0, 1.5, 2.0], [1.0, 2.0,
                                                             2.0]])
     result = plugin.fill_in_missing_data(self.snow_level_data, self.orog,
                                          self.highest_wb_int,
                                          self.highest_height)
     self.assertIsInstance(result, np.ndarray)
     self.assertArrayEqual(result, expected)
예제 #14
0
 def test_all_above_threshold(self):
     """Test it doesn't change points that are all above the threshold"""
     plugin = FallingSnowLevel()
     self.max_wb_integral[0, 1] = 100
     self.snow_falling_level[0, 1] = 100
     self.expected_snow_falling_level[0, 1] = 100
     plugin.fill_in_sea_points(self.snow_falling_level, self.land_sea,
                               self.max_wb_integral,
                               self.wet_bulb_temperature, self.heights)
     self.assertArrayAlmostEqual(self.snow_falling_level.data,
                                 self.expected_snow_falling_level)
예제 #15
0
 def test_freezing_points(self):
     """Test with integral below threshold sets snow level to missing_value
         where the data can not be interpolated from other points
         and points are not a sea-level points."""
     plugin = FallingSnowLevel()
     expected = np.array([[-300.0, -300.0, -300.0], [1.0, 1.5, 2.0],
                          [1.0, 2.0, -300.0]])
     result = plugin.fill_in_missing_data(self.snow_data_no_interp,
                                          self.orog, self.highest_wb_int,
                                          self.highest_height)
     self.assertIsInstance(result, np.ndarray)
     self.assertArrayEqual(result, expected)
예제 #16
0
 def test_freezing_sealevel_point(self):
     """Test sea point with integral below threshold sets snow level to 0"""
     plugin = FallingSnowLevel()
     orog = self.orog
     orog[1, 1] = 0.0
     expected = np.array([[1.0, 1.0, 2.0], [1.0, 0.0, 2.0], [1.0, 2.0,
                                                             2.0]])
     result = plugin.fill_in_missing_data(self.snow_level_data, orog,
                                          self.highest_wb_int,
                                          self.highest_height)
     self.assertIsInstance(result, np.ndarray)
     self.assertArrayEqual(result, expected)
예제 #17
0
 def test_nonfreezing_points(self):
     """Test with integral above threshold sets snow level to highest_level
         plus orograpy where the data can not be
         interpolated from other points and points are not
         sea-level points."""
     plugin = FallingSnowLevel()
     highest_wb_int = self.highest_wb_int * 100.0
     expected = np.array([[301.0, 301.0, 301.0], [1.0, 1.5, 2.0],
                          [1.0, 2.0, 301.0]])
     result = plugin.fill_in_missing_data(self.snow_data_no_interp,
                                          self.orog, highest_wb_int,
                                          self.highest_height)
     self.assertIsInstance(result, np.ndarray)
     self.assertArrayEqual(result, expected)
예제 #18
0
 def test_basic(self):
     """Test that the __repr__ returns the expected string."""
     result = str(FallingSnowLevel())
     msg = ('<FallingSnowLevel: '
            'precision:0.005, falling_level_threshold:90.0,'
            ' grid_point_radius: 2>')
     self.assertEqual(result, msg)
 def test_data(self):
     """Test that the falling snow level process returns a cube
     containing the expected data when points at sea-level."""
     expected = np.ones((2, 3, 3)) * 65.88732723
     expected[:, 1, 1] = 0.0
     orog = self.orog
     orog.data = orog.data * 0.0
     result = FallingSnowLevel().process(
         self.temperature_cube, self.relative_humidity_cube,
         self.pressure_cube, self.orog)
     self.assertIsInstance(result, iris.cube.Cube)
     self.assertArrayAlmostEqual(result.data, expected)
예제 #20
0
def process(temperature,
            relative_humidity,
            pressure,
            orog,
            land_sea,
            precision=0.005,
            falling_level_threshold=90.0):
    """Module to calculate continuous snow falling level.

    Calculate the wet-bulb temperature integral by firstly calculating the
    wet-bulb temperature from the inputs provided and then calculating the
    vertical integral of the wet-bulb temperature.
    Find the falling_snow_level by finding the height above sea level
    corresponding to the falling_level_threshold in the integral data.

    Args:
        temperature (iris.cube.Cube):
            Cube of air temperature at heights (m) at the points for which the
            continuous falling snow level is being calculated.
        relative_humidity (iris.cube.Cube):
            Cube of relative humidities at heights (m) at the points for which
            the continuous falling snow level is being calculated.
        pressure (iris.cube.Cube):
            Cube of air pressure at heights (m) at the points for which the
            continuous falling snow level is being calculated.
        orog (iris.cube.Cube):
            Cube of the orography height in m of the terrain over which the
            continuous falling snow level is being calculated.
        land_sea (iris.cube.Cube):
            Cube containing the binary land-sea mask for the points for which
            the continuous falling snow level is being calculated. Land points
            are set to 1, sea points are set to 0.
        precision (float):
            Precision to which the wet-bulb temperature is required: This is
            used by the Newton iteration.
            Default is 0.005.
        falling_level_threshold (float):
            Cutoff threshold for the wet-bulb integral used to calculate the
            falling snow level. This threshold indicates the level at which
            falling snow is deemed to have melted to become rain.
            Default is 90.0.

    Returns:
        iris.cube.Cube:
            Processed Cube of falling snow level above sea level.
    """
    result = FallingSnowLevel(
        precision=precision,
        falling_level_threshold=falling_level_threshold).process(
            temperature, relative_humidity, pressure, orog, land_sea)
    return result
예제 #21
0
 def test_data(self):
     """Test that the falling snow level process returns a cube
     containing the expected data when points at sea-level."""
     expected = np.ones((2, 3, 3), dtype=np.float32) * 65.88566
     orog = self.orog
     orog.data = orog.data * 0.0
     orog.data[1, 1] = 100.0
     land_sea = self.land_sea
     land_sea = land_sea * 0.0
     result = FallingSnowLevel().process(self.temperature_cube,
                                         self.relative_humidity_cube,
                                         self.pressure_cube, orog, land_sea)
     self.assertIsInstance(result, iris.cube.Cube)
     self.assertArrayAlmostEqual(result.data, expected)
예제 #22
0
 def test_basic(self):
     """Test the function does what it's meant to in a simple case."""
     plugin = FallingSnowLevel(grid_point_radius=1)
     result = plugin.find_max_in_nbhood_orography(self.cube)
     self.assertArrayAlmostEqual(result.data, self.expected_data)
예제 #23
0
def main(argv=None):
    """Load in arguments and get going."""
    parser = ArgParser(
        description="Calculate the continuous falling snow level ")
    parser.add_argument("temperature", metavar="TEMPERATURE",
                        help="Path to a NetCDF file of air temperatures at"
                        " heights (m) at the points for which the continuous "
                        "falling snow level is being calculated.")
    parser.add_argument("relative_humidity", metavar="RELATIVE_HUMIDITY",
                        help="Path to a NetCDF file of relative_humidities at"
                        " heights (m) at the points for which the continuous "
                        "falling snow level is being calculated.")
    parser.add_argument("pressure", metavar="PRESSURE",
                        help="Path to a NetCDF file of air pressures at"
                        " heights (m) at the points for which the continuous "
                        "falling snow level is being calculated.")
    parser.add_argument("orography", metavar="OROGRAPHY",
                        help="Path to a NetCDF file containing "
                        "the orography height in m of the terrain "
                        "over which the continuous falling snow level is "
                        "being calculated.")
    parser.add_argument("land_sea_mask", metavar="LAND_SEA_MASK",
                        help="Path to a NetCDF file containing "
                        "the binary land-sea mask for the points "
                        "for which the continuous falling snow level is "
                        "being calculated. Land points are set to 1, sea "
                        "points are set to 0.")
    parser.add_argument("output_filepath", metavar="OUTPUT_FILE",
                        help="The output path for the processed NetCDF")
    parser.add_argument("--precision", metavar="NEWTON_PRECISION",
                        default=0.005, type=float,
                        help="Precision to which the wet bulb temperature "
                        "is required: This is used by the Newton iteration "
                        "default value is 0.005")
    parser.add_argument("--falling_level_threshold",
                        metavar="FALLING_LEVEL_THRESHOLD",
                        default=90.0, type=float,
                        help=("Cutoff threshold for the wet-bulb integral used"
                              " to calculate the falling snow level. This "
                              "threshold indicates the level at which falling "
                              "snow is deemed to have melted to become rain. "
                              "The default value is 90.0, an empirically "
                              "derived value."))
    args = parser.parse_args(args=argv)

    temperature = load_cube(args.temperature, no_lazy_load=True)
    relative_humidity = load_cube(args.relative_humidity, no_lazy_load=True)
    pressure = load_cube(args.pressure, no_lazy_load=True)
    orog = load_cube(args.orography, no_lazy_load=True)
    land_sea = load_cube(args.land_sea_mask, no_lazy_load=True)

    result = FallingSnowLevel(
        precision=args.precision,
        falling_level_threshold=args.falling_level_threshold).process(
            temperature,
            relative_humidity,
            pressure,
            orog,
            land_sea)

    save_netcdf(result, args.output_filepath)
예제 #24
0
class Test_fill_in_by_horizontal_interpolation(IrisTest):
    """Test the fill_in_by_horizontal_interpolation method"""
    def setUp(self):
        """ Set up arrays for testing."""
        self.snow_level_data = np.array([[1.0, 1.0, 2.0], [1.0, np.nan, 2.0],
                                         [1.0, 2.0, 2.0]])
        self.orog_data = np.array([[6.0, 6.0, 6.0], [6.0, 7.0, 6.0],
                                   [6.0, 6.0, 6.0]])
        self.max_in_nbhood_orog = np.array([[7.0, 7.0, 7.0], [7.0, 7.0, 7.0],
                                            [7.0, 7.0, 7.0]])
        self.plugin = FallingSnowLevel()

    def test_basic(self):
        """Test when all the points around the missing data are the same."""
        snow_level_data = np.ones((3, 3))
        snow_level_data[1, 1] = np.nan
        expected = np.array([[1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0,
                                                                1.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            snow_level_data, self.max_in_nbhood_orog, self.orog_data)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_different_data(self):
        """Test when the points around the missing data have different
           values."""
        expected = np.array([[1.0, 1.0, 2.0], [1.0, 1.5, 2.0], [1.0, 2.0,
                                                                2.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            self.snow_level_data, self.max_in_nbhood_orog, self.orog_data)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_lots_missing(self):
        """Test when there's an extra missing value at the corner
           of the grid. This point can't be filled in by linear interpolation,
           but is instead filled by nearest neighbour extrapolation."""
        self.snow_level_data[2, 2] = np.nan
        expected = np.array([[1.0, 1.0, 2.0], [1.0, 1.5, 2.0], [1.0, 2.0,
                                                                2.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            self.snow_level_data, self.max_in_nbhood_orog, self.orog_data)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_all_above_max_orography(self):
        """Test that nothing is filled in if all the snow falling levels are
           above the maximum orography"""
        max_in_nbhood_orog = np.zeros((3, 3))
        orography = np.zeros((3, 3))
        expected = np.array([[1.0, 1.0, 2.0], [1.0, np.nan, 2.0],
                             [1.0, 2.0, 2.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            self.snow_level_data, max_in_nbhood_orog, orography)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_set_to_orography(self):
        """Test when the linear interpolation gives values that are higher
           than the orography the snow falling level is set back to the
           orography"""
        snow_falling_level = np.array([[10.0, np.nan, np.nan, np.nan, 20.0],
                                       [10.0, np.nan, np.nan, np.nan, 20.0],
                                       [10.0, np.nan, np.nan, np.nan, 20.0],
                                       [10.0, np.nan, np.nan, np.nan, 20.0],
                                       [10.0, np.nan, np.nan, np.nan, 20.0]])

        orography = np.array([[0.0, 30.0, 12.0, 30.0, 0.0],
                              [0.0, 30.0, 12.0, 30.0, 0.0],
                              [0.0, 30.0, 12.0, 30.0, 0.0],
                              [0.0, 30.0, 12.0, 30.0, 0.0],
                              [0.0, 30.0, 12.0, 30.0, 0.0]])

        max_in_nbhood_orog = np.ones((5, 5)) * 30.0
        expected = np.array([[10.0, 12.5, 12.0, 17.5, 20.0],
                             [10.0, 12.5, 12.0, 17.5, 20.0],
                             [10.0, 12.5, 12.0, 17.5, 20.0],
                             [10.0, 12.5, 12.0, 17.5, 20.0],
                             [10.0, 12.5, 12.0, 17.5, 20.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            snow_falling_level, max_in_nbhood_orog, orography)
        self.assertArrayEqual(snow_level_updated, expected)
예제 #25
0
class Test_fill_in_by_horizontal_interpolation(IrisTest):
    """Test the fill_in_by_horizontal_interpolation method"""
    def setUp(self):
        """ Set up arrays for testing."""
        self.snow_level_data = np.array([[1.0, 1.0, 2.0], [1.0, np.nan, 2.0],
                                         [1.0, 2.0, 2.0]])
        self.orog_data = np.array([[6.0, 6.0, 6.0], [6.0, 7.0, 6.0],
                                   [6.0, 6.0, 6.0]])
        self.max_in_nbhood_orog = np.array([[7.0, 7.0, 7.0], [7.0, 7.0, 7.0],
                                            [7.0, 7.0, 7.0]])
        self.plugin = FallingSnowLevel()

    def test_basic(self):
        """Test when all the points around the missing data are the same."""
        snow_level_data = np.ones((3, 3))
        snow_level_data[1, 1] = np.nan
        expected = np.array([[1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0,
                                                                1.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            snow_level_data, self.max_in_nbhood_orog, self.orog_data)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_not_enough_points_to_fill(self):
        """Test when there are not enough points to fill the gaps.
           This raises a QhullError if there are less than 3 points available
           to use for the interpolation. The QhullError is different to the one
           raised by test_badly_arranged_valid_data"""
        snow_level_data = np.array([[np.nan, 1, np.nan],
                                    [np.nan, np.nan, np.nan],
                                    [np.nan, 1, np.nan]])
        expected = np.array([[1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0,
                                                                1.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            snow_level_data, self.max_in_nbhood_orog, self.orog_data)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_badly_arranged_valid_data(self):
        """Test when there are enough points but they aren't arranged in a
           suitable way to allow horizontal interpolation. This raises a
           QhullError that we want to ignore and use nearest neighbour
           interpolation instead. This QhullError is different to the one
           raised by test_not_enough_points_to_fill."""
        snow_level_data = np.array([[np.nan, 1, np.nan], [np.nan, 1, np.nan],
                                    [np.nan, 1, np.nan]])
        expected = np.array([[1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0,
                                                                1.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            snow_level_data, self.max_in_nbhood_orog, self.orog_data)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_different_data(self):
        """Test when the points around the missing data have different
           values."""
        expected = np.array([[1.0, 1.0, 2.0], [1.0, 1.5, 2.0], [1.0, 2.0,
                                                                2.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            self.snow_level_data, self.max_in_nbhood_orog, self.orog_data)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_lots_missing(self):
        """Test when there's an extra missing value at the corner
           of the grid. This point can't be filled in by linear interpolation,
           but is instead filled by nearest neighbour extrapolation."""
        self.snow_level_data[2, 2] = np.nan
        expected = np.array([[1.0, 1.0, 2.0], [1.0, 1.5, 2.0], [1.0, 2.0,
                                                                2.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            self.snow_level_data, self.max_in_nbhood_orog, self.orog_data)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_all_above_max_orography(self):
        """Test that nothing is filled in if all the snow falling levels are
           above the maximum orography"""
        max_in_nbhood_orog = np.zeros((3, 3))
        orography = np.zeros((3, 3))
        expected = np.array([[1.0, 1.0, 2.0], [1.0, np.nan, 2.0],
                             [1.0, 2.0, 2.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            self.snow_level_data, max_in_nbhood_orog, orography)
        self.assertArrayEqual(snow_level_updated, expected)

    def test_set_to_orography(self):
        """Test when the linear interpolation gives values that are higher
           than the orography the snow falling level is set back to the
           orography"""
        snow_falling_level = np.array([[10.0, np.nan, np.nan, np.nan, 20.0],
                                       [10.0, np.nan, np.nan, np.nan, 20.0],
                                       [10.0, np.nan, np.nan, np.nan, 20.0],
                                       [10.0, np.nan, np.nan, np.nan, 20.0],
                                       [10.0, np.nan, np.nan, np.nan, 20.0]])

        orography = np.array([[0.0, 30.0, 12.0, 30.0, 0.0],
                              [0.0, 30.0, 12.0, 30.0, 0.0],
                              [0.0, 30.0, 12.0, 30.0, 0.0],
                              [0.0, 30.0, 12.0, 30.0, 0.0],
                              [0.0, 30.0, 12.0, 30.0, 0.0]])

        max_in_nbhood_orog = np.ones((5, 5)) * 30.0
        expected = np.array([[10.0, 12.5, 12.0, 17.5, 20.0],
                             [10.0, 12.5, 12.0, 17.5, 20.0],
                             [10.0, 12.5, 12.0, 17.5, 20.0],
                             [10.0, 12.5, 12.0, 17.5, 20.0],
                             [10.0, 12.5, 12.0, 17.5, 20.0]])
        snow_level_updated = self.plugin.fill_in_by_horizontal_interpolation(
            snow_falling_level, max_in_nbhood_orog, orography)
        self.assertArrayEqual(snow_level_updated, expected)