コード例 #1
0
    def confront(self, m):

        obs, mod = self.stageData(m)
        obs_area = obs.integrateInSpace().convert("1e6 km2")
        mod_area = mod.integrateInSpace().convert("1e6 km2")

        # Interpolate to a composed grid
        lat, lon, lat_bnds, lon_bnds = il._composeGrids(obs, mod)
        OBS = obs.interpolate(lat=lat,
                              lon=lon,
                              lat_bnds=lat_bnds,
                              lon_bnds=lon_bnds)
        MOD = mod.interpolate(lat=lat,
                              lon=lon,
                              lat_bnds=lat_bnds,
                              lon_bnds=lon_bnds)

        # Compute the different extent areas
        o_mask = OBS.data.mask
        o_land = (OBS.area > 1e-12) * (o_mask == 0)
        o_data = np.copy(OBS.data.data)
        o_data[np.where(OBS.data.mask)] = 0.

        m_mask = MOD.data.mask
        m_land = (MOD.area > 1e-12)
        m_data = np.copy(MOD.data.data)
        m_data[np.where(MOD.data.mask)] = 0.

        o_and_m = (np.abs(o_data - 1) < 1e-12) * (np.abs(m_data - 1) < 1e-12)
        o_not_m_land = (np.abs(o_data - 1) < 1e-12) * (np.abs(m_data) <
                                                       1e-12) * (m_land == 0)
        o_not_m_miss = (np.abs(o_data - 1) < 1e-12) * (np.abs(m_data) <
                                                       1e-12) * (m_land == 1)
        o_zones = 1. * o_and_m
        o_zones += 2. * o_not_m_land
        o_zones += 4. * o_not_m_miss
        o_zones = np.ma.masked_array(o_zones, mask=o_mask)

        m_and_o = (np.abs(m_data - 1) < 1e-12) * (np.abs(o_data - 1) < 1e-12)
        m_not_o_land = (np.abs(m_data - 1) < 1e-12) * (np.abs(o_data) <
                                                       1e-12) * (o_land == 0)
        m_not_o_miss = (np.abs(m_data - 1) < 1e-12) * (np.abs(o_data) <
                                                       1e-12) * (o_land == 1)
        m_zones = 1. * m_and_o
        m_zones += 2. * m_not_o_land
        m_zones += 4. * m_not_o_miss
        m_zones = np.ma.masked_array(m_zones, mask=m_mask)

        zones = 1. * o_and_m
        zones += 2. * o_not_m_miss
        zones += 4. * m_not_o_miss
        zones += 8. * m_not_o_land
        zones = np.ma.masked_less(zones, 1)
        for i, u in enumerate(np.unique(zones.compressed())):
            zones[np.where(zones == u)] = i

        # compute the intersection of obs and mod
        obs_and_mod = Variable(name="obs_and_mod",
                               unit="1",
                               data=np.ma.masked_values(zones == 0,
                                                        0).astype(float),
                               lat=lat,
                               lon=lon,
                               area=MOD.area)

        # compute the obs that is not the mod
        data = (OBS.data.mask == 0) * (MOD.data.mask == 1)
        obs_not_mod = Variable(name="obs_not_mod",
                               unit="1",
                               data=np.ma.masked_values(zones == 1,
                                                        0).astype(float),
                               lat=lat,
                               lon=lon,
                               area=OBS.area)

        # compute the mod that is not the obs
        data = (OBS.data.mask == 1) * (MOD.data.mask == 0)
        mod_not_obs = Variable(name="mod_not_obs",
                               unit="1",
                               data=np.ma.masked_values(zones == 2,
                                                        0).astype(float),
                               lat=lat,
                               lon=lon,
                               area=MOD.area)

        # compute the mod that is not the obs but because of land representation
        data = (OBS.data.mask == 1) * (MOD.data.mask == 0)
        mod_not_obs_land = Variable(name="mod_not_obs_land",
                                    unit="1",
                                    data=np.ma.masked_values(zones == 3,
                                                             0).astype(float),
                                    lat=lat,
                                    lon=lon,
                                    area=MOD.area)

        # compute areas
        obs_and_mod_area = obs_and_mod.integrateInSpace().convert("1e6 km2")
        obs_not_mod_area = obs_not_mod.integrateInSpace().convert("1e6 km2")
        mod_not_obs_area = mod_not_obs.integrateInSpace().convert("1e6 km2")
        mod_not_obs_land_area = mod_not_obs_land.integrateInSpace().convert(
            "1e6 km2")

        # determine score
        obs_score = Variable(name="Missed Score global",
                             unit="1",
                             data=obs_and_mod_area.data /
                             (obs_and_mod_area.data + obs_not_mod_area.data))
        mod_score = Variable(name="Excess Score global",
                             unit="1",
                             data=obs_and_mod_area.data /
                             (obs_and_mod_area.data + mod_not_obs_area.data))

        # Write to datafiles --------------------------------------

        obs_area.name = "Total Area"
        mod_area.name = "Total Area"
        obs_and_mod_area.name = "Overlap Area"
        obs_not_mod_area.name = "Missed Area"
        mod_not_obs_area.name = "Excess Area"
        mod_not_obs_land_area.name = "Excess Area (Land Representation)"

        results = Dataset("%s/%s_%s.nc" %
                          (self.output_path, self.name, m.name),
                          mode="w")
        results.setncatts({"name": m.name, "color": m.color})
        mod.toNetCDF4(results, group="MeanState")
        obs_and_mod.toNetCDF4(results, group="MeanState")
        obs_not_mod.toNetCDF4(results, group="MeanState")
        mod_not_obs.toNetCDF4(results, group="MeanState")
        mod_not_obs_land.toNetCDF4(results, group="MeanState")
        mod_area.toNetCDF4(results, group="MeanState")
        obs_and_mod_area.toNetCDF4(results, group="MeanState")
        obs_not_mod_area.toNetCDF4(results, group="MeanState")
        mod_not_obs_area.toNetCDF4(results, group="MeanState")
        mod_not_obs_land_area.toNetCDF4(results, group="MeanState")
        obs_score.toNetCDF4(results, group="MeanState")
        mod_score.toNetCDF4(results, group="MeanState")
        results.close()

        if self.master:
            results = Dataset("%s/%s_Benchmark.nc" %
                              (self.output_path, self.name),
                              mode="w")
            results.setncatts({
                "name": "Benchmark",
                "color": np.asarray([0.5, 0.5, 0.5])
            })
            obs_area.toNetCDF4(results, group="MeanState")
            results.close()
