def vectoravg(hr1, hr2, clocktype): 'Function to test vector-averaging of two time values:' import MV2 sin_avg = (MV2.sin(hrs_to_rad(hr1, clocktype)) + MV2.sin(hrs_to_rad(hr2, clocktype))) / 2 cos_avg = (MV2.cos(hrs_to_rad(hr1, clocktype)) + MV2.cos(hrs_to_rad(hr2, clocktype))) / 2 return rad_to_hrs(MV2.arctan2(sin_avg, cos_avg), clocktype)
def testUpdateArray(self): L = cdms2.createAxis(range(0, 360, 36)) L.designateLongitude() lat = cdms2.createAxis(range(-90, 90, 18)) a = numpy.arange(400) a.shape = (2, 2, 10, 10) b = MV2.cos(a) / 2. a = MV2.sin(a) t = cdms2.createAxis(range(2)) t.designateTime() t.units = "months since 2014" t.id = "time" l = cdms2.createAxis(numpy.arange(1, 3) * 1000.) l.designateLevel() l.units = "hPa" l.id = "plev" a.setAxis(0, t) a.setAxis(1, l) a.setAxis(2, lat) a.setAxis(3, L) b.setAxisList(a.getAxisList()) gm = self.x.createboxfill() gm.level_1 = -.8 gm.level_2 = .8 d = self.x.plot(a, gm, bg=self.bg) fnm = "test_vcs_update_array_step_1.png" self.checkImage(fnm) self.x.backend.update_input(d.backend, b(slice(1, 2), slice(1, 2))) fnm = "test_vcs_update_array_step_2.png" self.checkImage(fnm)
def moddir2vectx(m, d): return MV2.multiply(m, MV2.cos(deg2rad(d)))
import vcs,numpy,cdms2,MV2 L=cdms2.createAxis(range(0,360,36)) L.designateLongitude() lat = cdms2.createAxis(range(-90,90,18)) a=numpy.arange(400) a.shape=(2,2,10,10) b=MV2.cos(a)/2. a=MV2.sin(a) t=cdms2.createAxis(range(2)) t.designateTime() t.units="months since 2014" t.id="time" l=cdms2.createAxis(numpy.arange(1,3)*1000.) l.designateLevel() l.units="hPa" l.id="plev" a.setAxis(0,t) a.setAxis(1,l) a.setAxis(2,lat) a.setAxis(3,L) b.setAxisList(a.getAxisList()) x=vcs.init() gm=x.createboxfill() gm.level_1=-.8 gm.level_2=.8 d = x.plot(a,gm) raw_input("Press enter") x.backend.update_input(d.backend,b(slice(1,2),slice(1,2))) raw_input("ok done")
import vcs, numpy, cdms2, MV2 L = cdms2.createAxis(range(0, 360, 36)) L.designateLongitude() lat = cdms2.createAxis(range(-90, 90, 18)) a = numpy.arange(400) a.shape = (2, 2, 10, 10) b = MV2.cos(a) / 2. a = MV2.sin(a) t = cdms2.createAxis(range(2)) t.designateTime() t.units = "months since 2014" t.id = "time" l = cdms2.createAxis(numpy.arange(1, 3) * 1000.) l.designateLevel() l.units = "hPa" l.id = "plev" a.setAxis(0, t) a.setAxis(1, l) a.setAxis(2, lat) a.setAxis(3, L) b.setAxisList(a.getAxisList()) x = vcs.init() gm = x.createboxfill() gm.level_1 = -.8 gm.level_2 = .8 d = x.plot(a, gm) raw_input("Press enter") x.backend.update_input(d.backend, b(slice(1, 2), slice(1, 2))) raw_input("ok done")
def spacevavg(tvarb1, tvarb2, sftlf, model): ''' Given a "root filename" and month/year specifications, vector-average lat/lon arrays in an (amplitude, phase) pair of input data files. Each input data file contains diurnal (24h), semidiurnal (12h) and terdiurnal (8h) Fourier harmonic components of the composite mean day/night cycle. Vector-averaging means we consider the input data to be readings on an 8-, 12- or 24-hour clock and separately average the Cartesian components (called "cosine" and "sine" below). Then the averaged components are combined back into amplitude and phase values and returned. Space-averaging is done globally, as well as separately for land and ocean areas. ''' glolf = cdutil.averager(sftlf, axis='xy') print(' Global mean land fraction = %5.3f' % glolf) outD = {} # Output dictionary to be returned by this function harmonics = [1, 2, 3] for harmonic in harmonics: ampl = tvarb1[harmonic - 1] tmax = tvarb2[harmonic - 1] # print ampl[:, :] # print tmax[:, :] clocktype = 24 / harmonic cosine = MV2.cos(hrs_to_rad(tmax, clocktype)) * ampl # X-component sine = MV2.sin(hrs_to_rad(tmax, clocktype)) * ampl # Y-component print( 'Area-averaging globally, over land only, and over ocean only ...' ) # Average Cartesian components ... cos_avg_glo = cdutil.averager(cosine, axis='xy') sin_avg_glo = cdutil.averager(sine, axis='xy') cos_avg_lnd = cdutil.averager(cosine * sftlf, axis='xy') sin_avg_lnd = cdutil.averager(sine * sftlf, axis='xy') cos_avg_ocn = cos_avg_glo - cos_avg_lnd sin_avg_ocn = sin_avg_glo - sin_avg_lnd # ... normalized by land-sea fraction: cos_avg_lnd /= glolf sin_avg_lnd /= glolf cos_avg_ocn /= (1 - glolf) sin_avg_ocn /= (1 - glolf) # Amplitude and phase: # * 86400 Convert kg/m2/s -> mm/d? amp_avg_glo = MV2.sqrt(sin_avg_glo**2 + cos_avg_glo**2) # * 86400 Convert kg/m2/s -> mm/d? amp_avg_lnd = MV2.sqrt(sin_avg_lnd**2 + cos_avg_lnd**2) # * 86400 Convert kg/m2/s -> mm/d? amp_avg_ocn = MV2.sqrt(sin_avg_ocn**2 + cos_avg_ocn**2) pha_avg_glo = MV2.remainder( rad_to_hrs(MV2.arctan2(sin_avg_glo, cos_avg_glo), clocktype), clocktype) pha_avg_lnd = MV2.remainder( rad_to_hrs(MV2.arctan2(sin_avg_lnd, cos_avg_lnd), clocktype), clocktype) pha_avg_ocn = MV2.remainder( rad_to_hrs(MV2.arctan2(sin_avg_ocn, cos_avg_ocn), clocktype), clocktype) if 'CMCC-CM' in model: # print '** Correcting erroneous time recording in ', rootfname pha_avg_lnd -= 3.0 pha_avg_lnd = MV2.remainder(pha_avg_lnd, clocktype) elif 'BNU-ESM' in model or 'CCSM4' in model or 'CNRM-CM5' in model: # print '** Correcting erroneous time recording in ', rootfname pha_avg_lnd -= 1.5 pha_avg_lnd = MV2.remainder(pha_avg_lnd, clocktype) print( 'Converting singleton transient variables to plain floating-point numbers ...' ) amp_avg_glo = float(amp_avg_glo) pha_avg_glo = float(pha_avg_glo) amp_avg_lnd = float(amp_avg_lnd) pha_avg_lnd = float(pha_avg_lnd) amp_avg_ocn = float(amp_avg_ocn) pha_avg_ocn = float(pha_avg_ocn) print( '%s %s-harmonic amplitude, phase = %7.3f mm/d, %7.3f hrsLST averaged globally' % (monthname, harmonic, amp_avg_glo, pha_avg_glo)) print( '%s %s-harmonic amplitude, phase = %7.3f mm/d, %7.3f hrsLST averaged over land' % (monthname, harmonic, amp_avg_lnd, pha_avg_lnd)) print( '%s %s-harmonic amplitude, phase = %7.3f mm/d, %7.3f hrsLST averaged over ocean' % (monthname, harmonic, amp_avg_ocn, pha_avg_ocn)) # Sub-dictionaries, one for each harmonic component: outD['harmonic' + str(harmonic)] = {} outD['harmonic' + str(harmonic)]['amp_avg_lnd'] = amp_avg_lnd outD['harmonic' + str(harmonic)]['pha_avg_lnd'] = pha_avg_lnd outD['harmonic' + str(harmonic)]['amp_avg_ocn'] = amp_avg_ocn outD['harmonic' + str(harmonic)]['pha_avg_ocn'] = pha_avg_ocn return outD
def harmonic(data, k=3): data = data.reorder('t...') cdutil.setAxisTimeBoundsDaily(data.getTime()) axislist = data.getAxisList() dataid = data.id daily = True monthly = False timeAxis = axislist[0] N = 365. #len(timeAxis) # P = 10. # 10 year, yearly harmonic oscilation # P = 10*12 # 10 year, monthly harmonic oscilation # P = 10*365 # 10 year, daily harmonic oscilation # if P > N: # raise ValueError("P('%d') value should not exceed N(%d)" % (P,N)) if k > N/2: raise ValueError("k value should not exceed (%d) i.e. N/2 value" % (N/2)) if len(timeAxis) > 366: print 'found more than 1 year data.' # y_t = dailyClimatology(data, action='sum') else: y_t = data # end of if len(timeAxis) > 366: Y_0 = cdutil.averager(data, axis='t', action='average', weights='equal') # make memory free del data t = numpy.arange(1, N+1, dtype='float') otheraxis = list(Y_0.shape) ax_product = 1 for ax in otheraxis: ax_product *= ax otheraxis.insert(0,N) t = t.repeat(ax_product).reshape(otheraxis) angle = 2 * math.pi * t/N Y_k = 0. for i in range(1,k+1): kangle = angle*i A_k = (2./N) * cdutil.averager(y_t * numpy.cos(kangle), axis='t', action='sum') B_k = (2./N) * cdutil.averager(y_t * numpy.sin(kangle), axis='t', action='sum') C_k = MV2.sqrt((A_k*A_k) + (B_k*B_k)) # if A_k is positiv, then retain this phase_angle as it is. # phase_angle should be in degrees phase_angle = phase_arc_angle = MV2.arctan(B_k/A_k) # if A_k is zero, then replace phase_angle with pi/2 else retain same phase_angle = MV2.where(MV2.equal(A_k, 0.), math.pi/2.0, phase_arc_angle) # if A_k is negative, then add pi with phase_angle (if it is <= pi ) condition1 = MV2.logical_and(MV2.less(A_k, 0.), MV2.less_equal(phase_arc_angle, math.pi)) phase_angle = MV2.where(condition1, phase_arc_angle+math.pi, phase_arc_angle) # if A_k is negative, then subtract pi from phase_angle (if it is > pi ) condition2 = MV2.logical_and(MV2.less(A_k, 0.), MV2.greater(phase_arc_angle, math.pi)) condition3 = MV2.logical_or(condition1, condition2) phase_angle = MV2.where(condition3, phase_arc_angle-math.pi, phase_arc_angle) # make memory free del phase_arc_angle if daily and not monthly: # subtract 15 days lag to adjust phase_angle w.r.t daily print "Daily Subtraction" phase_angle -= (15.*2*math.pi)/N # end of if daily and not monthly: phase_angle = numpy.array(phase_angle) # phase_angle = numpy.tile(phase_angle, N).reshape(kangle.shape) kangle = numpy.array(kangle) Y_k += C_k * MV2.cos(kangle - phase_angle) # end of for i in range(1,k+1): # add mean to the sum of first k-th harmonic of data Y_k += Y_0 # make memory free del y_t, Y_0 sumOfMean_and_first_k_harmonic = cdms2.createVariable(Y_k, id=dataid) sumOfMean_and_first_k_harmonic.setAxisList(axislist) sumOfMean_and_first_k_harmonic.comments = 'sumOfMean_and_first_%d_harmonic' % k # make memory free del Y_k # return result return sumOfMean_and_first_k_harmonic
def spacevavg(tvarb1, tvarb2, sftlf, model): ''' Given a "root filename" and month/year specifications, vector-average lat/lon arrays in an (amplitude, phase) pair of input data files. Each input data file contains diurnal (24h), semidiurnal (12h) and terdiurnal (8h) Fourier harmonic components of the composite mean day/night cycle. Vector-averaging means we consider the input data to be readings on an 8-, 12- or 24-hour clock and separately average the Cartesian components (called "cosine" and "sine" below). Then the averaged components are combined back into amplitude and phase values and returned. Space-averaging is done globally, as well as separately for land and ocean areas. ''' glolf = cdutil.averager(sftlf, axis='xy') print(' Global mean land fraction = %5.3f' % glolf) outD = {} # Output dictionary to be returned by this function harmonics = [1, 2, 3] for harmonic in harmonics: ampl = tvarb1[harmonic - 1] tmax = tvarb2[harmonic - 1] # print ampl[:, :] # print tmax[:, :] clocktype = 24 / harmonic cosine = MV2.cos(hrs_to_rad(tmax, clocktype)) * ampl # X-component sine = MV2.sin(hrs_to_rad(tmax, clocktype)) * ampl # Y-component print('Area-averaging globally, over land only, and over ocean only ...') # Average Cartesian components ... cos_avg_glo = cdutil.averager(cosine, axis='xy') sin_avg_glo = cdutil.averager(sine, axis='xy') cos_avg_lnd = cdutil.averager(cosine * sftlf, axis='xy') sin_avg_lnd = cdutil.averager(sine * sftlf, axis='xy') cos_avg_ocn = cos_avg_glo - cos_avg_lnd sin_avg_ocn = sin_avg_glo - sin_avg_lnd # ... normalized by land-sea fraction: cos_avg_lnd /= glolf sin_avg_lnd /= glolf cos_avg_ocn /= (1 - glolf) sin_avg_ocn /= (1 - glolf) # Amplitude and phase: # * 86400 Convert kg/m2/s -> mm/d? amp_avg_glo = MV2.sqrt(sin_avg_glo**2 + cos_avg_glo**2) # * 86400 Convert kg/m2/s -> mm/d? amp_avg_lnd = MV2.sqrt(sin_avg_lnd**2 + cos_avg_lnd**2) # * 86400 Convert kg/m2/s -> mm/d? amp_avg_ocn = MV2.sqrt(sin_avg_ocn**2 + cos_avg_ocn**2) pha_avg_glo = MV2.remainder( rad_to_hrs( MV2.arctan2( sin_avg_glo, cos_avg_glo), clocktype), clocktype) pha_avg_lnd = MV2.remainder( rad_to_hrs( MV2.arctan2( sin_avg_lnd, cos_avg_lnd), clocktype), clocktype) pha_avg_ocn = MV2.remainder( rad_to_hrs( MV2.arctan2( sin_avg_ocn, cos_avg_ocn), clocktype), clocktype) if 'CMCC-CM' in model: # print '** Correcting erroneous time recording in ', rootfname pha_avg_lnd -= 3.0 pha_avg_lnd = MV2.remainder(pha_avg_lnd, clocktype) elif 'BNU-ESM' in model or 'CCSM4' in model or 'CNRM-CM5' in model: # print '** Correcting erroneous time recording in ', rootfname pha_avg_lnd -= 1.5 pha_avg_lnd = MV2.remainder(pha_avg_lnd, clocktype) print('Converting singleton transient variables to plain floating-point numbers ...') amp_avg_glo = float(amp_avg_glo) pha_avg_glo = float(pha_avg_glo) amp_avg_lnd = float(amp_avg_lnd) pha_avg_lnd = float(pha_avg_lnd) amp_avg_ocn = float(amp_avg_ocn) pha_avg_ocn = float(pha_avg_ocn) print('%s %s-harmonic amplitude, phase = %7.3f mm/d, %7.3f hrsLST averaged globally' % (monthname, harmonic, amp_avg_glo, pha_avg_glo)) print('%s %s-harmonic amplitude, phase = %7.3f mm/d, %7.3f hrsLST averaged over land' % (monthname, harmonic, amp_avg_lnd, pha_avg_lnd)) print('%s %s-harmonic amplitude, phase = %7.3f mm/d, %7.3f hrsLST averaged over ocean' % (monthname, harmonic, amp_avg_ocn, pha_avg_ocn)) # Sub-dictionaries, one for each harmonic component: outD['harmonic' + str(harmonic)] = {} outD['harmonic' + str(harmonic)]['amp_avg_lnd'] = amp_avg_lnd outD['harmonic' + str(harmonic)]['pha_avg_lnd'] = pha_avg_lnd outD['harmonic' + str(harmonic)]['amp_avg_ocn'] = amp_avg_ocn outD['harmonic' + str(harmonic)]['pha_avg_ocn'] = pha_avg_ocn return outD
import vcs import numpy import cdms2 import MV2 # prepare some data x = numpy.arange(360) # in degrees s = MV2.sin(x / 180. * numpy.pi) c = MV2.cos(x / 180. * numpy.pi) x = cdms2.createAxis(x) # in degrees s.setAxis(0, x) c.setAxis(0, x) canvas = vcs.init() canvas.yxvsx(s, linewidth=2, linecolor="blue", markersize=0) canvas.yxvsx(c, linewidth=2, linecolor="red", markersize=0) canvas.png("plot_sine_cosine_vcs.png") canvas.interact()
def harmonic(data, k=3, time_type='daily', phase_shift=15): """ Inputs : data : climatology data k : Integer no to compute K th harmonic. By default it takes 3. time_type : daily | monthly | full (time type of input climatology) 'daily' -> it returns 365 days harmonic, 'monthly' -> it returns 12 month harmonic, 'full' -> it retuns harmonic for full length of input data. phase_shift : Used to subtract 'phase_shift' days lag to adjust phase_angle w.r.t daily or monthly. By default it takes 15 days lag to adjust phase_angle w.r.t daily data. User can pass None disable this option. Returns : Returns "sum mean of mean and first K th harmonic" of input climatology data. Concept : Earth science data consists of a strong seasonality component as indicated by the cycles of repeated patterns in climate variables such as air pressure, temperature and precipitation. The seasonality forms the strongest signals in this data and in order to find other patterns, the seasonality is removed by subtracting the monthly mean values of the raw data for each month. However since the raw data like air temperature, pressure, etc. are constantly being generated with the help of satellite observations, the climate scientists usually use a moving reference base interval of some years of raw data to calculate the mean in order to generate the anomaly time series and study the changes with respect to that. Fourier series analysis decomposes a signal into an infinite series of harmonic components. Each of these components is comprised initially of a sine wave and a cosine wave of equal integer frequency. These two waves are then combined into a single cosine wave, which has characteristic amplitude (size of the wave) and phase angle (offset of the wave). Convergence has been established for bounded piecewise continuous functions on a closed interval, with special conditions at points of discontinuity. Its convergence has been established for other conditions as well, but these are not relevant to the analysis at hand. Reference: Daniel S Wilks, 'Statistical Methods in the Atmospheric Sciences' second Edition, page no(372-378). Written By : Arulalan.T Date : 16.05.2014 """ data = data.reorder('t...') cdutil.setAxisTimeBoundsDaily(data.getTime()) axislist = data.getAxisList() timeAxis = axislist[0] dataid = data.id if time_type in ['daily']: N = 365.0 # must be float elif time_type[:3] in ['mon']: N = 12.0 # must be float elif time_type in ['full']: N = float(len(timeAxis)) if k > N/2: raise ValueError("k value should not exceed (%d) i.e. N/2 value" % (N/2)) if len(timeAxis) > 366: print 'found more than 1 year data.' raise ValueError("Kindly pass only climatology data") else: y_t = data # end of if len(timeAxis) > 366: Y_0 = cdutil.averager(data, axis='t', action='average', weights='equal') # make memory free del data t = numpy.arange(1, N+1, dtype='float') otheraxis = list(Y_0.shape) ax_product = 1 for ax in otheraxis: ax_product *= ax otheraxis.insert(0,N) t = t.repeat(ax_product).reshape(otheraxis) angle = 2 * math.pi * t/N Y_k = 0. for i in range(1,k+1): kangle = angle*i A_k = (2./N) * cdutil.averager(y_t * numpy.cos(kangle), axis='t', action='sum') B_k = (2./N) * cdutil.averager(y_t * numpy.sin(kangle), axis='t', action='sum') C_k = MV2.sqrt((A_k*A_k) + (B_k*B_k)) # if A_k is positiv, then retain this phase_angle as it is. # phase_angle should be in degrees phase_angle = phase_arc_angle = MV2.arctan(B_k/A_k) # if A_k is zero, then replace phase_angle with pi/2 else retain same phase_angle = MV2.where(MV2.equal(A_k, 0.), math.pi/2.0, phase_arc_angle) # if A_k is negative, then add pi with phase_angle (if it is <= pi ) condition1 = MV2.logical_and(MV2.less(A_k, 0.), MV2.less_equal(phase_arc_angle, math.pi)) phase_angle = MV2.where(condition1, phase_arc_angle+math.pi, phase_arc_angle) # if A_k is negative, then subtract pi from phase_angle (if it is > pi ) condition2 = MV2.logical_and(MV2.less(A_k, 0.), MV2.greater(phase_arc_angle, math.pi)) condition3 = MV2.logical_or(condition1, condition2) phase_angle = MV2.where(condition3, phase_arc_angle-math.pi, phase_arc_angle) # make memory free del phase_arc_angle if phase_shift: # subtract 15 days lag to adjust phase_angle w.r.t daily phase_angle -= (phase_shift *2 * math.pi) / N # end of if daily and not monthly: phase_angle = numpy.array(phase_angle) kangle = numpy.array(kangle) Y_k += C_k * MV2.cos(kangle - phase_angle) # end of for i in range(1,k+1): # add mean to the sum of first k-th harmonic of data Y_k += Y_0 # make memory free del y_t, Y_0 sumOfMean_and_first_k_harmonic = cdms2.createVariable(Y_k, id=dataid) sumOfMean_and_first_k_harmonic.setAxisList(axislist) sumOfMean_and_first_k_harmonic.comments = 'sumOfMean_and_first_%d_harmonic' % k # make memory free del Y_k # return result return sumOfMean_and_first_k_harmonic