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 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 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
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
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)))
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
""" 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.
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 setup_method(self): """ This ensures a new Workspace for every test. """ self.ws = Workspace(verbosity = 0) self.setup_workspace()
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