コード例 #2
0
ファイル: ConfTWSA.py プロジェクト: dvalters/ILAMB
    def stageData(self,m):
        r"""Extracts model data which is comparable to the observations.

        The observational data measure the anomaly in terrestrial
        water storage, 'twsa' in terms of [kg m-2]. We convert this
        unit to [cm] using the density of water. The models are
        expected to provide the terrestrial water storage variable,
        'tws', and we need to find the anomaly. First, the model
        result is trimmed to match the temporal extents of the
        observational data. Then, to get the anomaly, we subtract off
        the temporal mean,

        .. math:: \mathit{twsa}(t,\mathbf{x}) = tws(t,\mathbf{x}) - \frac{1}{t_f-t_0}\int_{t_0}^{t_f} tws(t,\mathbf{x})\ dt 

        We do this for the model 'tws' variable, and optionally for
        the observation, treating its 'twsa' variable as 'tws' in the
        above expression. This is because the observational data can
        have a small mean even though it represents only the anomaly.

        Parameters
        ----------
        m : ILAMB.ModelResult.ModelResult
            the model result context

        Returns
        -------
        obs : ILAMB.Variable.Variable
            the variable context associated with the observational dataset
        mod : ILAMB.Variable.Variable
            the variable context associated with the model result

        """
        # get the observational data
        obs = Variable(filename       = self.source,
                       variable_name  = self.variable,
                       alternate_vars = self.alternate_vars).convert("cm")

        # get the model data, in the units of the obseravtions
        mod = m.extractTimeSeries(self.variable,
                                  alt_vars     = self.alternate_vars,
                                  expression   = self.derived,
                                  initial_time = obs.time_bnds[ 0,0],
                                  final_time   = obs.time_bnds[-1,1])

        # if the derived expression is used, then we get a mass flux
        # rate and need to accumulate
        try:
            mod.convert(obs.unit)
        except:
            mod = mod.accumulateInTime()
            mod.name = obs.name
        obs,mod = il.MakeComparable(obs,mod,clip_ref=True)

        # subtract off the mean
        mean      = obs.integrateInTime(mean=True)
        obs.data -= mean.data
        mean      = mod.integrateInTime(mean=True)
        mod.data -= mean.data

        # compute mean values over each basin
        odata = np.ma.zeros((obs.time.size,len(self.basins)))
        mdata = np.ma.zeros((mod.time.size,len(self.basins)))
        for i,basin in enumerate(self.basins):
            odata[:,i] = obs.integrateInSpace(region=basin,mean=True).data
            mdata[:,i] = mod.integrateInSpace(region=basin,mean=True).data
        obs.data = odata; obs.ndata = odata.shape[1]; obs.spatial = False
        mod.data = mdata; mod.ndata = mdata.shape[1]; mod.spatial = False
        mod.data.mask = obs.data.mask
        
        return obs,mod
