Beispiel #1
0
 def setup_method(self):
     """
     This ensures a new Workspace for every test.
     """
     self.dir = os.path.dirname(os.path.realpath(__file__))
     self.ws = Workspace(verbosity=0)
     self.setup_workspace()
Beispiel #2
0
 def test_variable_create(self):
     """
     Test initialization of workspace variables.
     """
     self.ws = Workspace()
     self.ws.IndexCreate("myindex")
     with pytest.raises(Exception):
         print(self.ws.myindex.value)
Beispiel #3
0
def configure_workspace(verbosity=0):
    """Configures the ARTS application.

    Args:
        verbosity: ARTS verbosity level.

    Returns:
        A Workspace object.
    """
    workspace = Workspace(verbosity=0)
    for name in ["general", "continua", "agendas"]:
        workspace.execute_controlfile(join("general", "{}.arts".format(name)))
    workspace.verbositySetScreen(workspace.verbosity, verbosity)
    workspace.jacobianOff()
    workspace.Copy(workspace.abs_xsec_agenda, workspace.abs_xsec_agenda__noCIA)
    workspace.AtmosphereSet1D()
    return workspace
Beispiel #4
0
    def setup(self, verbosity=0):

        self.verbosity  = verbosity
        self._workspace = Workspace(verbosity=verbosity,
                                    agenda_verbosity=verbosity)
        ws = self._workspace
        for include in self.includes:
            ws.execute_controlfile(include)

        ws.Copy(ws.ppath_agenda, ws.ppath_agenda__FollowSensorLosPath)
        ws.Copy(ws.ppath_step_agenda, ws.ppath_step_agenda__GeometricPath)
        ws.Copy(ws.iy_space_agenda, ws.iy_space_agenda__CosmicBackground)
        ws.Copy(ws.iy_surface_agenda, ws.iy_surface_agenda__UseSurfaceRtprop)
        ws.Copy(ws.iy_main_agenda, ws.iy_main_agenda__Emission)

        self.atmosphere.setup(ws, self.sensors)

        for s in self.sensors:
            s.setup(ws, self.atmosphere.scattering)

        self._setup = True
Beispiel #5
0
def test_dimension_broadcast():
    """
    Test propagation of dimension information for ARTS properties
    as well as broadcasting.
    """
    class A(ArtsObject):
        def __init__(self):
            super().__init__()
            pass

        @arts_property("Vector", shape=(dim.P, ), wsv=wsv["p_grid"])
        def p_grid():
            return None

        @arts_property("Tensor3",
                       shape=(dim.P, dim.Lat, dim.Lon),
                       wsv=wsv["t_field"])
        def temperature(self):
            return None

    class TProvider:
        def __init__(self):
            pass

        def get_temperature(self):
            return np.ones((1, 3, 5))

    ws = Workspace()
    a = A()
    dp = TProvider()

    a.p_grid = np.zeros(4)

    a.setup_arts_properties(ws)
    a.get_data_arts_properties(ws, dp)

    assert (ws.t_field.value.shape[0] == 4)
    assert (np.all(ws.p_grid.value == np.zeros(4)))
Beispiel #6
0
import os

from pyarts.workspace import Workspace
from pyarts.classes.SpeciesAuxData import SpeciesAuxData
from pyarts.classes import from_workspace

# Get a workspace
ws = Workspace()
datapath = "../../arts-xml-data/" if not os.getenv(
    "ARTS_XML_DATA_DIR") else os.getenv("ARTS_XML_DATA_DIR")
fn = os.path.join(datapath, 'planets/Mars/isotopratio_Mars.xml')

sad1 = SpeciesAuxData()
sad1.readxml(fn)
sad2 = from_workspace(ws.isotopologue_ratios)
ws.ReadXML(ws.isotopologue_ratios, fn)
sad3 = SpeciesAuxData()
sad3.set(sad2)
sad4 = SpeciesAuxData()

sad1.savexml("tmp.sad.xml", "binary")
sad4.readxml("tmp.sad.xml")
assert sad1 == sad4

assert sad1 == sad2
assert sad1 == sad3
Beispiel #7
0
import os
from pyarts.workspace import Workspace
from pyarts.classes import from_workspace
from pyarts.classes.AbsorptionLines import AbsorptionLines, ArrayOfAbsorptionLines

ws = Workspace()
datapath = "../../arts-xml-data/" if not os.getenv(
    "ARTS_XML_DATA_DIR") else os.getenv("ARTS_XML_DATA_DIR")
fn1 = os.path.join(datapath, 'spectroscopy/Artscat/')
fn2 = os.path.join(datapath, 'spectroscopy/Artscat/O2-66.xml')

# Init
al = AbsorptionLines()
aal = ArrayOfAbsorptionLines()
aaal = from_workspace(ws.abs_lines_per_species)

# Init is as expected
assert al.selfbroadening == False, "Bad init"
assert al.bathbroadening == False, "Bad init"
assert al.cutoff == "None", "Bad init"
assert al.mirroring == "None", "Bad init"
assert al.population == "LTE", "Bad init"
assert al.normalization == "None", "Bad init"
assert al.lineshapetype == "VP", "Bad init"
assert al.t0 == 296, "Bad init"
assert al.cutofffreq == -1, "Bad init"
assert al.linemixinglimit == -1, "Bad init"
assert al.quantumidentity.spec_ind == -1, "Bad init"
assert al.quantumidentity.type == "None", "Bad init"
assert not al.localquantumnumbers, "Bad init"
assert not al.broadeningspecies, "Bad init"
Beispiel #8
0
 def setup_method(self):
     """
     This ensures a new Workspace for every test.
     """
     self.ws = Workspace(verbosity = 0)
     self.setup_workspace()
