def test_concat_results(): allresult = result.concat_results((res_example, res_example2), coord=('dim0', [0, 1])) print(allresult) assert 'dim0' in allresult.data.dims assert len(allresult.data['dim0']) == 2
def test_concat_results_other_data(): res = copy.deepcopy(res_example) res2 = copy.deepcopy(res_example2) res.other_data['other_value'] = xr.DataArray([0.1, 0.2], coords=[('layer', [0, 1])]) res2.other_data['other_value'] = xr.DataArray([0.2, 0.3], coords=[('layer', [0, 1])]) allresult = result.concat_results((res, res2), coord=('dim0', [0, 1])) assert allresult.other_data['other_value'].dims == ('dim0', 'layer')
def run(sensor, snowpack, ke_option=0, grainsize_option=1, hut_path=None): """call HUT for the snowpack and sensor configuration given as argument. Any microstructure model that defines the "radius" parameter is valid. :param snowpack: describe the snowpack. :param sensor: describe the sensor configuration. :param ke_option: see HUT snowemis_nlayers.m code :param grainsize_option: see HUT snowemis_nlayers.m code """ if hut_path is not None: set_hut_path(hut_path) if isinstance(snowpack, collections.Sequence): result_list = [run(sensor, sp, ke_option=ke_option, grainsize_option=grainsize_option) for sp in snowpack] return concat_results(result_list, ('snowpack', range(len(snowpack)))) if snowpack.substrate is not None: Tg = snowpack.substrate.temperature roughness_rms = getattr(snowpack.substrate, "roughness_rms", 0) soil_eps = snowpack.substrate.permittivity(sensor.frequency, Tg) else: Tg = 273.0 roughness_rms = 0 soil_eps = 1 snow = [] # snow is a N Layer (snowpack+soil) row and 8 columns. Each colum has a data (see snowemis_nlayer) enough_warning = False for lay in snowpack.layers: density = lay.frac_volume * 917.0 snow.append((lay.temperature-273.15, lay.thickness*density, 2000*lay.microstructure.radius, density/1000, lay.liquid_water, lay.salinity, 0, 0)) if lay.salinity and enough_warning: print("Warning: salinity in HUT is ppm") enough_warning = True # ground snow.append((Tg-273.15, 0, 0, 0, 0, 0, roughness_rms, soil_eps)) thetad = np.degrees(sensor.theta) TbV = [octave.snowemis_nlayer(otulo, snow, sensor.frequency/1e9, 0, ke_option, grainsize_option) for otulo in thetad] TbH = [octave.snowemis_nlayer(otulo, snow, sensor.frequency/1e9, 1, ke_option, grainsize_option) for otulo in thetad] coords = [('theta', sensor.theta), ('polarization', ['V', 'H'])] return Result(np.vstack((TbV, TbH)).T, coords)
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)
def run(sensor, snowpack, dmrt_qms_path=None, snowpack_dimension=None, full_output=False): """call DMRT-QMS for the snowpack and sensor configuration given as argument. The :py:mod:`~smrt.microstructure_model.sticky_hard_spheres` microstructure model must be used. :param snowpack: describe the snowpack. :param sensor: describe the sensor configuration. :param full_output: determine if ks, ka and effective permittivity are return in addition to the result object """ if dmrt_qms_path is not None: set_dmrt_qms_path(dmrt_qms_path) if isinstance(snowpack, SensitivityStudy): snowpack_dimension = (snowpack.variable, snowpack.values) snowpack = snowpack.snowpacks.tolist() if isinstance(snowpack, Sequence): result_list = [run(sensor, sp) for sp in snowpack] if snowpack_dimension is None: snowpack_dimension = 'snowpack', range(len(snowpack)) return concat_results(result_list, snowpack_dimension) Tg = snowpack.substrate.temperature if snowpack.substrate is not None else 273.0 rough = Struct() if snowpack.substrate is None: rough.model = 'QH' epsr_ground = complex(1.0, 0.0) rough.Q = 0.0 rough.H = 0.0 elif hasattr(snowpack.substrate, "Q") and hasattr(snowpack.substrate, "H"): rough.model = 'QH' epsr_ground = snowpack.substrate.permittivity_model( sensor.frequency, Tg) rough.Q = snowpack.substrate.Q rough.H = snowpack.substrate.H if hasattr(snowpack.substrate, "N") and snowpack.substrate.N != 2: print( "Warning: DMRT QMS with QH model assumes N=2. You should set N=2 to avoid this warning." ) elif hasattr(snowpack.substrate, "roughness_rms"): print( "Warning: DMRT-QMS does not implement the same version of the Wegmuller & Mazler model" ) rough.model = 'WM' epsr_ground = snowpack.substrate.permittivity_model( sensor.frequency, Tg) rough.s = snowpack.substrate.roughness_rms diameter = np.float64( [lay.microstructure.radius * 200 for lay in snowpack.layers]) density = np.float64( [lay.frac_volume * DENSITY_OF_ICE / 1000 for lay in snowpack.layers]) thickness = np.float64([lay.thickness * 100.0 for lay in snowpack.layers]) stickiness = np.float64([ min(lay.microstructure.stickiness, 1000.0) for lay in snowpack.layers ]) temperature = np.float64([lay.temperature for lay in snowpack.layers]) TbV, TbH, deg0, ot, albedo, epsr_snow = octave.DMRT_QMS_passive( sensor.frequency * 1e-9, diameter, density, stickiness, thickness, temperature, Tg, epsr_ground, rough, nout=6) # squeeze extra dimension deg0 = deg0.squeeze() # interpolate TbV = np.interp(np.degrees(sensor.theta), deg0, TbV.squeeze()) TbH = np.interp(np.degrees(sensor.theta), deg0, TbH.squeeze()) coords = [('theta', sensor.theta), ('polarization', ['V', 'H'])] if full_output: ke = ot / np.array([lay.thickness for lay in snowpack.layers]) ks = albedo * ke ka = (1 - albedo) * ke return Result(np.vstack([TbV, TbH]).T, coords), ks, ka, epsr_snow else: return Result(np.vstack([TbV, TbH]).T, coords)