Exemplo n.º 1
0
def setRttovProfiles(h5ProfileFileName, additionalItems=[]):
    nlevels = 101
    nprofiles = 6
    myProfiles = pyrttov.Profiles(nprofiles, nlevels)
    myProfiles.P, profileItems, myProfiles.GasUnits = readProfileItemsH5(
        h5ProfileFileName, additionalItems)
    for item in list(profileItems.keys()):
        exec("myProfiles.{} = profileItems['{}']".format(item, item))

    # View/Solar angles
    # satzen, satazi, sunzen, sunazi
    #nprofiles, nvar (4)
    myProfiles.Angles = 0.0 * np.zeros([nprofiles, 4])
    # set solar zenith angle below horizon +10 deg
    myProfiles.Angles[:, 2] = 100.0  #below horizon for solar

    # s2m surface 2m variables
    # surface : pressure, temperature, specific humidity, wind (u comp), wind (v comp), windfetch
    # nprofiles, nvar (6)
    s2m = []

    for i in list(range(nprofiles)):
        Ps = myProfiles.P[:, -1]
        Ts = myProfiles.T[:, -1]
        Qs = myProfiles.Q[:, -1]

        s2m.append([Ps[i], Ts[i], Qs[i], 0, 0., 10000.])
    myProfiles.S2m = np.asarray(s2m)

    #Skin variables
    #skin%t, skin%salinity, skin%snow_fraction, skin %foam_fraction, skin%fastem(1:5), skin%specularity
    #nprofiles, nvar (10)
    myProfiles.Skin = np.zeros([nprofiles, 10])
    myProfiles.Skin[:, 0] = 270.0
    myProfiles.Skin[:, 1] = 35.0

    #Surface Type info
    # surftype (land = 0, sea = 1, seacice =2), watertype (fresh = 0, ocean = 1)
    #nprofiles, nvar (2)
    myProfiles.SurfType = np.ones([nprofiles, 2])

    #Surface geometry
    # latitude, longitude, elevation (lat/lon used in refractivity and emis/BRDF atlases, elevation used for refractivity).
    #nprofiles, nvar (3)
    myProfiles.SurfGeom = np.zeros([nprofiles, 3])

    #Date/times
    #nprofiles, nvar(6)
    datetimes = []
    for i in list(range(nprofiles)):
        datetimes.append([2015, 8, 1, 0, 0, 0])
    myProfiles.DateTimes = np.asarray(datetimes)
    return myProfiles
Exemplo n.º 2
0
def make_profile(n_profiles, n_levels, ice_scheme, ice_paramer, pres, temp,
                 spechum, ozone, sat_angs, s2m, skin, surf_type, surf_geom,
                 datetimes):
    """Create a set of RTTOV profiles."""

    my_profiles = pyrttov.Profiles(n_profiles, n_levels)

    # We want clouds in g/m3
    my_profiles.MmrCldAer = 0

    # Set ice cloud types
    icecloud = np.array([ice_scheme, ice_paramer], dtype=np.int32).transpose()

    # We want kg/kg for O3 and Q
    my_profiles.GasUnits = 1

    # Set up the actual profiles, expanding for nprofs
    # This essentially copies the RTTOV example code
    my_profiles.P = expand2nprofiles(pres, n_profiles)
    my_profiles.T = expand2nprofiles(temp, n_profiles)
    my_profiles.Q = expand2nprofiles(spechum, n_profiles)
    my_profiles.O3 = expand2nprofiles(ozone, n_profiles)

    my_profiles.Angles = expand2nprofiles(sat_angs, n_profiles)
    my_profiles.S2m = expand2nprofiles(s2m, n_profiles)
    my_profiles.Skin = expand2nprofiles(skin, n_profiles)
    my_profiles.SurfType = expand2nprofiles(surf_type, n_profiles)
    my_profiles.SurfGeom = expand2nprofiles(surf_geom, n_profiles)

    my_profiles.DateTimes = expand2nprofiles(datetimes, n_profiles)

    my_profiles.IceCloud = expand2nprofiles(icecloud, n_profiles)
    my_profiles.Icede = expand2nprofiles(np.zeros(n_levels), n_profiles)
    my_profiles.Cirr = expand2nprofiles(np.zeros(n_levels), n_profiles)
    my_profiles.Cfrac = expand2nprofiles(np.zeros(n_levels), n_profiles)

    return my_profiles
