def stageData(self, m): # Get the observational data obs = Variable(filename=self.source, variable_name=self.variable, alternate_vars=self.alternate_vars) # Reduce the sites if self.map: obs.lat = obs.lat[self.map] obs.lon = obs.lon[self.map] obs.depth = obs.depth[self.map] obs.data = obs.data[:, self.map] obs.ndata = len(self.map) # Get the model result force_emulation = self.keywords.get("force_emulation", "False").lower() == "true" never_emulation = self.keywords.get("never_emulation", "False").lower() == "true" no_co2 = False mod = None if not force_emulation: try: #print "Trying to get co2 from %s" % m.name mod = m.extractTimeSeries( self.variable, alt_vars=self.alternate_vars, initial_time=obs.time_bnds[0, 0], final_time=obs.time_bnds[-1, 1], lats=None if obs.spatial else obs.lat, lons=None if obs.spatial else obs.lon) except il.VarNotInModel: #print "co2 not in %s" % m.name no_co2 = True if (((mod is None) or no_co2) and (not never_emulation)): #print "Emulating co2 in %s" % m.name mod = self.emulatedModelResult(m, obs) if mod is None: raise il.VarNotInModel() # get the right layering, closest to the layer elevation where all aren't masked. if mod.layered: ind = (np.abs(obs.depth[:, np.newaxis] - mod.depth)).argmin(axis=1) for i in range(ind.size): while (mod.data[:, ind[i], i].mask.sum() > 0.5 * mod.data.shape[0]): ind[i] += 1 data = [] for i in range(ind.size): data.append(mod.data[:, ind[i], i]) mod.data = np.ma.masked_array(data).T mod.depth = None mod.depth_bnds = None mod.layered = False obs, mod = il.MakeComparable(obs, mod, mask_ref=True, clip_ref=True) mod.data.mask += obs.data.mask # Remove the trend via quadradic polynomial obs = _detrend(obs) mod = _detrend(mod) return obs, mod
def getDiurnalDataForGivenYear(var, year): """ """ # Get this year's data, make sure there is enough spd = int(round(1 / np.diff(var.time_bnds, axis=1).mean())) datum = cftime.date2num(cftime.datetime(year, 1, 1), "days since 1850-1-1") ind = np.where(year == var.year)[0] t = var.time[ind] - datum tb = var.time_bnds[ind] - datum data = var.data[ind, 0] # Reshape the data begin = np.argmin(tb[:(spd - 1), 0] % 1) end = begin + int(t[begin:].size / float(spd) - 1) * spd shift = int(round((var.tmax - 12) / (var.dt * 24))) begin += shift end += shift shp = (-1, spd) + data.shape[1:] data = data[begin:end].reshape(shp) t = t[begin:end].reshape(shp).mean(axis=1) # Diurnal magnitude mag = Variable(name="mag%d" % year, unit=var.unit, time=t, data=data.max(axis=1) - data.min(axis=1)) # Some of the tower data is 'intelligently' masked which leads to # too much of the data being removed to use my change-detection # algorithm to determine season begin/end. mag.skip = False if mag.data.mask.all(): raise NotEnoughDataInYear # if year is all masked dmag = (mag.data.max() - mag.data.min()) if dmag < 1e-14: raise NotEnoughDataInYear # if diurnal mag has no amplitude # Some mask out off seasons, season is taken to be all the data begin_day, end_day = mag.time[mag.data.mask == False][[ 0, -1 ]] # begin/end of the mask data if ((begin_day < 2 and end_day < 363) or (begin_day > 2 and end_day > 363)): # this is likely a dataset which is a partial year raise NotEnoughDataInYear elif (begin_day > 2 and end_day < 363): # this is likely a dataset that masks out off-seasons season = np.asarray([begin_day, end_day]) else: season = findSeasonalTiming(mag.time, mag.data) centroid = findSeasonalCentroid(mag.time, mag.data) mag.season = season mag.centroid = centroid # Mask out off season mask = (t < season[0]) + (t > season[1]) data = np.ma.masked_array(data, mask=mask[:, np.newaxis] * np.ones(data.shape[1], dtype=bool)) # Mean seasonal diurnal cycle uncert = np.zeros((data.shape[1], 2)) for i in range(data.shape[1]): d = data[:, i].compressed() if d.size == 0: continue uncert[i, :] = np.percentile(d, [10, 90]) day = np.linspace(0, 1, spd + 1) day = 0.5 * (day[:-1] + day[1:]) with np.errstate(under='ignore', over='ignore'): cycle = Variable(name="cycle%d" % year, unit=var.unit, time=day, data=data.mean(axis=0), data_bnds=uncert) # Mean seasonal uptake uptake = Variable(unit=var.unit, time=var.time[ind] - datum, time_bnds=var.time_bnds[ind] - datum, data=var.data[ind, 0]) uptake.data = np.ma.masked_array(uptake.data, mask=((uptake.time < season[0]) + (uptake.time > season[1]))) uptake = uptake.integrateInTime(mean=True) cycle.uptake = uptake.data # Timing of peak seasonal cycle, could be a maximum or minimum, # check second derivative of a best-fit parabola to the daytime # data. begin = int(spd / 4) end = int(spd * 3 / 4) p = np.polyfit(cycle.time[begin:end], cycle.data[begin:end], 2) if p[0] < 0: cycle.peak = day[cycle.data.argmax()] * 24 else: cycle.peak = day[cycle.data.argmin()] * 24 return mag, cycle