Beispiel #9
0
class TestVariables:
    """
    Tests the manipulation of workspace variables.
    """
    def setup_method(self):
        """
        This ensures a new Workspace for every test.
        """
        self.dir = os.path.dirname(os.path.realpath(__file__))
        self.ws = Workspace(verbosity=0)
        self.setup_workspace()

    def setup_workspace(self):
        ws = self.ws
        ws.atmosphere_dim = 1
        ws.p_grid = np.linspace(1e5, 1e3, 21)
        ws.Touch(ws.lat_grid)
        ws.Touch(ws.lon_grid)

        ws.f_grid = 183.0e9 * np.ones(1)
        ws.stokes_dim = 1

        ws.sensor_los = 180.0 * np.ones((1, 1))
        ws.sensor_pos = 830e3 * np.ones((1, 1))
        ws.sensorOff()

    def test_index_transfer(self):
        """
        Create and set Index WSV.
        """
        self.ws.IndexCreate("index_variable")
        i = np.random.randint(0, 100)
        self.ws.index_variable = i
        assert self.ws.index_variable.value == i

    def test_string_transfer(self):
        """
        Create and set String WSV.
        """
        self.ws.StringCreate("string_variable")
        s = "some random string."
        self.ws.string_variable = s
        assert self.ws.string_variable.value == s

    def test_array_of_index_transfer(self):
        """
        Create and set ArrayOfIndex WSV.
        """
        self.ws.ArrayOfIndexCreate("array_of_index_variable")
        i = [np.random.randint(0, 100) for j in range(10)]

        self.ws.array_of_index_variable = i
        assert self.ws.array_of_index_variable.value == i

        self.ws.array_of_index_variable = []
        assert self.ws.array_of_index_variable.value == []

    def test_array_of_vector_transfer(self):
        """
        Create and set ArrayOfVector WSV.

        """
        self.ws.ArrayOfVectorCreate("array_of_vector_variable")
        aov = pyarts.xml.load(
            os.path.join(self.dir, "../xml/reference/arrayofvector.xml"))
        self.ws.array_of_vector_variable = aov
        assert self.ws.array_of_vector_variable.value == aov

    def test_vector_transfer(self):
        """
        Create and set Vector WSV.
        """
        self.ws.VectorCreate("vector_variable")
        v = np.random.rand(10)
        self.ws.vector_variable = v
        assert all(self.ws.vector_variable.value == v)

    def test_matrix_transfer(self):
        """
        Create and set Matrix WSV.
        """
        self.ws.MatrixCreate("matrix_variable")
        m = np.random.rand(10, 10)
        self.ws.matrix_variable = m
        assert all(self.ws.matrix_variable.value.ravel() == m.ravel())

    def test_sparse_transfer(self):
        """
        Create and set Sparse WSV.
        """
        n = 100
        d2 = np.ones(n - 2)
        d1 = np.ones(n - 1)
        d = np.ones(n)
        m = sp.sparse.diags(diagonals=[d2, d1, d, d1, d2],
                            offsets=[2, 1, 0, -1, -2])
        self.ws.sensor_response = m
        assert np.all(m.toarray() == self.ws.sensor_response.value.toarray())

    def test_tensor_3(self):
        """
        Create and set Tensor3 variable.
        """
        t_0 = np.random.rand(*([3] * 3))
        self.ws.Tensor3Create("tensor_3")
        self.ws.tensor_3 = t_0
        assert np.all(t_0 == self.ws.tensor_3.value)

    def test_tensor_4(self):
        """
        Create and set Tensor4 variable.
        """
        t_0 = np.random.rand(*([3] * 4))
        t_1 = self.ws.Tensor4Create("tensor_4")
        self.ws.tensor_4 = t_0
        assert np.all(t_0 == self.ws.tensor_4.value)

    def test_tensor_5(self):
        """
        Create and set Tensor5 variable.
        """
        t_0 = np.random.rand(*([3] * 5))
        t_1 = self.ws.Tensor5Create("tensor_5")
        self.ws.tensor_5 = t_0
        assert np.all(t_0 == self.ws.tensor_5.value)

    def test_tensor_6(self):
        """
        Create and set Tensor6 variable.
        """
        t_0 = np.random.rand(*([3] * 6))
        t_1 = self.ws.Tensor6Create("tensor_6")
        self.ws.tensor_6 = t_0
        assert np.all(t_0 == self.ws.tensor_6.value)

    def test_tensor_7(self):
        """
        Create and set Tensor7 variable.
        """
        t_0 = np.random.rand(*([3] * 7))
        self.ws.Tensor7Create("tensor_7")
        self.ws.tensor_7 = t_0
        assert np.all(t_0 == self.ws.tensor_7.value)

    def test_time(self):
        """
        Create and set Time variable.
        """
        times = ["2020-01-02 03:04:05", "2021-02-03 04:05:06"]
        self.ws.ArrayOfTimeCreate("time_1")
        self.ws.ArrayOfTimeNLinSpace(self.ws.time_1, 2, times[0], times[1])
        assert (times[0] == str(self.ws.time_1.value[0])[0:19]
                and times[1] == str(self.ws.time_1.value[1])[0:19])

    def test_creation(self):
        """
        Test creation of WSVs.
        """
        self.ws.ArrayOfIndexCreate("array_of_index")
        self.ws.ArrayOfIndexCreate("array_of_index")
        with pytest.raises(Exception):
            self.ws.VectorCreate("array_of_index")

    def test_covariance_matrix(self):
        """
        Test manipulation of CorvarianceMatrix objects.
        """
        ws = self.ws

        ws.jacobianInit()
        ws.jacobianAddAbsSpecies(species="O3",
                                 g1=ws.p_grid,
                                 g2=ws.lat_grid,
                                 g3=ws.lon_grid)
        ws.jacobianAddAbsSpecies(species="H2O",
                                 g1=ws.p_grid,
                                 g2=ws.lat_grid,
                                 g3=ws.lon_grid)
        ws.jacobianClose()

        ws.covmatDiagonal(out=ws.covmat_block,
                          out_inverse=ws.covmat_block,
                          vars=10.0 * np.ones(ws.p_grid.value.size))
        ws.covmat_sxAddBlock(block=ws.covmat_block)
        ws.covmatDiagonal(out=ws.covmat_block,
                          out_inverse=ws.covmat_block,
                          vars=20.0 * np.ones(ws.p_grid.value.size))
        ws.covmat_sxAddBlock(block=ws.covmat_block)

    def test_variable_creation(self):
        """
        Test creation of named and unnambed WSVs.
        """

        # Unnamed variable
        wsv = self.ws.create_variable("Matrix", None)
        self.ws.__setattr__(wsv.name, np.eye(5))
        assert np.all(
            np.isclose(np.eye(5),
                       self.ws.__getattr__(wsv.name).value))

        # Named variable
        wsv = self.ws.create_variable("Matrix", "matrix_wsv")
        self.ws.matrix_wsv = np.eye(5)
        assert np.all(np.isclose(np.eye(5), self.ws.matrix_wsv.value))

    def test_variable_set_empty(self):
        """
        Test initialization of workspace variables.
        """
        self.ws.f_grid = np.array([94e9])
        self.ws.f_grid = []
        assert self.ws.f_grid.value.size == 0

    def test_variable_create(self):
        """
        Test initialization of workspace variables.
        """
        self.ws = Workspace()
        self.ws.IndexCreate("myindex")
        with pytest.raises(Exception):
            print(self.ws.myindex.value)

    def test_convert(self):
        """
        Test automatic conversion of Python types.
        """

        v = WorkspaceVariable.convert("Index", 1.2)
        assert (v == 1)

        v = WorkspaceVariable.convert("String", "string")
        assert (v == "string")

        v = WorkspaceVariable.convert("Numeric", 1)
        assert (type(v) == np.float64)

        v = WorkspaceVariable.convert("Vector", 1.0)
        assert (v.shape == (1, ))

        v = WorkspaceVariable.convert("Matrix", 1.0)
        assert (v.shape == (1, 1))

        v = WorkspaceVariable.convert("Tensor3", 1.0)
        assert (v.shape == (1, 1, 1))

        v = WorkspaceVariable.convert("Tensor6", 1.0)
        assert (v.shape == (1, 1, 1, 1, 1, 1))

        v = WorkspaceVariable.convert("ArrayOfArrayOfIndex", 1.0)
        assert (type(v) == list)
        assert (type(v[0]) == list)
        assert (type(v[0][0]) == int)

        v = WorkspaceVariable.convert("ArrayOfArrayOfIndex", 1)
        return v
Beispiel #10
0
from time import sleep
from math import isclose

from pyarts.workspace import Workspace
from pyarts.classes.Timer import Timer
from pyarts.classes import from_workspace

ws = Workspace()
ws.timerStart()

time = 1
sleep(time)

ws.timerStop()

t = from_workspace(ws.timer)
assert isinstance(t, Timer)

if t.supported:
    # Test that we are within 2.5 ticks of the true answer
    assert isclose((t.realtime_end - t.realtime_start) / t.tick,
                   time,
                   rel_tol=2.5 / t.tick)

