Coverage for src / CSET / operators / temperature.py: 0%
28 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-02 15:01 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-02 15:01 +0000
1# © Crown copyright, Met Office (2022-2026) and CSET contributors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
15"""Operators for temperature conversions."""
17import iris.cube
18import numpy as np
20from CSET._common import iter_maybe
21from CSET.operators.constants import EPSILON, T0
22from CSET.operators.pressure import vapour_pressure
25def dewpoint_temperature(
26 temperature: iris.cube.Cube | iris.cube.CubeList,
27 relative_humidity: iris.cube.Cube | iris.cube.CubeList,
28) -> iris.cube.Cube | iris.cube.CubeList:
29 """Calculate the dewpoint temperature."""
30 Td = iris.cube.CubeList([])
31 for T, RH in zip(
32 iter_maybe(temperature), iter_maybe(relative_humidity), strict=True
33 ):
34 vp = vapour_pressure(T, RH)
35 td = vp.copy()
36 td.data = (243.5 * np.log(vp.core_data()) - 440.8) / (
37 19.48 - np.log(vp.core_data())
38 )
39 td.data[td.data - T0 < -35.0] = np.nan
40 td.data[td.data - T0 > 35.0] = np.nan
41 td.units("K")
42 td.rename("dewpoint temperature")
43 Td.append(td)
44 if len(Td) == 1:
45 return Td[0]
46 else:
47 return Td
50def virtual_temperature(
51 temperature: iris.cube.Cube | iris.cube.CubeList,
52 mixing_ratio: iris.cube.Cube | iris.cube.CubeList,
53) -> iris.cube.Cube | iris.cube.CubeList:
54 """Calculate the virtual temperature."""
55 Tv = iris.cube.CubeList([])
56 for T, W in zip(iter_maybe(temperature), iter_maybe(mixing_ratio), strict=True):
57 virT = T * ((W + EPSILON) / (EPSILON * (1 + W)))
58 virT.rename("virtual_temperature")
59 Tv.append(virT)
60 if len(Tv) == 1:
61 return Tv[0]
62 else:
63 return Tv