コード例 #1
0
    def ft_even_diffuse_reflection_matrix(self, frequency, eps_1, mu_s, mu_i,
                                          m_max, npol):

        assert mu_s is mu_i

        if isinstance(self.backscattering_coefficient,
                      dict):  # we have a dictionary with polarization
            diffuse_refl_coeff = smrt_matrix.zeros(
                (npol, m_max + 1, len(mu_i)))

            for m in range(m_max + 1):
                if m == 0:
                    coef = 0.5
                elif (m % 2) == 1:
                    coef = -1.0
                else:
                    coef = 1.0
                coef /= 4 * np.pi * mu_i  # SMRT requires scattering coefficient / 4 * pi

                coef /= m_max + 0.5  # ad hoc normalization to get the right backscatter. This is a trick to deal with the dirac.

                diffuse_refl_coeff[0, m, :] += coef * self._get_refl(
                    self.backscattering_coefficient['VV'], mu_i)
                diffuse_refl_coeff[1, m, :] += coef * self._get_refl(
                    self.backscattering_coefficient['HH'], mu_i)

        elif self.backscattering_coefficient is not None:
            raise SMRTError(
                "backscattering_coefficient must be a dictionary with keys VV and HH"
            )
        else:
            return smrt_matrix(0)

        return diffuse_refl_coeff
コード例 #2
0
    def ft_even_diffuse_reflection_matrix(self, m, frequency, eps_1, mu1,
                                          npol):

        if m > 0:
            return 0  # we've to assume that the backscattering is hemispheric, dealing with a dirac is not possible here
        if isinstance(self.backscattering_coefficient,
                      dict):  # we have a dictionary with polarization
            diffuse_refl_coeff = np.empty(npol * len(mu1))
            if m == 0:
                coef = 0.5
            elif (m % 2) == 1:
                coef = -1.0
            else:
                coef = 1.0

            # correct for the angle between the air and the medium
            #relsin2 = (1 - mu1 ** 2) * eps_1.real
            #coef *= np.where(relsin2 < 1, 1/np.sqrt(1 - relsin2), 0)

            # no, no, it does not work, there is something to be clarified...
            coef /= mu1

            diffuse_refl_coeff[0::npol] += coef * self._get_refl(
                self.backscattering_coefficient['VV'], mu1)
            diffuse_refl_coeff[1::npol] += coef * self._get_refl(
                self.backscattering_coefficient['HH'], mu1)
        elif self.backscattering_coefficient is not None:
            raise SMRTError("backscattering_coefficient must be a dictionary")
        else:
            return 0

        return scipy.sparse.diags(diffuse_refl_coeff, 0)
コード例 #3
0
 def _get_refl(self, specular_reflection, mu1):
     if callable(specular_reflection):  # we have a function, call it and see what we get
         user_refl = specular_reflection(np.arccos(mu1))
         if len(user_refl) == len(mu1):  # we have only one polarization
             return user_refl
         else:
             raise SMRTError("The length/shape or the specular_reflection function is incorrect")
     else:  # we have a scalar
         return np.full(len(mu1), specular_reflection, dtype=np.float64)