# t2 = Timer()
# t.savexml("tmp.t.xml", "binary")
# t2.readxml("tmp.t.xml")
# assert t == t2
Beispiel #11
0
class TestAgendas:
    """
    Tests the calling of ARTS workspace methods.
    """
    def setup_method(self):
        """
        This ensures a new Workspace for every test.
        """
        self.ws = Workspace(verbosity = 0)
        self.setup_workspace()

    def setup_workspace(self):
        self.ws.execute_controlfile("artscomponents/clearsky/TestClearSky.arts")

    def test_assignment(self):
        """
        Test assignment of agendas.
        """
        ws = self.ws
        ws.ppath_agenda = ppath_agenda

    def test_include(self):
        ws = self.ws

        @arts_agenda
        def ppath_agenda_inc(ws):
            INCLUDE(ppath_agenda)

        ws.ppath_agenda = ppath_agenda_inc

    def test_execution(self):
        """
        Test definition and execution of agendas.
        """

        self.ws.atmosphere_dim = 1

        @arts_agenda
        def add_1(ws):
            ws.IndexAdd(ws.atmosphere_dim,
                        ws.atmosphere_dim,
                        1)
        add_1.execute(self.ws)

        assert self.ws.atmosphere_dim.value == 2

        add_1.append(add_1)
        add_1.execute(self.ws)

        assert self.ws.atmosphere_dim.value == 4

        args = [self.ws.atmosphere_dim, self.ws.atmosphere_dim, 1]

        @arts_agenda
        def add_2(ws):
            ws.IndexAdd(*args)

        add_2.execute(self.ws)

        assert self.ws.atmosphere_dim.value == 5

    def test_callback(self):
        """
        Test callbacks by re-implementing iy_space_agenda in Python and
        comparing results of yCalc.
        """
        z_ppath = []

        ws = self.ws

        ws.yCalc()
        y_old = np.copy(ws.y.value)

        import scipy.constants as c

        @arts_agenda(allow_callbacks=True)
        def space_agenda(ws):
            # Since everything happens in Python we need
            # to tell ARTS that we are using all in and outputs.
            ws.Ignore(ws.f_grid)
            ws.Ignore(ws.rtp_pos)
            ws.Ignore(ws.rtp_los)
            ws.Touch(ws.iy)

            # Temperatures and frequency
            t = 2.735
            f = ws.f_grid.value

            # Compute radiances
            c1 = 2.0 * c.h / c.c ** 2
            c2 = c.h / c.k
            b = c1 * f ** 3 / (np.exp(c2 * f / t) - 1.0)

            # Put into iy vector.
            ws.iy = np.zeros((f.size, ws.stokes_dim.value))
            ws.iy.value[:, 0] = b

        # Copy ppath_agenda into workspace.
        ws.iy_space_agenda = space_agenda
        ws.yCalc()

        y_new = np.copy(ws.y.value)

        assert(np.allclose(y_new, y_old))


    def test_callback_2(self):
        """
        Test a very complicated Python callback.
        """

        @arts_agenda(allow_callbacks=True)
        def agenda(ws):
            """
            This agenda sets a workspace variable in a very
            obscure way.
            """

            class Foo:
                def __init__(self, ws):
                    self.ws = ws

                def ooo(self):
                    self.ws.IndexSet(ws.stokes_dim, 42)

            foo = Foo(ws)
            ws.IndexSet(ws.stokes_dim, 21)
            foo.ooo()

        agenda.execute(self.ws)

    def test_unknown_wsv(self):
        """
        Ensure that an exception is thrown when an unknown WSV is
        used inside an agenda.

        This covers https://github.com/atmtools/arts/issues/368
        """
        with pytest.raises(ValueError):
            @arts_agenda
            def my_agenda(ws):
                  ws.UnknownMethod()

    def test_starred(self):
        """
        Test expansion of starred expression.
        """
        @arts_agenda
        def agenda(ws):
            """
            This agenda uses a starred expression.
            """
            ws.IndexSet(*[ws.stokes_dim, 42])

        self.ws.stokes_dim = 0
        agenda.execute(self.ws)
        assert self.ws.stokes_dim.value == 42

    def test_double_starred(self):
        """
        Test expansion of starred expression.
        """
        @arts_agenda
        def agenda(ws):
            """
            This agenda uses a starred expression.
            """
            ws.IndexSet(**{"out" : ws.stokes_dim,
                           "value" : 42})

        self.ws.stokes_dim = 0
        agenda.execute(self.ws)
        assert self.ws.stokes_dim.value == 42

    def test_exception(self):
        """
        Ensure that exception is thrown when a agenda
        variable is set to an invalid value.
        """
        @arts_agenda(allow_callbacks=True)
        def abs_xsec_agenda(ws):
              pass
        self.ws = pyarts.workspace.Workspace()
        with pytest.raises(Exception):
              self.ws.abs_xsec_agenda = abs_xsec_agenda
Beispiel #12
0
    def __init__(self,
                 ws=None,
                 threads=None,
                 nstreams=4,
                 scale_vmr=True,
                 verbosity=0):
        """Initialize a wrapper for an ARTS workspace.

        Parameters:
            ws (pyarts.workspace.Workspace): An ARTS workspace.
            threads (int): Number of threads to use.
                Default is all available threads.
            nstreams (int): Number of viewing angles to base the radiative
                flux calculation on.
            scale_vmr (bool): Control whether dry volume mixing ratios are
                scaled with the water-vapor concentration (default is `False.`)
            verbosity (int): Control the ARTS verbosity from 0 (quiet) to 2.
        """
        from pyarts.workspace import Workspace, arts_agenda

        self.nstreams = nstreams
        self.scale_vmr = scale_vmr

        if ws is None:
            self.ws = Workspace(verbosity=verbosity)

        self.ws.execute_controlfile("general/general.arts")
        self.ws.execute_controlfile("general/continua.arts")
        self.ws.execute_controlfile("general/agendas.arts")
        self.ws.execute_controlfile("general/planet_earth.arts")

        # Agenda settings
        self.ws.Copy(self.ws.abs_xsec_agenda, self.ws.abs_xsec_agenda__noCIA)
        self.ws.Copy(self.ws.iy_main_agenda, self.ws.iy_main_agenda__Emission)
        self.ws.Copy(self.ws.iy_space_agenda,
                     self.ws.iy_space_agenda__CosmicBackground)
        self.ws.Copy(self.ws.iy_surface_agenda,
                     self.ws.iy_surface_agenda__UseSurfaceRtprop)
        self.ws.Copy(
            self.ws.propmat_clearsky_agenda,
            self.ws.propmat_clearsky_agenda__LookUpTable,
        )
        self.ws.Copy(self.ws.ppath_agenda,
                     self.ws.ppath_agenda__FollowSensorLosPath)
        self.ws.Copy(self.ws.ppath_step_agenda,
                     self.ws.ppath_step_agenda__GeometricPath)

        @arts_agenda
        def p_eq_agenda(workspace):
            workspace.water_p_eq_fieldMK05()

        self.ws.Copy(self.ws.water_p_eq_agenda, p_eq_agenda)

        @arts_agenda
        def cloudbox_agenda(workspace):
            workspace.iyInterpCloudboxField()

        self.ws.Copy(self.ws.iy_cloudbox_agenda, cloudbox_agenda)

        # Number of Stokes components to be computed
        self.ws.IndexSet(self.ws.stokes_dim, 1)

        self.ws.jacobianOff()  # No jacobian calculation
        self.ws.cloudboxOff()  # Clearsky = No scattering

        # Set Absorption Species
        self.ws.abs_speciesSet(species=[
            "O2, O2-CIAfunCKDMT100",
            "H2O, H2O-SelfContCKDMT252, H2O-ForeignContCKDMT252",
            "O3",
            "CO2, CO2-CKDMT252",
            "N2, N2-CIAfunCKDMT252, N2-CIArotCKDMT252",
            "N2O",
            "CH4",
            "CO",
        ])

        # Surface handling
        self.ws.VectorSetConstant(self.ws.surface_scalar_reflectivity, 1, 0.0)
        self.ws.Copy(
            self.ws.surface_rtprop_agenda,
            self.ws.
            surface_rtprop_agenda__Specular_NoPol_ReflFix_SurfTFromt_surface,
        )

        # Read lookup table
        abs_lookup = os.getenv("KONRAD_LOOKUP_TABLE",
                               join(dirname(__file__), "data/abs_lookup.xml"))

        if not isfile(abs_lookup):
            raise FileNotFoundError(
                "Could not find ARTS absorption lookup table.\n"
                "To perform ARTS calculations you have to download the lookup "
                "table at:\n\n    https://doi.org/10.5281/zenodo.3885410\n\n"
                "Afterwards, use the following environment variable to tell "
                "konrad where to find it:\n\n"
                "    $ export KONRAD_LOOKUP_TABLE='/path/to/abs_lookup.xml'")

        self.ws.ReadXML(self.ws.abs_lookup, abs_lookup)
        self.ws.f_gridFromGasAbsLookup()
        self.ws.abs_lookupAdapt()

        # Sensor settings
        self.ws.sensorOff()  # No sensor properties

        # Atmosphere
        self.ws.AtmosphereSet1D()

        # Set number of OMP threads
        if threads is not None:
            self.ws.SetNumberOfThreads(threads)