Exemplo n.º 3
0
 def do_load(self, inp):
     """Load an atmospheric profile. Requires inputs for data and resolution."""
     # Convert resolution into a number of profiles
     data, resolution, sun_zen, sun_az = inp.split()
     resolution = int(resolution)
     sun_zen = int(sun_zen)
     sun_az = int(sun_az)
     # Load the data
     data = h5py.File("{}/{}.h5".format(PROFILE_DIR, data), 'r')
     nlevels = len(np.array(data['P']))
     # Set up the profiles
     nprofs = 4 * resolution * resolution
     self.Profiles = pyrttov.Profiles(nprofs, nlevels)
     # Set the profile data
     probs = ['GasUnits', 'Skin']
     for key in [key for key in list(data.keys()) if key not in probs]:
         setattr(self.Profiles, key, np.tile(data[key], (nprofs, 1)))
         # print('{}\t{}'.format(key, getattr(self.Profiles, key).shape))
     setattr(self.Profiles, 'GasUnits', int(np.squeeze(data['GasUnits'])))
     setattr(self.Profiles, 'Skin',
             np.tile(list(data['Skin']) + [0], (nprofs, 1)))
     # Set angles
     ang_arr = np.empty((resolution, 4 * resolution, 4))
     # RTTOV can only handle up to 85 degrees for v9 predicators, otherwise 75
     # zen_leg = 85/resolution if '9pred' in self.Rttov.FileCoef else 75/resolution
     zen_leg = 90 / resolution
     az_leg = 90 / resolution
     for zen in range(resolution):
         for az in range(4 * resolution):
             ang_arr[zen,
                     az] = [zen_leg * zen, az_leg * az, sun_zen, sun_az]
     setattr(self.Profiles, 'Angles', ang_arr.reshape((nprofs, 4)))
     # print(self.Profiles.Angles)
     # Load the profiles
     self.Rttov.Profiles = self.Profiles
     return