コード例 #3
0
    def confront(self, m):

        obs, mod = self.stageData(m)
        obs_area = obs.integrateInSpace().convert("1e6 km2")
        mod_area = mod.integrateInSpace().convert("1e6 km2")

        # interpolate to a composed grid
        lat, lon = il.ComposeSpatialGrids(obs, mod)
        iobs = obs.interpolate(lat=lat, lon=lon)
        imod = mod.interpolate(lat=lat, lon=lon)

        # compute the intersection of obs and mod
        data = (iobs.data.mask == 0) * (imod.data.mask == 0)
        obs_and_mod = Variable(name="obs_and_mod",
                               unit="1",
                               data=np.ma.masked_values(data, 0).astype(float),
                               lat=lat,
                               lon=lon)

        # compute the obs that is not the mod
        data = (iobs.data.mask == 0) * (imod.data.mask == 1)
        obs_not_mod = Variable(name="obs_not_mod",
                               unit="1",
                               data=np.ma.masked_values(data, 0).astype(float),
                               lat=lat,
                               lon=lon)

        # compute the mod that is not the obs
        data = (iobs.data.mask == 1) * (imod.data.mask == 0)
        mod_not_obs = Variable(name="mod_not_obs",
                               unit="1",
                               data=np.ma.masked_values(data, 0).astype(float),
                               lat=lat,
                               lon=lon)

        # compute areas
        obs_and_mod_area = obs_and_mod.integrateInSpace().convert("1e6 km2")
        obs_not_mod_area = obs_not_mod.integrateInSpace().convert("1e6 km2")
        mod_not_obs_area = mod_not_obs.integrateInSpace().convert("1e6 km2")

        # determine score
        obs_score = Variable(name="Obs Score global",
                             unit="1",
                             data=obs_and_mod_area.data / obs_area.data)
        mod_score = Variable(name="Mod Score global",
                             unit="1",
                             data=obs_and_mod_area.data / mod_area.data)

        # Write to datafiles --------------------------------------

        obs_area.name = "Total Area"
        mod_area.name = "Total Area"
        obs_and_mod_area.name = "Overlap Area"
        obs_not_mod_area.name = "Missed Area"
        mod_not_obs_area.name = "Excess Area"

        results = Dataset("%s/%s_%s.nc" %
                          (self.output_path, self.name, m.name),
                          mode="w")
        results.setncatts({"name": m.name, "color": m.color})
        mod.toNetCDF4(results, group="MeanState")
        obs_and_mod.toNetCDF4(results, group="MeanState")
        obs_not_mod.toNetCDF4(results, group="MeanState")
        mod_not_obs.toNetCDF4(results, group="MeanState")
        mod_area.toNetCDF4(results, group="MeanState")
        obs_and_mod_area.toNetCDF4(results, group="MeanState")
        obs_not_mod_area.toNetCDF4(results, group="MeanState")
        mod_not_obs_area.toNetCDF4(results, group="MeanState")
        obs_score.toNetCDF4(results, group="MeanState")
        mod_score.toNetCDF4(results, group="MeanState")
        results.close()

        if self.master:
            results = Dataset("%s/%s_Benchmark.nc" %
                              (self.output_path, self.name),
                              mode="w")
            results.setncatts({
                "name": "Benchmark",
                "color": np.asarray([0.5, 0.5, 0.5])
            })
            obs_area.toNetCDF4(results, group="MeanState")
            results.close()