Beispiel #13
0
from pyarts.workspace import Workspace
from pyarts.classes.Vector import Vector
from pyarts.classes.Matrix import Matrix
from pyarts.classes.MCAntenna import MCAntenna
from pyarts.classes import from_workspace

ws = Workspace()

mca = MCAntenna()

mca.type = 1
mca.type = 2
mca.type = 3

mca.sigma_aa = 4.5
mca.sigma_za = 4.5

mca.aa_grid = Vector([1, 2, 3, 4])
mca.za_grid = Vector([1, 2, 3, 4, 5])
mca.g_lookup = Matrix([[5, 6, 7, 8], [5, 6, 7, 8], [5, 6, 7, 8], [5, 6, 7, 8],
                       [5, 6, 7, 8]])

mca2 = from_workspace(ws.mc_antenna)
mca2.set(mca)

assert mca2 == mca

# mca3 = MCAntenna()
# mca.savexml("tmp.mca.xml", "binary")
# mca3.readxml("tmp.mca.xml")
# assert mca3 == mca
Beispiel #14
0
        ws.atmgeom_checkedCalc()
        ws.cloudbox_checkedCalc()
        ws.sensor_checkedCalc()
        ws.yCalc()

    ws.Copy(ws.ybatch_calc_agenda, ybatch_calc_agenda)
    ws.IndexSet(ws.ybatch_start, 0)
    ws.IndexSet(ws.ybatch_n, 1)  # Amount of atmospheres
    ws.ybatchCalc()  # conduct the forward simulation
    return ws


# test for ybatch
def test_ybatch(ws):
    ybatch_ref = np.array([256.9629541])
    assert np.allclose(ws.ybatch.value[0], ybatch_ref)


# test for ybatch_jacobians
def test_ybatch_jacobians(ws):
    ybatch_jacobians_ref = np.array([[3.38652849e-6]])
    assert np.allclose(ws.ybatch_jacobians.value[0], ybatch_jacobians_ref, atol=1e-12)


if __name__ == '__main__':
    ws = Workspace(verbosity=2)
    ws = setup_testcase(ws)
    test_ybatch(ws)
    test_ybatch_jacobians(ws)
    print('SurfaceBlackbody tests passed.')
Beispiel #15
0
import os

from pyarts.workspace import Workspace
from pyarts.classes.ScatteringMetaData import ScatteringMetaData
from pyarts.classes.SingleScatteringData import SingleScatteringData
from pyarts.classes import from_workspace


# Get a workspace
ws = Workspace()
datapath = "../../arts-xml-data/" if not os.getenv("ARTS_XML_DATA_DIR") else os.getenv("ARTS_XML_DATA_DIR")
fn1 = os.path.join(datapath, 'scattering/H2O_ice/MieSphere_R1.00000e+00um.meta.xml')
fn2 = os.path.join(datapath, 'scattering/H2O_ice/MieSphere_R1.00000e+00um.xml')

smd1 = ScatteringMetaData()
smd1.readxml(fn1)
smd2 = from_workspace(ws.scat_meta_single)
ws.ReadXML(ws.scat_meta_single, fn1)
smd3 = ScatteringMetaData()
smd3.set(smd2)

assert smd1 == smd2
assert smd1 == smd3

ssd1 = SingleScatteringData()
ssd1.readxml(fn2)
ssd2 = from_workspace(ws.scat_data_single)
ws.ReadXML(ws.scat_data_single, fn2)
ssd3 = SingleScatteringData()
ssd3.set(ssd2)
Beispiel #16
0
from pyarts.workspace import Workspace
from pyarts.classes.QuantumIdentifier import QuantumIdentifier
from pyarts.classes.RetrievalQuantity import RetrievalQuantity, ArrayOfRetrievalQuantity
from pyarts.classes.SpeciesTag import SpeciesTag
from pyarts.classes.Vector import ArrayOfVector
from pyarts.classes import from_workspace

# Get a workspace
ws = Workspace()
ws.jacobianInit()
ws.atmosphere_dim = 3
p = from_workspace(ws.p_grid)
lat = from_workspace(ws.lat_grid)
lon = from_workspace(ws.lon_grid)
p.data = [3, 2, 1]
lat.data = [1, 2, 3, 4]
lon.data = [1, 2, 3, 4, 5]
ws.jacobianAddTemperature(g1=p.data, g2=lat.data, g3=lon.data)

arq = from_workspace(ws.jacobian_quantities)
rq = RetrievalQuantity()
rq.maintag = ""
rq.subtag = "HSE on"
rq.subsubtag = ""
rq.mode = ""
rq.analytical = 1
rq.target.type = "Atm"
rq.target.subtype = "Temperature"
rq.target.perturbation = 0.1
rq.grids = ArrayOfVector([p, lat, lon])
Beispiel #17
0
from math import isclose

from pyarts.workspace import Workspace
from pyarts.classes.Time import Time
from pyarts.classes import from_workspace

ws = Workspace()
ws.create_variable("Time", "start")
ws.create_variable("Time", "end")
ws.create_variable("Time", "time")
ws.create_variable("Numeric", "dt")
start_time = from_workspace(ws.start)
end_time = from_workspace(ws.end)
cur_time = from_workspace(ws.time)
dt = from_workspace(ws.dt)

# Test Now and Sleep
ws.timeNow(ws.start)
ws.Sleep(1)
ws.timeNow(ws.end)
ws.Duration(ws.dt, ws.start, ws.end)
assert dt >= 1, \
    f"Slept for one second but duration was less: {float(dt):.3f} s"