Exemplo n.º 4
0
def runRTTOV(profileDict):
    nlevels = profileDict['P'].shape[1]
    nprofiles = profileDict['P'].shape[0]
    myProfiles = pyrttov.Profiles(nprofiles, nlevels)
    myProfiles.GasUnits = 2
    myProfiles.P = profileDict['P']
    myProfiles.T = profileDict['T']
    myProfiles.Q = profileDict['Q']
    myProfiles.Angles = profileDict['Angles']
    myProfiles.S2m = profileDict['S2m']
    myProfiles.Skin = profileDict['Skin']
    myProfiles.SurfType = profileDict['SurfType']
    myProfiles.SurfGeom = profileDict['SurfGeom']
    myProfiles.DateTimes = profileDict['Datetimes']
    month = profileDict['Datetimes'][0, 1]

    # ------------------------------------------------------------------------
    # Set up Rttov instance
    # ------------------------------------------------------------------------

    # Create Rttov object for the TIRS instrument

    tirsRttov = pyrttov.Rttov()
    #    nchan_tirs = 1

    # Set the options for each Rttov instance:
    # - the path to the coefficient file must always be specified
    # - specify paths to the emissivity and BRDF atlas data in order to use
    #   the atlases (the BRDF atlas is only used for VIS/NIR channels so here
    #   it is unnecessary for HIRS or MHS)
    # - turn RTTOV interpolation on (because input pressure levels differ from
    #   coefficient file levels)
    # - set the verbose_wrapper flag to true so the wrapper provides more
    #   information
    # - enable solar simulations for SEVIRI
    # - enable CO2 simulations for HIRS (the CO2 profiles are ignored for
    #   the SEVIRI and MHS simulations)
    # - enable the store_trans wrapper option for MHS to provide access to
    #   RTTOV transmission structure
    s = pyrttov.__file__
    envPath = os.sep.join(s.split(os.sep)[:-6])
    rttovPath = os.path.join(envPath, 'share')
    rttovCoeffPath = os.path.join(rttovPath, 'rttov')
    rttovEmisPath = os.path.join(rttovCoeffPath, 'emis_data')
    rttovBRDFPath = os.path.join(rttovCoeffPath, 'brdf_data')
    if not os.path.exists(rttovBRDFPath):
        print("downloading atlases.....")
        ftp = ftplib.FTP("ftp.star.nesdis.noaa.gov")
        ftp.login("anonymous", "")

        ftp.cwd('/pub/smcd/emb/mschull/')  # change directory to /pub/
        getFile(ftp, 'rttov_atlas.tar')

        ftp.quit()
        untar('rttov_atlas.tar', rttovPath)

        subprocess.check_output("chmod 755 %s%s*.H5" % (rttovEmisPath, os.sep),
                                shell=True)
        subprocess.check_output("chmod 755 %s%s*.H5" % (rttovBRDFPath, os.sep),
                                shell=True)
    tirsRttov.FileCoef = '{}/{}'.format(rttovCoeffPath,
                                        "rtcoef_landsat_8_tirs.dat")
    tirsRttov.EmisAtlasPath = rttovEmisPath
    tirsRttov.BrdfAtlasPath = rttovBRDFPath

    tirsRttov.Options.AddInterp = True
    tirsRttov.Options.StoreTrans = True
    tirsRttov.Options.StoreRad2 = True
    tirsRttov.Options.VerboseWrapper = True

    # Load the instruments:

    try:
        tirsRttov.loadInst()
    except pyrttov.RttovError as e:
        sys.stderr.write("Error loading instrument(s): {!s}".format(e))
        sys.exit(1)

    # Associate the profiles with each Rttov instance
    tirsRttov.Profiles = myProfiles
    # ------------------------------------------------------------------------
    # Load the emissivity and BRDF atlases
    # ------------------------------------------------------------------------

    # Load the emissivity and BRDF atlases:
    # - load data for August (month=8)
    # - note that we only need to load the IR emissivity once and it is
    #   available for both SEVIRI and HIRS: we could use either the seviriRttov
    #   or hirsRttov object to do this
    # - for the BRDF atlas, since SEVIRI is the only VIS/NIR instrument we can
    #   use the single-instrument initialisation

    tirsRttov.irEmisAtlasSetup(month)
    # ------------------------------------------------------------------------
    # Call RTTOV
    # ------------------------------------------------------------------------

    # Since we want the emissivity/reflectance to be calculated, the
    # SurfEmisRefl attribute of the Rttov objects are left uninitialised:
    # That way they will be automatically initialise to -1 by the wrapper

    # Call the RTTOV direct model for each instrument:
    # no arguments are supplied to runDirect so all loaded channels are
    # simulated
    try:
        tirsRttov.runDirect()
    except pyrttov.RttovError as e:
        sys.stderr.write("Error running RTTOV direct model: {!s}".format(e))
        sys.exit(1)

    return tirsRttov