コード例 #4
0
def run(sensor,
        snowpack,
        scattering_choice=ABORN,
        atmosphere=None,
        memls_path=None,
        memls_driver=None,
        snowpack_dimension=None):
    """ call MEMLS for the snowpack and sensor configuration given as argument. Any microstructure model that defines the "corr_length" parameter
        is valid, but it must be clear that MEMLS only considers exponential autocorrelation.

        :param snowpack: describe the snowpack.
        :param sensor: describe the sensor configuration.
        :param scattering_choice: MEMLS proposes several formulation to compute scattering_function. scattering_choice=ABORN (equals 12) is the default
            here and is recommended choice to compare with IBA. Note that some comments in memlsmain.m suggest to use 
            scattering_choice=MEMLS_RECOMMENDED (equals 11). Note also that the default grain type in memlsmain is graintype=1 
            corresponding to oblate spheroidal calculation of effective permittivity from the empirical representation of depolarization factors. To use a Polder-Van Santen representation of effective permittivity for small spheres, graintype=2 must be set in your local copy of MEMLS.
        :param atmosphere: describe the atmosphere. Only tbdown is used for the Tsky argument of memlsmain.
        :param memls_path: directory path to the memls Matlab scripts
        :param memls_driver: matlab function to call to run memls. memlsmain.m is the default driver in the original MEMLS distribution for the passive case and amemlsmain.m for the active case.
        :param snowpack_dimension: name and values (as a tuple) of the dimension to create for the results when a list of snowpack is provided. E.g. time, point, longitude, latitude. By default the dimension is called 'snowpack' and the values are from 1 to the number of snowpacks.


"""

    if memls_path is not None:
        set_memls_path(memls_path)

    if isinstance(sensor.frequency, Sequence) or isinstance(
            sensor.frequency, np.ndarray):
        raise SMRTError(
            "Sensor must have a single frequency for running memls_legagcy")

    if isinstance(snowpack, SensitivityStudy):
        snowpack_dimension = (snowpack.variable, snowpack.values)
        snowpack = snowpack.snowpacks.tolist()

    if isinstance(snowpack, Sequence):
        result_list = [
            run(sensor,
                sp,
                scattering_choice=scattering_choice,
                atmosphere=atmosphere,
                memls_driver=memls_driver) for sp in snowpack
        ]
        if snowpack_dimension is None:
            snowpack_dimension = 'snowpack', range(len(snowpack))
        return concat_results(result_list, snowpack_dimension)

    Tsky = atmosphere.tbdown(sensor.frequency, np.cos(sensor.theta),
                             1) if atmosphere is not None else 0
    Tgnd = snowpack.substrate.temperature if snowpack.substrate is not None else 273

    if snowpack.substrate is None:
        ground_reflH = itertools.repeat(0)
        ground_reflV = itertools.repeat(0)
    else:
        print(
            "Using MEMLS with substrate has not been tested. Provide feeback if it works (or not)"
        )
        eps_1 = snowpack.layers[-1].permittivity(1, sensor.frequency)
        print(
            "Warning: the permittivity of the ice in the last layer is used instead of the effective permittivity to compute the reflection of the subtrate. This is an approximation that needs to be changed. Please contact developer for any serious simulations with soil..."
        )
        m = snowpack.substrate.specular_reflection_matrix(
            sensor.frequency, eps_1, np.cos(sensor.theta), 2)
        ground_reflH = m.diagonal()[1::2]
        ground_reflV = m.diagonal()[0::2]

    # prepare the input file in a temporary file
    with NamedTemporaryFile("w", delete=False) as f:
        #     layer-number, temp [K], volume fraction of liquid water, density [kg/m3],
        # thickness [cm], Salinity (0 - 0.1) [ppt], expon.corr.length [mm]

        for ilay, lay in enumerate(reversed(snowpack.layers)):
            f.write("%i, %g, %g, %g, %g, %g, %g\n" %
                    (ilay + 1, lay.temperature, lay.liquid_water,
                     lay.frac_volume * DENSITY_OF_ICE, lay.thickness * 100.0,
                     lay.salinity, lay.microstructure.corr_length * 1000.))

    # uncomment these lines if you need to check the input file content.
    #with open(f.name) as ff:
    #    print(ff.readlines())

    if memls_driver is None:
        memls_driver = "memlsmain" if sensor.mode == 'P' else "amemlsmain"

    memlsfct = getattr(octave, memls_driver)

    if sensor.mode == 'P':
        res = [
            memlsfct(sensor.frequency * 1e-9, thetad,
                     float(reflH), float(reflV), f.name, float(Tsky),
                     float(Tgnd), scattering_choice) for thetad, reflH, reflV
            in zip(sensor.theta_deg, ground_reflH, ground_reflV)
        ]
        res = np.vstack(res)
        coords = [('theta', sensor.theta_deg), ('polarization', ['V', 'H'])]

    else:  # active
        mean_slope = 1e3  # a high value to remove this contribution. But in the future should be taken from the substrate model, depending on the model...
        res = [
            memlsfct(sensor.frequency * 1e-9, thetad, float(reflH),
                     float(reflV), float(reflH), float(reflV), f.name,
                     float(Tsky), float(Tgnd), scattering_choice, mean_slope,
                     0)['sigma0'][0, :] for thetad, reflH, reflV in zip(
                         sensor.theta_inc_deg, ground_reflH, ground_reflV)
        ]

        coords = [('polarization', ['V', 'H']),
                  ('polarization_inc', ['V', 'H']),
                  ('theta_inc', sensor.theta_inc_deg),
                  ('theta', sensor.theta_deg)]
        res = np.array(res)
        norm = 4 * np.pi * np.cos(
            sensor.theta)  # convert back backscattering coefficient
        # assemble in the polarizations
        res = [[np.diagflat(res[:, 0] / norm),
                np.diagflat(res[:, 2] / norm)],
               [np.diagflat(res[:, 2] / norm),
                np.diagflat(res[:, 1]) / norm]]

    os.unlink(f.name)

    return Result(res, coords)