# Test SleepUntil
ws.timeNow(ws.start)
end_time.sec = start_time.sec + 1
ws.timeSleep(ws.end)
ws.timeNow(ws.time)
duration = cur_time.sec - start_time.sec
assert duration >= 1, \
Beispiel #18
0
class TestMethods:
    """
    Tests the calling of ARTS workspace methods.
    """
    def setup_method(self):
        """
        This ensures a new Workspace for every test.
        """
        self.ws = Workspace(verbosity=0)
        self.setup_workspace()

    def setup_workspace(self):
        self.ws.execute_controlfile(
            "artscomponents/clearsky/TestClearSky.arts")

    def test_mixed_arguments(self):
        """
        Check that this raises a syntax error.
        """
        ws = self.ws
        with pytest.raises(SyntaxError):
            ws.yCalc(ws.yf, y_f=ws.y_f)

    def test_unexpected_argument(self):
        """
        Providing a named argument with a name that is not actually an argument
        of the WSM should raise an error.
        """
        ws = self.ws
        with pytest.raises(Exception):
            ws.yCalc(nonsense=ws.y_f)

    def test_override_output(self):
        """
        Test overriding of output parameters in the two possible
        ways.
        """
        ws = self.ws
        y_ref = np.copy(ws.y.value)

        ws.yf = np.zeros(y_ref.size)
        ws.yCalc(ws.yf)
        assert (np.allclose(ws.yf.value, y_ref))

        ws.yf = np.zeros(y_ref.size)
        ws.yCalc(y=ws.yf)
        assert (np.allclose(ws.yf.value, y_ref))

    def test_override_input(self):
        """
        Test overriding of input parameters in the two possible ways.

        atmgeom_checked WSV is set to zero so that both calculations
        should fail if input is not overridden.
        """
        ws = self.ws
        ws.atmgeom_checked = 0

        ws.rte_pos = np.array([600e3, 0, 0])
        ws.rte_pos2 = np.array([600e3, 0])
        ws.rte_los = np.array([180.0, 0])

        ws.ppathCalc(ws.ppath, ws.ppath_agenda, ws.ppath_lmax,
                     ws.ppath_lraytrace, 1)
        ws.ppathCalc(atmgeom_checked=1)

    def test_generic_input(self):
        """
        Test overriding of generic input in the two possible ways.
        """
        ws = self.ws
        species = ([
            "H2O-SelfContStandardType, H2O-ForeignContStandardType, H2O",
            "N2-SelfContStandardType", "O3"
        ])

        ws.ArrayOfArrayOfSpeciesTagCreate("abs_species_2")
        ws.abs_speciesSet(ws.abs_species_2, ws.abs_xsec_agenda_checked,
                          ws.propmat_clearsky_agenda_checked, species)
        ws.ArrayOfArrayOfSpeciesTagCreate("abs_species_3")
        ws.abs_speciesSet(abs_species=ws.abs_species_3, species=species)
        assert (ws.abs_species_2.value == ws.abs_species_3.value)

    def test_generic_output(self):
        """
        Test overriding of generic input in the two possible ways.
        """
        ws = self.ws

        tempfile = NamedTemporaryFile()

        mat = np.ones((2, 2))
        ws.sensor_los = np.ones((2, 2))
        ws.WriteXML("ascii", ws.sensor_los, tempfile.name)

        ws.sensor_los = np.zeros((2, 2))
        ws.ReadXML(ws.sensor_los, tempfile.name)
        assert (np.allclose(mat, ws.sensor_los.value))

        ws.sensor_los = np.zeros((2, 2))
        ws.ReadXML(out=ws.sensor_los, filename=tempfile.name)
        assert (np.allclose(mat, ws.sensor_los.value))

    def test_supergeneric_overload_resolution(self):
        """
        Test resolution of supergeneric methods.
        """
        self.ws.ArrayOfIndexCreate("array_of_index")
        self.ws.ArrayOfArrayOfIndexCreate("array_of_array_of_index")
        self.ws.array_of_index = [1, 2, 3]
        self.ws.Append(self.ws.array_of_array_of_index, self.ws.array_of_index)
        self.ws.Append(self.ws.array_of_array_of_index, self.ws.array_of_index)

    def test_supergeneric_overload_failure(self):
        """
        Test expected failure of supergeneric overload resolution.
        """
        with pytest.raises(Exception):
            self.ws.NumericCreate("numeric_wsv")
            self.ws.StringCreate("string_wsv")
            self.ws.Copy(self.ws.string_wsv, self.ws.numeric_wsv)

    def test_wsm_error(self):
        """
        Test error handling from ARTS WSMs.
        """
        with pytest.raises(Exception):
            ws.atmgeom_checked = 0
            self.ws.yCalc()
Beispiel #19
0
from pyarts.workspace import Workspace
from pyarts.classes.SpeciesTag import SpeciesTag, ArrayOfArrayOfSpeciesTag
from pyarts.classes import from_workspace

# Get a workspace
ws = Workspace()

aast = from_workspace(ws.abs_species)
st = SpeciesTag("H2O-161")
ws.abs_speciesSet(species=["H2O-161"])
aast.size = 2
aast[1].size = 1
aast[1][0].set(aast[0][0])

assert st == aast[0][0]
assert st == aast[1][0]

aast.savexml("tmp.aast.xml", "binary")
aast2 = ArrayOfArrayOfSpeciesTag()
aast2.readxml("tmp.aast.xml")
assert aast == aast2
Beispiel #20
0
from pyarts.workspace import Workspace

ws = Workspace()

ws.StringCreate("mystring")
ws.StringSet(ws.mystring, "Hello World!")
ws.Print(ws.mystring, 0)
Beispiel #21
0
class TestWorkspace:
    def setup_method(self):
        """This ensures a new Workspace for every test."""
        self.dir = os.path.dirname(os.path.realpath(__file__))
        self.ws  = Workspace()
        self.setup_workspace()

    def setup_workspace(self):
        ws = self.ws
        ws.atmosphere_dim = 1
        ws.p_grid = np.linspace(1e5, 1e3, 21)
        ws.Touch(ws.lat_grid)
        ws.Touch(ws.lon_grid)

        ws.f_grid = 183.0e9 * np.ones(1)
        ws.stokes_dim = 1

        ws.sensor_los = 180.0 * np.ones((1, 1))
        ws.sensor_pos = 830e3 * np.ones((1, 1))
        ws.sensorOff()

    def test_execute_controlfile(self):

        dir = os.path.dirname(os.path.realpath(__file__))
        test_dir = os.path.join(dir, "test_files")
        self.ws.WriteXML("ascii", np.array([1.0]),
                         os.path.join(test_dir, "vector.xml"))
        os.chdir(test_dir)
        self.ws.execute_controlfile("controlfile.arts")

        os.remove(os.path.join(test_dir, "vector.xml"))


    def test_execute_controlfile(self):

        dir = os.path.dirname(os.path.realpath(__file__))
        test_dir = os.path.join(dir, "test_files")
        self.ws.WriteXML("ascii", np.array([1.0]),
                         os.path.join(test_dir, "vector.xml"))
        os.chdir(test_dir)

        agenda = self.ws.execute_controlfile("controlfile.arts")
        self.ws.foo = "not bar"

        @arts_agenda
        def execute(ws):
            ws.FlagOff(ws.jacobian_do)
            ws.StringSet(ws.foo, "still not bar")
            INCLUDE("controlfile.arts")
            INCLUDE(agenda)

        self.ws.execute_agenda(execute)

        assert self.ws.foo.value == "bar"
        os.remove(os.path.join(test_dir, "vector.xml"))

    def test_wsv_setattr(self):
        wsv = self.ws.atmosphere_dim
        wsv.value = 12
        assert self.ws.atmosphere_dim.value == 12


    def test_callbacks(self):

        @arts_agenda
        def agenda(ws):
            """
            This agenda sets a workspace variable in a very
            obscure way.
            """

            class Foo:
                def __init__(self, ws):
                    self.ws = ws

                def ooo(self):
                    self.ws.IndexSet(ws.stokes_dim, 42)

            foo = Foo(ws)
            ws.IndexSet(ws.stokes_dim, 21)
            foo.ooo()

        agenda.execute(self.ws)

        assert self.ws.stokes_dim.value == 42

    def test_contiguous_arrays(self):
        x = np.linspace(0, 1, 256)

        xf = np.asarray(x, order='F')
        self.ws.f_grid = xf
        assert np.array_equal(self.ws.f_grid.value, xf)

        self.ws.f_grid = x[::2]
        assert np.array_equal(self.ws.f_grid.value, x[::2])

        self.ws.f_grid = np.ascontiguousarray(x[::2])
        assert np.array_equal(self.ws.f_grid.value, x[::2])

    def test_name_collision(self):
        self.ws.VectorSetConstant(self.ws.f_grid, 10, 1.)
        self.ws.VectorCreate("np")
        f_grid = self.ws.f_grid.value
        assert np.all(np.isclose(f_grid, np.ones(10)))