Exemplo n.º 5
0
def runRTTOV(profileDict):
    nlevels = profileDict['P'].shape[1]
    nprofiles = profileDict['P'].shape[0]
    myProfiles = pyrttov.Profiles(nprofiles, nlevels)
    myProfiles.GasUnits = 2
    myProfiles.P = profileDict['P']
    myProfiles.T = profileDict['T']
    myProfiles.Q = profileDict['Q']
    myProfiles.Angles = profileDict['Angles']
    myProfiles.S2m = profileDict['S2m']
    myProfiles.Skin = profileDict['Skin']
    myProfiles.SurfType = profileDict['SurfType']
    myProfiles.SurfGeom = profileDict['SurfGeom']
    myProfiles.DateTimes = profileDict['Datetimes']
    month = profileDict['Datetimes'][0, 1]

    # ------------------------------------------------------------------------
    # Set up Rttov instance
    # ------------------------------------------------------------------------

    # Create Rttov object for the TIRS instrument

    tirsRttov = pyrttov.Rttov()
    nchan_tirs = 1

    # Set the options for each Rttov instance:
    # - the path to the coefficient file must always be specified
    # - specify paths to the emissivity and BRDF atlas data in order to use
    #   the atlases (the BRDF atlas is only used for VIS/NIR channels so here
    #   it is unnecessary for HIRS or MHS)
    # - turn RTTOV interpolation on (because input pressure levels differ from
    #   coefficient file levels)
    # - set the verbose_wrapper flag to true so the wrapper provides more
    #   information
    # - enable solar simulations for SEVIRI
    # - enable CO2 simulations for HIRS (the CO2 profiles are ignored for
    #   the SEVIRI and MHS simulations)
    # - enable the store_trans wrapper option for MHS to provide access to
    #   RTTOV transmission structure

    tirsRttov.FileCoef = '{}/{}'.format(
        rttov_installdir,
        "rtcoef_rttov11/rttov7pred54L/rtcoef_landsat_8_tirs.dat")

    #tirsRttov.EmisAtlasPath = os.path.join(base,'ALEXIdisALEXIfusion','rttov113','emis_data')
    tirsRttov.EmisAtlasPath = '{}/{}'.format(rttov_installdir, "emis_data")
    print "%s" % tirsRttov.EmisAtlasPath
    tirsRttov.BrdfAtlasPath = '{}/{}'.format(rttov_installdir, "brdf_data")
    #tirsRttov.BrdfAtlasPath = os.path.join(base,'ALEXIdisALEXIfusion','rttov113','brdf_data')

    tirsRttov.Options.AddInterp = True
    tirsRttov.Options.StoreTrans = True
    tirsRttov.Options.StoreRad2 = True
    tirsRttov.Options.VerboseWrapper = True

    # Load the instruments:

    try:
        tirsRttov.loadInst()
    except pyrttov.RttovError as e:
        sys.stderr.write("Error loading instrument(s): {!s}".format(e))
        sys.exit(1)

    # Associate the profiles with each Rttov instance
    tirsRttov.Profiles = myProfiles
    # ------------------------------------------------------------------------
    # Load the emissivity and BRDF atlases
    # ------------------------------------------------------------------------

    # Load the emissivity and BRDF atlases:
    # - load data for August (month=8)
    # - note that we only need to load the IR emissivity once and it is
    #   available for both SEVIRI and HIRS: we could use either the seviriRttov
    #   or hirsRttov object to do this
    # - for the BRDF atlas, since SEVIRI is the only VIS/NIR instrument we can
    #   use the single-instrument initialisation

    tirsRttov.irEmisAtlasSetup(month)
    # ------------------------------------------------------------------------
    # Call RTTOV
    # ------------------------------------------------------------------------

    # Since we want the emissivity/reflectance to be calculated, the
    # SurfEmisRefl attribute of the Rttov objects are left uninitialised:
    # That way they will be automatically initialise to -1 by the wrapper

    # Call the RTTOV direct model for each instrument:
    # no arguments are supplied to runDirect so all loaded channels are
    # simulated
    try:
        tirsRttov.runDirect()
    except pyrttov.RttovError as e:
        sys.stderr.write("Error running RTTOV direct model: {!s}".format(e))
        sys.exit(1)

    return tirsRttov
