def month_numbers(series): n = len(series) values = zeros(n, 'd') for el, i in zip(series, range(n)): t = el.getXString() values[i] = monthlist.index(t[2:5]) out = RegularTimeSeries("/MONTH_NUMBER//////", series.getStartTime().toString(), series.getTimeInterval().toString(), values) out.getAttributes().setYType(series.getAttributes().getYType()) return out
def month_numbers(series): n=len(series) values=zeros(n,'d') for el,i in zip(series,range(n)): t=el.getXString() values[i]=monthlist.index(t[2:5]) out=RegularTimeSeries("/MONTH_NUMBER//////", series.getStartTime().toString(), series.getTimeInterval().toString(), values) out.getAttributes().setYType(series.getAttributes().getYType()) return out
def days_in_month(series): n = len(series) values = zeros(n, 'd') for el, i in zip(series, range(n)): t = el.getXString() m = monthlist.index(t[2:5]) y = int(t[5:9]) values[i] = monthrange(y, m)[1] out = RegularTimeSeries("/DAY_IN_MONTH//////", series.getStartTime().toString(), series.getTimeInterval().toString(), values) out.getAttributes().setYType(series.getAttributes().getYType()) return out
def days_in_month(series): n=len(series) values=zeros(n,'d') for el,i in zip(series,range(n)): t=el.getXString() m=monthlist.index(t[2:5]) y=int(t[5:9]) values[i]=monthrange(y,m)[1] out=RegularTimeSeries("/DAY_IN_MONTH//////", series.getStartTime().toString(), series.getTimeInterval().toString(), values) out.getAttributes().setYType(series.getAttributes().getYType()) return out
def replace_vamp(non_pulse, pulse, include_shoulder=0): """Creates a new series based on non_pulse values, replacing them with pulse values during the VAMP season (April 15-May 15 inclusive) or April1 - May 31 if include_shoulder is set to true (1) Arguments: non_pulse: monthly or daily series of values to use for non-pulse pulse: pulse values, must have same start, length, interval as non-pulse Output: New series with non-pulse values replaced by pulse during vamp """ if not isinstance(non_pulse, RegularTimeSeries): raise TypeError("Non-Pulse flow must be regular time series") if not isinstance(pulse, RegularTimeSeries): raise TypeError("Pulse flow must be regular time series") if include_shoulder: first_april_day = 1 last_may_day = 31 else: first_april_day = 15 last_may_day = 15 #if non_pulse.getTimeInterval() == timeinterval("1MON"): non_pulse = interpolate(non_pulse, "1DAY") #if pulse.getTimeInterval() == timeinterval("1MON"): pulse = interpolate(pulse, "1DAY") if non_pulse.getStartTime() != pulse.getStartTime() or \ len(non_pulse) != len(pulse): raise ValueError("Pulse and Non-pulse must have the same start time," " interval and length") values = zeros(len(non_pulse), 'd') for np, p, i in zip(non_pulse, pulse, range(len(values))): values[i] = np.getY() xstr = np.getXString() day, month = int(xstr[0:2]), xstr[2:5] if month == "APR" and day >= first_april_day: values[i] = p.getY() elif month == "MAY" and day <= last_may_day: values[i] = p.getY() out = RegularTimeSeries("/vamp//////", non_pulse.getStartTime().toString(), non_pulse.getTimeInterval().toString(), values) out.getAttributes().setYUnits("CFS") out.getAttributes().setYType("PER-AVER") return out
def replace_vamp(non_pulse,pulse,include_shoulder=0): """Creates a new series based on non_pulse values, replacing them with pulse values during the VAMP season (April 15-May 15 inclusive) or April1 - May 31 if include_shoulder is set to true (1) Arguments: non_pulse: monthly or daily series of values to use for non-pulse pulse: pulse values, must have same start, length, interval as non-pulse Output: New series with non-pulse values replaced by pulse during vamp """ if not isinstance(non_pulse,RegularTimeSeries): raise TypeError("Non-Pulse flow must be regular time series") if not isinstance(pulse,RegularTimeSeries): raise TypeError("Pulse flow must be regular time series") if include_shoulder: first_april_day=1 last_may_day=31 else: first_april_day=15 last_may_day=15 #if non_pulse.getTimeInterval() == timeinterval("1MON"): non_pulse=interpolate(non_pulse,"1DAY") #if pulse.getTimeInterval() == timeinterval("1MON"): pulse=interpolate(pulse,"1DAY") if non_pulse.getStartTime() != pulse.getStartTime() or \ len(non_pulse) != len(pulse): raise ValueError("Pulse and Non-pulse must have the same start time," " interval and length") values=zeros(len(non_pulse),'d') for np,p,i in zip(non_pulse,pulse,range(len(values))): values[i]=np.getY() xstr=np.getXString() day,month=int(xstr[0:2]),xstr[2:5] if month=="APR" and day >= first_april_day: values[i]=p.getY() elif month=="MAY" and day <= last_may_day: values[i]=p.getY() out=RegularTimeSeries("/vamp//////", non_pulse.getStartTime().toString(), non_pulse.getTimeInterval().toString(),values) out.getAttributes().setYUnits("CFS") out.getAttributes().setYType("PER-AVER") return out
def ts_where(criteria,trueval,falseval): if not( len(criteria) == len(trueval) and \ len(criteria) == len(falseval) ): raise ValueError("Criteria (len %s), trueval (len %s) and falseval (len %s)" " must be the same length" % (len(criteria),len(trueval),len(falseval))) n=len(criteria) values=zeros(n,'d') for c,t,f,i in zip(criteria,trueval,falseval,range(n)): if filter.isAcceptable(c): if c.getY(): values[i]=t.getY() else: values[i]=f.getY() else: values[i]=NA_VAL out=RegularTimeSeries("/WHERE//////",criteria.getStartTime().toString(), criteria.getTimeInterval().toString(),values) out.getAttributes().setYType(trueval.getAttributes().getYType()) return out
def ts_where(criteria, trueval, falseval): if not( len(criteria) == len(trueval) and \ len(criteria) == len(falseval) ): raise ValueError( "Criteria (len %s), trueval (len %s) and falseval (len %s)" " must be the same length" % (len(criteria), len(trueval), len(falseval))) n = len(criteria) values = zeros(n, 'd') for c, t, f, i in zip(criteria, trueval, falseval, range(n)): if filter.isAcceptable(c): if c.getY(): values[i] = t.getY() else: values[i] = f.getY() else: values[i] = NA_VAL out = RegularTimeSeries("/WHERE//////", criteria.getStartTime().toString(), criteria.getTimeInterval().toString(), values) out.getAttributes().setYType(trueval.getAttributes().getYType()) return out
def ECEst(stage, ndo, so, sb, beta, npow1, npow2, g0, zrms, c): """ Estimate 15min EC at the boundary. Inputs: stage astronomical tide estimate. Only 15min data are acceptable ndo ndo estimate -- e.g., from CALSIM """ import interpolate from vista.set import Units if not isinstance(stage,RegularTimeSeries) or \ not isinstance(ndo,RegularTimeSeries): raise "stage and ndo must be RegularTimeSeries" if ndo.getTimeInterval().toString() == "1DAY": ndo = interpolate.spline(ndo, "15MIN", 0.5) << 95 elif ndo.getTimeInterval().toString() != "15MIN": raise "ndo must be a one day or 15 minute series" if not stage.getTimeInterval().toString() == "15MIN": raise "stage must be an hourly or 15 minute series" # if ndo.getTimeInterval().toString() != stage.getTimeInterval().toString(): raise "stage and ndo must have the same window" # #if not len(c) ==9: # raise "Wrong number (%s) of coefficients in the array c" % len(c) if (first_missing(ndo)) >= 0: raise "missing data not allowed in ndo. First missing data at index: %s" % first_missing( ndo) if (first_missing(stage)) >= 0: raise "missing data not allowed in stage. First missing data at index: %s" % first_missing( stage) newstart = ndo.getStartTime() - "21HOURS" newend = ndo.getEndTime() - "3HOURS" if (stage.getStartTime().getTimeInMinutes() - newstart.getTimeInMinutes() > 0): print "Stage record starts %s and NDO starts %s" % ( stage.getStartTime().toString(), ndo.getStartTime().toString()) raise "stage record must begin at least 21 hours before ndo" if (newend.getTimeInMinutes() - stage.getEndTime().getTimeInMinutes() > 0): raise "stage record must end no more than 3 hours before end of ndo" ztw = timewindow(newstart.toString() + ' - ' + newend.toString()) z = stage.createSlice(ztw) g = gCalc(ndo, beta, g0) # writedss("planning_ec_input.dss","/CALC/RSAC054/G//15MIN/CALC",g) # for debug zarr = z.getYArray() giter = g.getIterator() ec = zeros(g.size(), 'd') ec = map(lambda x: -901.0, ec) zrmsiter = zrms.getIterator() i = 0 while (not giter.atEnd()): gval = giter.getElement().getY() zrmsval = zrmsiter.getElement().getY() ecfrac = gval * c[0] + 1.1 * gval**npow1 * ( c[1] * zarr[i + 72] + c[2] * zarr[i + 60] + c[3] * zarr[i + 48] + c[4] * zarr[i + 36] + c[5] * zarr[i + 24] + c[6] * zarr[i + 12] + c[7] * zarr[i]) ec[i] = max(200, exp(ecfrac) * (so - sb) + sb) zrmsiter.advance() giter.advance() i = i + 1 # ec needs to be set umhos/cm rts = RegularTimeSeries("/ECest//////", g.getStartTime().toString(), g.getTimeInterval().toString(), ec) rts.getAttributes().setYUnits(Units.UMHOS_CM) return [rts, gval]
def gCalcFlatQ(ndo, beta, g0, out="inst"): """ Calculates antecedent outflow from ndo based on the flat ndo assumption in the g documentation. In this case, the integration of g is exact rather than numeric, but the approximation to ndo is a series of flat lines. In the case of daily data this is probably acceptable. In the case of monthly data it leads to large errors, though it is common Arguments: ndo: a regular time series. Must be 1DAY, 1MONTH g0: initial condition. If g0 is not given it is equal to ndo at the first time step. beta: g-model parameter. out: must be "inst" to calculate instantaneous values of g or "ave" to calculate averages over the time step. Output: g: a regular time series, same sampling rate as input with the same start time as ndo, ending at the end of ndo or the first piece of bad data in ndo. """ if ndo.getTimeInterval().toString( ) != "1DAY" | ndo.getTimeInterval().toString() != "1MONTH": raise "Time step for input must be 1DAY or 1MONTH" dsi = ndo.getIterator() nstep = ndo.size() g = zeros(nstep, 'd') g = map(lambda x: -901.0, g) bdt = beta / dt if g0 == None: g[0] = q[0] else: g[0] = g0 atend = 0 i = 1 if out[:4] == "inst": while atend == 0: el = dsi.getElement() if Constants.DEFAULT_FLAG_FILTER.isAcceptable(el): q = el.getY() g[i] = q / (1 + (q / g[i - 1] - 1) * exp(-q / bdt)) i = i + 1 if not dsi.atEnd(): dsi.advance() else: atend = 1 else: atend = 1 elif out[:3] == "ave": while atend == 0: el = dsi.getElement() if Constants.DEFAULT_FLAG_FILTER.isAcceptable(el): q = el.getY() g[i] = q / (1 + (q / g[i - 1] - 1) * exp(-q / bdt)) i = i + 1 if not dsi.atEnd(): dsi.advance() else: atend = 1 else: atend = 1 else: raise "Argument out must be either \"inst\" or \"ave\")" rts = RegularTimeSeries("gcalc", ndo.getStartTime().toString(), ndo.getTimeInterval(), g) if out[:4] == "inst": raise "dummy exception" if out[:3] == "ave": rts.getAttributes().setXType("PER-VAL") return rts
def ECEst(stage, ndo, beta, npow1, npow2,g0=None, zrms=None, c=getMTZCoef()): """ Estimate 15min EC at the boundary. Inputs: stage astronomical tide estimate. Only 15min data are acceptable ndo ndo estimate -- e.g., from CALSIM """ import interpolate from vista.set import Units if not isinstance(stage,RegularTimeSeries) or \ not isinstance(ndo,RegularTimeSeries): raise "stage and ndo must be RegularTimeSeries" if ndo.getTimeInterval().toString() == "1DAY": ndo=interpolate.spline(ndo,"15MIN",0.5) << 95 elif ndo.getTimeInterval().toString()!= "15MIN": raise "ndo must be a one day or 15 minute series" if not stage.getTimeInterval().toString() == "15MIN": raise "stage must be an hourly or 15 minute series" # if ndo.getTimeInterval().toString() != stage.getTimeInterval().toString(): raise "stage and ndo must have the same window" # #if not len(c) ==9: # raise "Wrong number (%s) of coefficients in the array c" % len(c) if (first_missing(ndo)) >= 0: raise "missing data not allowed in ndo. First missing data at index: %s" % first_missing(ndo) if (first_missing(stage)) >= 0: raise "missing data not allowed in stage. First missing data at index: %s" % first_missing(stage) newstart=ndo.getStartTime() - "21HOURS" newend =ndo.getEndTime() - "3HOURS" if (stage.getStartTime().getTimeInMinutes() - newstart.getTimeInMinutes() > 0): print "Stage record starts %s and NDO starts %s" % (stage.getStartTime().toString(),ndo.getStartTime().toString()) raise "stage record must begin at least 21 hours before ndo" if (newend.getTimeInMinutes() - stage.getEndTime().getTimeInMinutes() > 0): raise "stage record must end no more than 3 hours before end of ndo" ztw=timewindow(newstart.toString()+' - '+newend.toString()) z=stage.createSlice(ztw) g=gCalc(ndo,beta,g0) zarr=z.getYArray() giter=g.getIterator() ec=zeros(g.size(),'d') ec=map(lambda x: -901.0, ec) so=32797 #ocean salinity parameter for gmodel sb=200 #river salinity parameter for gmodel zrmsiter=zrms.getIterator() i=0 while (not giter.atEnd()): gval=giter.getElement().getY() zrmsval=zrmsiter.getElement().getY() ecfrac = c[0] + gval*c[1] + 1.1*gval**npow1*(c[2]*zarr[i+72] + c[3]*zarr[i+60] + c[4]*zarr[i+48] + c[5]*zarr[i+36] + c[6]*+zarr[i+24] + c[7]*zarr[i+12] + c[8]*zarr[i])-0.1 #+ c[9]*zrmsval ec[i]=max(200,exp(ecfrac)*(so-sb) + sb) #ec[i]=max((1+ecfrac)*(so-sb)+sb,200) zrmsiter.advance() giter.advance() i=i+1 # ec needs to be set umhos/cm rts = RegularTimeSeries("/ECest//////",g.getStartTime().toString(),g.getTimeInterval().toString(),ec) rts.getAttributes().setYUnits(Units.UMHOS_CM) return [rts,gval]
def gCalcFlatQ(ndo, beta, g0,out = "inst"): """ Calculates antecedent outflow from ndo based on the flat ndo assumption in the g documentation. In this case, the integration of g is exact rather than numeric, but the approximation to ndo is a series of flat lines. In the case of daily data this is probably acceptable. In the case of monthly data it leads to large errors, though it is common Arguments: ndo: a regular time series. Must be 1DAY, 1MONTH g0: initial condition. If g0 is not given it is equal to ndo at the first time step. beta: g-model parameter. out: must be "inst" to calculate instantaneous values of g or "ave" to calculate averages over the time step. Output: g: a regular time series, same sampling rate as input with the same start time as ndo, ending at the end of ndo or the first piece of bad data in ndo. """ if ndo.getTimeInterval().toString() != "1DAY" | ndo.getTimeInterval().toString() != "1MONTH": raise "Time step for input must be 1DAY or 1MONTH" dsi=ndo.getIterator() nstep=ndo.size() g=zeros(nstep,'d') g=map(lambda x: -901.0, g) bdt=beta/dt if g0==None: g[0]=q[0] else: g[0]=g0 atend=0 i=1 if out[:4] == "inst": while atend == 0: el=dsi.getElement() if Constants.DEFAULT_FLAG_FILTER.isAcceptable(el): q=el.getY() g[i] = q/(1+(q/g[i-1] -1)*exp(-q/bdt)) i=i+1 if not dsi.atEnd(): dsi.advance() else: atend=1 else: atend=1 elif out[:3]=="ave": while atend == 0: el=dsi.getElement() if Constants.DEFAULT_FLAG_FILTER.isAcceptable(el): q=el.getY() g[i] = q/(1+(q/g[i-1] -1)*exp(-q/bdt)) i=i+1 if not dsi.atEnd(): dsi.advance() else: atend=1 else: atend=1 else: raise "Argument out must be either \"inst\" or \"ave\")" rts = RegularTimeSeries("gcalc", ndo.getStartTime().toString(), ndo.getTimeInterval(),g) if out[:4] == "inst": raise "dummy exception" if out[:3]=="ave": rts.getAttributes().setXType("PER-VAL") return rts