Beispiel #22
0
from pyarts.workspace import Workspace
from pyarts.classes.Ppath import Ppath
from pyarts.classes import from_workspace

# Get a workspace
ws = Workspace()
ws.atmosphere_dim = 1
ws.cloudbox_on = 0
ws.ppath_inside_cloudbox_do = 0
cloudbox_limits = from_workspace(ws.cloudbox_limits)
z_field = from_workspace(ws.z_field)
z_field.data = [0, 1, 2, 3]
z_field.data = z_field.data.reshape(4, 1, 1)
z_surface = from_workspace(ws.z_surface)
z_surface.data = [0]
rte_pos = from_workspace(ws.rte_pos)
rte_pos.data = [4]
rte_los = from_workspace(ws.rte_los)
rte_los.data = [91]
ws.ppath_lmax = 0.1
ws.ppathPlaneParallel()

# Get the path
path = from_workspace(ws.ppath)
path2 = Ppath()
path2.set(path)

assert isinstance(path, Ppath), "Bad read"
assert path, "Bad read"
assert path2 == path
Beispiel #23
0
class _ARTS:
    def __init__(self,
                 ws=None,
                 threads=None,
                 nstreams=4,
                 scale_vmr=True,
                 verbosity=0):
        """Initialize a wrapper for an ARTS workspace.

        Parameters:
            ws (pyarts.workspace.Workspace): An ARTS workspace.
            threads (int): Number of threads to use.
                Default is all available threads.
            nstreams (int): Number of viewing angles to base the radiative
                flux calculation on.
            scale_vmr (bool): Control whether dry volume mixing ratios are
                scaled with the water-vapor concentration (default is `False.`)
            verbosity (int): Control the ARTS verbosity from 0 (quiet) to 2.
        """
        from pyarts.workspace import Workspace, arts_agenda

        self.nstreams = nstreams
        self.scale_vmr = scale_vmr

        if ws is None:
            self.ws = Workspace(verbosity=verbosity)

        self.ws.execute_controlfile("general/general.arts")
        self.ws.execute_controlfile("general/continua.arts")
        self.ws.execute_controlfile("general/agendas.arts")
        self.ws.execute_controlfile("general/planet_earth.arts")

        # Agenda settings
        self.ws.Copy(self.ws.abs_xsec_agenda, self.ws.abs_xsec_agenda__noCIA)
        self.ws.Copy(self.ws.iy_main_agenda, self.ws.iy_main_agenda__Emission)
        self.ws.Copy(self.ws.iy_space_agenda,
                     self.ws.iy_space_agenda__CosmicBackground)
        self.ws.Copy(self.ws.iy_surface_agenda,
                     self.ws.iy_surface_agenda__UseSurfaceRtprop)
        self.ws.Copy(
            self.ws.propmat_clearsky_agenda,
            self.ws.propmat_clearsky_agenda__LookUpTable,
        )
        self.ws.Copy(self.ws.ppath_agenda,
                     self.ws.ppath_agenda__FollowSensorLosPath)
        self.ws.Copy(self.ws.ppath_step_agenda,
                     self.ws.ppath_step_agenda__GeometricPath)

        @arts_agenda
        def p_eq_agenda(workspace):
            workspace.water_p_eq_fieldMK05()

        self.ws.Copy(self.ws.water_p_eq_agenda, p_eq_agenda)

        @arts_agenda
        def cloudbox_agenda(workspace):
            workspace.iyInterpCloudboxField()

        self.ws.Copy(self.ws.iy_cloudbox_agenda, cloudbox_agenda)

        # Number of Stokes components to be computed
        self.ws.IndexSet(self.ws.stokes_dim, 1)

        self.ws.jacobianOff()  # No jacobian calculation
        self.ws.cloudboxOff()  # Clearsky = No scattering

        # Set Absorption Species
        self.ws.abs_speciesSet(species=[
            "O2, O2-CIAfunCKDMT100",
            "H2O, H2O-SelfContCKDMT252, H2O-ForeignContCKDMT252",
            "O3",
            "CO2, CO2-CKDMT252",
            "N2, N2-CIAfunCKDMT252, N2-CIArotCKDMT252",
            "N2O",
            "CH4",
            "CO",
        ])

        # Surface handling
        self.ws.VectorSetConstant(self.ws.surface_scalar_reflectivity, 1, 0.0)
        self.ws.Copy(
            self.ws.surface_rtprop_agenda,
            self.ws.
            surface_rtprop_agenda__Specular_NoPol_ReflFix_SurfTFromt_surface,
        )

        # Read lookup table
        abs_lookup = os.getenv("KONRAD_LOOKUP_TABLE",
                               join(dirname(__file__), "data/abs_lookup.xml"))

        if not isfile(abs_lookup):
            raise FileNotFoundError(
                "Could not find ARTS absorption lookup table.\n"
                "To perform ARTS calculations you have to download the lookup "
                "table at:\n\n    https://doi.org/10.5281/zenodo.3885410\n\n"
                "Afterwards, use the following environment variable to tell "
                "konrad where to find it:\n\n"
                "    $ export KONRAD_LOOKUP_TABLE='/path/to/abs_lookup.xml'")

        self.ws.ReadXML(self.ws.abs_lookup, abs_lookup)
        self.ws.f_gridFromGasAbsLookup()
        self.ws.abs_lookupAdapt()

        # Sensor settings
        self.ws.sensorOff()  # No sensor properties

        # Atmosphere
        self.ws.AtmosphereSet1D()

        # Set number of OMP threads
        if threads is not None:
            self.ws.SetNumberOfThreads(threads)

    def calc_lookup_table(self, filename=None, fnum=2**15, wavenumber=None):
        """Calculate an absorption lookup table.

        The lookup table is constructed to cover surface temperatures
        between 200 and 400 K, and water vapor mixing ratio up to 40%.

        The frequency grid covers the whole outgoing longwave spectrum
        from 10 to 3,250 cm^-1.

        References:
            An absorption lookup table can be found at
                https://doi.org/10.5281/zenodo.3885410

        Parameters:
            filename (str): (Optional) path to an ARTS XML file
                to store the lookup table.
            fnum (int): Number of frequencies in frequency grid.
                Ignored if `wavenumber` is set.
            wavenumber (ndarray): Wavenumber grid [m-1].
        """
        # Create a frequency grid
        if wavenumber is None:
            wavenumber = np.linspace(10e2, 3_250e2, fnum)
        self.ws.f_grid = ty.physics.wavenumber2frequency(wavenumber)

        # Read line catagloge and create absorption lines.
        self.ws.ReadSplitARTSCAT(
            abs_lines=self.ws.abs_lines,
            abs_species=self.ws.abs_species,
            basename="hitran_split_artscat5/",
            fmin=0.0,
            fmax=1e99,
            globalquantumnumbers="",
            localquantumnumbers="",
            ignore_missing=0,
        )

        # Set line shape and cut off.
        self.ws.abs_linesSetLineShapeType(self.ws.abs_lines, "VP")
        self.ws.abs_linesSetNormalization(self.ws.abs_lines, "VVH")
        self.ws.abs_linesSetCutoff(self.ws.abs_lines, "ByLine", 750e9)

        self.ws.abs_lines_per_speciesCreateFromLines()
        self.ws.abs_lines_per_speciesCompact()

        # Create a standard atmosphere
        p_grid = get_quadratic_pgrid(1_200e2, 0.5, 80)

        atmosphere = Atmosphere(p_grid)
        atmosphere["T"][
            -1, :] = 300.0 + 5.0 * np.log(atmosphere["plev"] / 1000e2)
        atmosphere.tracegases_rcemip()
        atmosphere["O2"][:] = 0.2095
        atmosphere["CO2"][:] = 1.5 * 348e-6

        h2o = 0.01 * (p_grid / 1000e2)**0.2
        atmosphere["H2O"][:] = h2o[:-1]

        # Convert the konrad atmosphere into an ARTS atm_fields_compact.
        atm_fields_compact = atmosphere.to_atm_fields_compact()
        self.ws.atm_fields_compact = atm_fields_compact

        self.ws.atm_fields_compactAddConstant(
            atm_fields_compact=self.ws.atm_fields_compact,
            name="abs_species-N2",
            value=0.7808,
            condensibles=["abs_species-H2O"],
        )

        # Setup the lookup table calculation
        self.ws.AtmFieldsAndParticleBulkPropFieldFromCompact()
        self.ws.vmr_field.value = self.ws.vmr_field.value.clip(min=0.0)
        self.ws.atmfields_checkedCalc()
        self.ws.abs_lookupSetup(p_step=1.0)  # Do not refine p_grid
        self.ws.abs_t_pert = np.arange(-160, 61, 20)

        nls_idx = [
            i for i, tag in enumerate(self.ws.abs_species.value)
            if "H2O" in tag[0]
        ]
        self.ws.abs_speciesSet(
            abs_species=self.ws.abs_nls,
            species=[", ".join(self.ws.abs_species.value[nls_idx[0]])],
        )

        self.ws.abs_nls_pert = np.array(
            [10**x for x in [-9, -7, -5, -3, -1, 0, 0.5, 1, 1.5, 2]])

        # Run checks
        self.ws.abs_xsec_agenda_checkedCalc()
        self.ws.lbl_checkedCalc()

        # Calculate actual lookup table.
        self.ws.abs_lookupCalc()

        if filename is not None:
            self.ws.WriteXML("binary", self.ws.abs_lookup, filename)

    def set_atmospheric_state(self, atmosphere, t_surface):
        """Set and check the atmospheric fields."""
        import pyarts

        atm_fields_compact = atmosphere.to_atm_fields_compact()

        # Scale dry-air VMRs with H2O and CO2 content.
        if self.scale_vmr:
            variable_vmrs = (atm_fields_compact.get("abs_species-H2O")[0] +
                             atm_fields_compact.get("abs_species-CO2")[0])
        else:
            t3_shape = atm_fields_compact.get("abs_species-H2O")[0].shape
            variable_vmrs = np.zeros(t3_shape)

        for species in atm_fields_compact.grids[0]:
            if (species.startswith("abs_species-") and "H2O" not in species
                    and "CO2" not in species):
                atm_fields_compact.scale(species, 1 - variable_vmrs)

        # Compute the N2 VMR as a residual of the full atmosphere composition.
        n2 = pyarts.types.GriddedField3(
            grids=atm_fields_compact.grids[1:],
            data=0.7808 * (1 - variable_vmrs),
        )

        self.ws.atm_fields_compact = atm_fields_compact
        self.ws.atm_fields_compactAddSpecies(
            atm_fields_compact=self.ws.atm_fields_compact,
            name="abs_species-N2",
            value=n2,
        )
        self.ws.AtmFieldsAndParticleBulkPropFieldFromCompact()
        self.ws.vmr_field = self.ws.vmr_field.value.clip(min=0)

        # Surface & TOA
        # Add pressure layers to the surface and top-of-the-atmosphere to
        # ensure consistent atmosphere boundaries between ARTS and RRTMG.
        self.ws.t_surface = np.array([[t_surface]])
        self.ws.z_surface = np.array([[0.0]])
        self.ws.z_field.value[0, 0, 0] = 0.0

        # Perform configuration and atmosphere checks
        self.ws.atmfields_checkedCalc()
        self.ws.propmat_clearsky_agenda_checkedCalc()
        self.ws.atmgeom_checkedCalc()
        self.ws.cloudbox_checkedCalc()

    def calc_spectral_irradiance_field(self, atmosphere, t_surface):
        """Calculate the spectral irradiance field."""
        self.set_atmospheric_state(atmosphere, t_surface)

        # get the zenith angle grid and the integrations weights
        self.ws.AngularGridsSetFluxCalc(N_za_grid=self.nstreams,
                                        N_aa_grid=1,
                                        za_grid_type="double_gauss")

        # calculate intensity field
        self.ws.Tensor3Create("trans_field")
        self.ws.spectral_radiance_fieldClearskyPlaneParallel(
            trans_field=self.ws.trans_field,
            use_parallel_za=0,
        )
        self.ws.spectral_irradiance_fieldFromSpectralRadianceField()

        return (
            self.ws.f_grid.value.copy(),
            self.ws.p_grid.value.copy(),
            self.ws.spectral_irradiance_field.value.copy(),
            self.ws.trans_field.value[:, 1:, 0].copy().prod(axis=1),
        )

    def calc_optical_thickness(self, atmosphere, t_surface):
        """Calculate the spectral irradiance field."""
        self.set_atmospheric_state(atmosphere, t_surface)

        self.ws.propmat_clearsky_fieldCalc()

        tau = np.trapz(
            y=self.ws.propmat_clearsky_field.value[:, :, 0, 0, :, 0, 0],
            x=self.ws.z_field.value[:, 0, 0],
            axis=-1,
        )

        return self.ws.f_grid.value.copy(), tau

    @staticmethod
    def integrate_spectral_irradiance(frequency, irradiance):
        """Integrate the spectral irradiance field over the frequency.

        Parameters:
            frequency (ndarray): Frequency [Hz].
            irradiance (ndarray): Spectral irradiance [W m^-2 / Hz].

        Returns:
            ndarray, ndarray: Downward flux, upward, flux [W m^-2]
        """
        F = np.trapz(irradiance, frequency, axis=0)[:, 0, 0, :]

        # Fluxes
        lw_down = -F[:, 0]
        lw_up = F[:, 1]

        return lw_down, lw_up

    def calc_spectral_olr(self, atmosphere, surface):
        """Calculate the outgoing longwave radiation as function of wavenumber.

        Parameters:
            atmosphere (konrad.atmosphere.Atmosphere): Atmosphere model.
            surface (konrad.surface.Surface): Surface model.

        Returns:
           ndarray: Outgoing longwave radiation [W m^-2 / cm^-1]
        """
        f, _, irradiance_field, _ = self.calc_spectral_irradiance_field(
            atmosphere=atmosphere, t_surface=surface["temperature"][0])
        return f, irradiance_field[:, -1, 0, 0, 1]