Exemplo n.º 6
0
def call_pyrttov(ds, config):
    """Run RTTOV, return xarray Dataset of reflectance or brightness temperature

    Args:
        ds (xr.Dataset): instance returned by xr.open_dataset, select one time
        config (object): see example below

    Example:
            config = setup_VIS()  # or setup_IR()
            ds_xr_out = call_pyrttov(ds_xr_in, config)
    """

    time_dt = get_wrfout_time(ds)
    print(time_dt)

    ########### input reading
    basetemp = 300.
    p = ds.PB / 100.  # (ds.P + ds.PB)/100. # ignore perturbation pressure as this could break monotonicity in p, and RTTOV
    theta = ds.T + basetemp
    qv = ds.QVAPOR  #  Water vapor mixing ratio  kg kg-1
    qi = ds.QICE  # Ice mixing ratio  kg kg-1
    qc = ds.QCLOUD
    cfrac = ds.CLDFRA
    tsk = ds.TSK
    u, v = ds.U10, ds.V10
    psfc = ds.PSFC / 100.
    try:  # in case that input is a wrfinput file (doesnt have these fields)
        albedo = ds.ALBEDO
        emissivity = ds.EMISS
    except AttributeError as e:
        warnings.warn(str(e) + ' -> using default values!')
        albedo = 0.17 + 0 * tsk
        emissivity = 0.985 + 0 * tsk

    nlevels = p.shape[0]

    def reformat_profile(arr):
        # reshape to out-dims: (nprofiles, nlevels); convention from TOA to ground
        return np.flip(arr.values.reshape((nlevels, -1)).transpose(), axis=1)

    p = reformat_profile(p)
    theta = reformat_profile(theta)
    qv = reformat_profile(qv)
    qi = reformat_profile(qi)
    qc = reformat_profile(qc)
    cfrac = reformat_profile(cfrac)
    nprofiles = p.shape[0]

    # reshape to (nprofiles, nlevels)
    u = u.values.reshape((-1, 1))
    v = v.values.reshape((-1, 1))
    tsk = tsk.values.reshape((-1, 1))
    psfc = psfc.values.reshape((-1, 1))
    albedo = albedo.values.reshape((-1, 1))
    emissivity = emissivity.values.reshape((-1, 1))

    ##  conversion to Rttov
    kappa = 2 / 7
    tmp = theta * (
        p *
        1e-3)**kappa  # ignoring water vapor in conversion to dry temperature

    ####### actual rttov
    seviriRttov = config.seviriRttov
    irAtlas = config.irAtlas
    try:
        brdfAtlas = config.brdfAtlas
        brdfAtlas.loadBrdfAtlas(
            time_dt.month, seviriRttov
        )  # Supply Rttov object to enable single-instrument initialisation
        brdfAtlas.IncSea = False  # Do not use BRDF atlas for sea surface types
    except AttributeError:
        pass

    nprofiles = p.shape[0]
    nlevels = p.shape[1]
    print('nlevels:', nlevels, 'nprofiles:', nprofiles)

    # solar angles
    lat = 45.
    lon = 0.
    sunzen = 90. - get_altitude(lat, lon, time_dt)
    sunazi = get_azimuth(lat, lon, time_dt)
    print('sunzen', sunzen, 'sunazi', sunazi)

    # surface data = lowest model half level data
    fetch = 100000. * np.ones(nprofiles)
    sfc_p_t_qv_u_v_fetch = np.stack(
        [psfc[:, 0], tmp[:, -1], qv[:, -1], u[:, 0], v[:, 0], fetch],
        axis=1).astype(np.float64)
    # sfc_u_v_fetch = np.array([[1., 1., 100000.]], dtype=np.float64)
    # sfc_u_v_fetch = expand(nprofiles, sfc_u_v_fetch)
    # sfc_p_t_qv_u_v_fetch = np.concatenate((arr[:,-1,:3], sfc_u_v_fetch), axis=-1)

    # quickfix qv
    # Q[:, :22] = 1e-6  # kg/kg  until 120 hPa
    if True:  # FIXME: is this necessary?
        qv[qv < 1e-9] = 1e-9

    # print('surface p_t_qv_u_v_fetch:', sfc_p_t_qv_u_v_fetch[0,...])
    # print('lowest level  p tmp qv qc:', arr[0, -1, :])
    # print('min sp', arr[:,-1,0].min())
    # print('uppermost level p tmp qv qc:', arr[0, 0, :])

    def expand2nprofiles(n, nprof):
        # Transform 1D array to a [nprof, nlevels] array
        outp = np.empty((nprof, len(n)), dtype=n.dtype)
        for i in range(nprof):
            outp[i, :] = n[:]
        return outp

    # Declare an instance of Profiles
    myProfiles = pyrttov.Profiles(nprofiles, nlevels)

    myProfiles.GasUnits = 1  # kg/kg for mixing ratios   [ ppmv_dry=0, kg_per_kg=1, ppmv_wet=2 ]
    myProfiles.MmrCldAer = True  # kg/kg for clouds and aerosoles

    myProfiles.P = p
    myProfiles.T = tmp
    myProfiles.Q = qv
    clw = qc  # cloud liquid water
    ciw = qi  # cloud ice water

    # input on layers; (nprofiles, nlevels)
    # myProfiles.CO2 = np.ones((nprofiles,nlevels))*3.743610E+02

    # for MW channels
    # myProfiles.CLW = clw

    # quickfix
    debug = False
    if debug:
        print('cfrac', np.min(cfrac), np.max(cfrac))
    myProfiles.Cfrac = cfrac  # cloud fraction

    # WATER CLOUDS
    dummy = np.ones((nprofiles, 2))
    dummy[:, 0] = 2  # clw_scheme : (1) OPAC or (2) Deff scheme
    dummy[:, 1] = 1  # clwde_param : currently only "1" possible
    myProfiles.ClwScheme = dummy

    myProfiles.Clwde = 20 * np.ones(
        (nprofiles, nlevels))  # microns effective diameter
    # Cloud types - concentrations in kg/kg
    myProfiles.Stco = clw  # Stratus Continental STCO
    myProfiles.Stma = 0 * clw  # Stratus Maritime STMA
    myProfiles.Cucc = 0 * clw  # Cumulus Continental Clean CUCC
    myProfiles.Cucp = 0 * clw  # Cumulus Continental Polluted CUCP
    myProfiles.Cuma = 0 * clw  # Cumulus Maritime CUMA
    myProfiles.Cirr = ciw  # all ice clouds CIRR

    # icecloud[2][nprofiles]: ice_scheme, idg
    icecloud = np.array([[1, 1]], dtype=np.int32)
    myProfiles.IceCloud = expand(nprofiles, icecloud)
    myProfiles.Icede = 60 * np.ones(
        (nprofiles, nlevels))  # microns effective diameter

    myProfiles.S2m = expand(nprofiles, sfc_p_t_qv_u_v_fetch)
    t_np = np.array([[
        time_dt.year, time_dt.month, time_dt.day, time_dt.hour, time_dt.minute,
        0
    ]],
                    dtype=np.int32)
    myProfiles.DateTimes = expand(nprofiles, t_np)
    # angles[4][nprofiles]: satzen, satazi, sunzen, sunazi
    angles = np.array([[45., 180., sunzen, sunazi]], dtype=np.float64)
    myProfiles.Angles = expand(nprofiles, angles)

    # surfgeom[3][nprofiles]: lat, lon, elev
    surfgeom = np.array([[lat, lon, 0.49]], dtype=np.float64)
    myProfiles.SurfGeom = expand(nprofiles, surfgeom)
    # surftype[2][nprofiles]: surftype, watertype
    surftype = np.array([[0, 0]], dtype=np.int32)
    myProfiles.SurfType = expand(nprofiles, surftype)
    # skin[10][nprofiles]: skin T, salinity, snow_frac, foam_frac, fastem_coefsx5, specularity
    skin = np.array([[270., 35., 0., 0., 3.0, 5.0, 15.0, 0.1, 0.3]],
                    dtype=np.float64)
    myProfiles.Skin = expand(nprofiles, skin)
    myProfiles.Skin[:, 0] = tsk[:, 0]

    seviriRttov.Profiles = myProfiles
    irAtlas.loadIrEmisAtlas(
        time_dt.month, ang_corr=True
    )  # Include angular correction, but do not initialise for single-instrument
    #######################################
    # Set up the surface emissivity/reflectance arrays and associate with the Rttov objects
    surfemisrefl_seviri = np.zeros((4, nprofiles, config.nchan),
                                   dtype=np.float64)
    surfemisrefl_seviri[0, :, :] = emissivity  # emissivity
    surfemisrefl_seviri[1, :, :] = albedo / np.pi  # reflectance
    surfemisrefl_seviri[2, :, :] = 0.  # diffuse reflectance
    surfemisrefl_seviri[3, :, :] = 0.  # specularity
    seviriRttov.SurfEmisRefl = surfemisrefl_seviri

    albedo_emiss_by_RTTOV = False
    if albedo_emiss_by_RTTOV:
        # Surface emissivity/reflectance arrays must be initialised *before every call to RTTOV*
        # Negative values will cause RTTOV to supply emissivity/BRDF values (i.e. equivalent to
        # calcemis/calcrefl TRUE - see RTTOV user guide)
        # Call emissivity and BRDF atlases
        try:
            # Do not supply a channel list for SEVIRI: this returns emissivity/BRDF values for all
            # *loaded* channels which is what is required
            surfemisrefl_seviri[:, :, 0] = irAtlas.getEmisBrdf(seviriRttov)
            surfemisrefl_seviri[:, :, 1] = brdfAtlas.getEmisBrdf(seviriRttov)
        except pyrttov.RttovError as e:
            # If there was an error the emissivities/BRDFs will not have been modified so it
            # is OK to continue and call RTTOV with calcemis/calcrefl set to TRUE everywhere
            sys.stderr.write("Error calling atlas: {!s}".format(e))

    # Call the RTTOV direct model for each instrument:
    # no arguments are supplied to runDirect so all loaded channels are simulated
    try:
        t = time.time()
        seviriRttov.runDirect()
        t = time.time() - t
        print('took', int(t * 10) / 10., 's')
    except pyrttov.RttovError as e:
        sys.stderr.write("Error running RTTOV direct model: {!s}".format(e))

    print('output shape:', (seviriRttov.BtRefl.shape))
    if seviriRttov.RadQuality is not None:
        print('Quality (qualityflag>0, #issues):',
              np.sum(seviriRttov.RadQuality > 0))

    dsout = ds.copy()
    delvars = [a for a in list(ds.variables)
               if not a in ['XLAT', 'XLONG']]  # 'OLR',
    dsout = dsout.drop_vars(delvars)

    # save each channel to separate file
    if debug:
        mmin = data.ravel().min()
        mmax = data.ravel().max()
        print(name, 'min:', mmin, 'max:', mmax)

    nx, ny = len(ds.west_east), len(ds.south_north)
    #data = np.zeros((ny, nx), dtype=np.float32)
    for i, name in enumerate(config.chan_seviri_names):
        data = seviriRttov.BtRefl[:, i]

        dsout[name] = (("south_north", "west_east"),
                       data.reshape(ny, nx).astype(np.float32))

    dsout.coords['time'] = time_dt.replace(
        tzinfo=None)  # .strftime('%Y-%m-%d_%H:%M')

    drop_lat_lon = True  # switch to False to retain coordinates from input file.
    if drop_lat_lon:
        dsout = dsout.drop_vars(['XLAT', 'XLONG'])
    return dsout