Beispiel #24
0
"""
Surface
=======

"""
import numpy as np
from pyarts.workspace import Workspace, arts_agenda

ws = Workspace()
ws.NumericCreate("surface_temperature")
ws.NumericCreate("surface_salinity")
ws.NumericCreate("surface_windspeed")

from artssat.atmosphere.surface.surface import Tessem, Telsem, CombinedSurface
Beispiel #25
0
"""
The surface sub-module provides implementations of the different surface models
that are available in ARTS.
"""
from abc import abstractmethod, abstractproperty
import numpy as np
import os

from artssat.arts_object import ArtsObject, arts_property, Dimension
from pyarts.workspace import Workspace, arts_agenda
from pyarts.workspace.variables import (WorkspaceVariable, workspace_variables)
wsv = workspace_variables

ws = Workspace(verbosity = 0)


class Surface:
    """
    Abstract base class for surfaces.

    This class defines the general interfaces for surface models in artssat.
    """

    @abstractproperty
    def required_data(self):
        pass

    @abstractmethod
    def setup(self, ws):
        """
        Setup the surface model in the given workspace.
Beispiel #26
0
class ActiveSensor(Sensor):
    """
    Specialization of the abstract :code:`Sensor` class that implements
    active sensors (Radar).

    """
    ws = Workspace()
    extinction_scaling = ws.create_variable("Numeric", "extinction_scaling")
    private_wsvs = Sensor.private_wsvs + [
        "range_bins", "instrument_pol_array", "instrument_pol",
        "iy_transmitter_agenda", "extinction_scaling"
    ]

    ############################################################################
    # ARTS properties
    ############################################################################

    @arts_property("Numeric", wsv="extinction_scaling")
    def extinction_scaling(self):
        return 1.0

    @arts_property("Numeric")
    def k2(self):
        return -1.0

    @arts_property("Numeric")
    def y_min(self):
        return -35.0

    @arts_property("Vector", shape=(dim.Joker, ), wsv=wsv["range_bins"])
    def range_bins(self):
        return []

    @arts_property("ArrayOfIndex", wsv=wsv["instrument_pol"])
    def instrument_pol(self):
        return [1]

    @arts_property("ArrayOfArrayOfIndex", wsv=wsv["instrument_pol_array"])
    def instrument_pol_array(self):
        return [[1]]

    @property
    def y_vector_length(self):
        return (self.range_bins.size -
                1) * self.f_grid.size * self.stokes_dimension

    def __init__(self, name, f_grid, stokes_dimension, range_bins=None):
        super().__init__(name, f_grid, stokes_dimension=stokes_dimension)
        self.iy_unit = "dBZe"

        if not range_bins is None:
            self.range_bins = range_bins

    #
    # Agendas
    #

    @property
    def iy_transmitter_agenda(self):
        """
        The :code:`iy_transmitter_agenda` which is required for active
        sensors. Input arguments of :code:`iy_transmitter_agenda` are
        replaced by the private workspace variables of the sensor.

        Returns:

            The iy_transmitter_agenda for the active sensor.

        """
        kwargs = self.get_wsm_kwargs(wsm["iy_transmitterSinglePol"])

        @arts_agenda
        def iy_transmitter_agenda(ws):
            ws.Ignore(ws.rtp_pos)
            ws.Ignore(ws.rtp_los)
            ws.Ignore(ws.f_grid)
            ws.iy_transmitterSinglePol(**kwargs)

        return iy_transmitter_agenda

    def make_iy_main_agenda(self, scattering=False):
        """
        The :code: `iy_main_agenda` for active sensor. Currently uses
        the single scattering radar module, but might be extended
        at some point.
        """

        kwargs = self.get_wsm_kwargs(wsm["iyActiveSingleScat2"])

        @arts_agenda
        def iy_main_agenda(ws):
            ws.Ignore(ws.iy_id)
            ws.Ignore(ws.nlte_field)
            ws.Ignore(ws.rte_pos2)
            ws.Ignore(ws.iy_unit)
            ws.Ignore(ws.iy_aux_vars)
            ws.FlagOff(ws.cloudbox_on)
            ws.ppathCalc()
            ws.FlagOn(ws.cloudbox_on)
            ws.iyActiveSingleScat(
                **kwargs,
                pext_scaling=self._wsvs["extinction_scaling"],
                trans_in_jacobian=1)

        return iy_main_agenda

    #
    # Specialized setters
    #

    def iy_unit_setter(self, u):
        if not u in ["1", "Ze", "dBZe"]:
            raise Exception("Value of iy_unit for an active sensor must"
                            " be one of ['1', 'Ze', 'dBZe']")
        else:
            self._iy_unit.value = u
            self._iy_unit.fixed = True

    def iy_aux_vars_setter(self, v):
        if not type(v) == list:
            v = [v]
        if not all([
                u in [
                    "Radiative background", "Backsacttering", "Optical depth",
                    "Particle extinction"
                ] for u in v
        ]):
            raise Exception("Value of iy_aux_vars for an active sensor must"
                            " be a list consisting of the following strings: "
                            "['RadiativeBackground', 'Backscattering', "
                            "'Optical depth', Particle extinction'].")
        else:
            self._iy_aux_vars.value = v
            self._iy_aux_vars.fixed = False

    #
    # Preparation and y_calc factories.
    #

    def make_preparation_function(self):
        """
        Return the workspace preparation function, which prepares
        a workspace for simulating the signal recorded by the sensor.

        Returns:

            The function to prepare the workspace.

        """
        def preparations(ws):
            ws.IndexSet(ws.stokes_dim, self.stokes_dimension)
            #ws.Copy(ws.iy_transmitter_agenda,
            #        self._wsvs["iy_transmitter_agenda"])
            #ws.Copy(ws.iy_main_agenda,
            #        self._wsvs["_iy_main_agenda"])
            #ws.Copy(ws.instrument_pol, self._wsvs["instrument_pol"])
            #ws.IndexSet(self._wsvs["_stokes_dim"], self.stokes_dimension)
            #ws.IndexSet(ws.stokes_dim, self.stokes_dimension)

        return preparations

    def make_y_calc_function(self, append=False, scattering=False):
        """
        Returns y_calc function, which computes the radar signal
        on an accordingly prepared workspace. This function can
        be converted into an ARTS agenda and thus included in
        the other agendas using the INCLUDE statement.

        Returns:

            The function to compute the radar signal.
        """
        if append:
            raise Exception("ARTS doesn't support appending measurements from"
                            " active sensors.")

        kwargs = self.get_wsm_kwargs(wsm["yActive"])

        if self.y_min:
            y_min = self.y_min
        else:
            y_min = -np.inf

        def y_calc(ws):
            ws.yActive(dbze_min=y_min, k2=self.k2, **kwargs)

        return y_calc

    #
    # Setup
    #

    def setup(self, ws, scattering=True):
        super().setup(ws, scattering)
        self._wsvs["iy_transmitter_agenda"].value = self.iy_transmitter_agenda
Beispiel #27
0
from pyarts.workspace import Workspace
from pyarts.classes.EnergyLevelMap import EnergyLevelMap
from pyarts.classes import from_workspace

# Get a workspace
ws = Workspace()
datapath = "../"

elm1 = EnergyLevelMap()
elm1.readxml(datapath +
             "controlfiles/artscomponents/nlte/testdata/nlte_testdata.xml")
ws.ReadXML(
    ws.nlte_field,
    datapath + "controlfiles/artscomponents/nlte/testdata/nlte_testdata.xml")
elm2 = from_workspace(ws.nlte_field)

assert elm1, "Bad read"
assert elm1 == elm2, "Bad read"
assert elm1.data

elm3 = EnergyLevelMap()
elm3.set(elm1)

assert elm3 == elm2

elm4 = EnergyLevelMap()
elm1.savexml("tmp.elm.xml", "binary")
elm4.readxml("tmp.elm.xml")
assert elm4 == elm1
Beispiel #28
0
import os

from pyarts.workspace import Workspace
from pyarts.classes.CIARecord import CIARecord, ArrayOfCIARecord
from pyarts.classes import from_workspace

# Get a workspace
ws = Workspace()
datapath = "../../arts-xml-data/" if not os.getenv(
    "ARTS_XML_DATA_DIR") else os.getenv("ARTS_XML_DATA_DIR")
fn = os.path.join(datapath,
                  "spectroscopy/cia/borysow/Borysow_CIA_JUICE_SWI.xml")

acr1 = ArrayOfCIARecord()
assert not acr1, "Bad init"

acr1.readxml(fn)
ws.ReadXML(ws.abs_cia_data, fn)
acr2 = from_workspace(ws.abs_cia_data)

assert acr1, "Bad read"
assert acr1 == acr2, "Bad read"
assert isinstance(acr1[0], CIARecord), "Bad type"

acr3 = ArrayOfCIARecord()
acr3.set(acr1)
assert acr1 == acr3, "Bad read"

acr1.savexml("tmp.acr.xml", "binary")
acr3 = ArrayOfCIARecord()
acr3.readxml("tmp.acr.xml")