Пример #1
0
 def getStations(self):
    lat  = Common.clean(self._file.variables["Lat"])
    lon  = Common.clean(self._file.variables["Lon"])
    id   = Common.clean(self._file.variables["Location"])
    elev = Common.clean(self._file.variables["Elev"])
    stations = list()
    for i in range(0, lat.shape[0]):
       station = Station.Station(id[i], lat[i], lon[i], elev[i])
       stations.append(station)
    return stations
Пример #2
0
 def setAggregator(self, name):
    self._aggregatorName = name
    if(name == "mean"):
       self._aggregator = np.mean
    elif(name == "median"):
       self._aggregator = np.median
    elif(name == "min"):
       self._aggregator = np.min
    elif(name == "max"):
       self._aggregator = np.max
    elif(name == "std"):
       self._aggregator = np.std
    elif(name == "range"):
       self._aggregator = Common.nprange
    else:
       Common.error("Invalid aggregator")
Пример #3
0
   def computeCore(self, data, tRange):
      if(tRange is None):
         Common.error("Metric " + self.getClassName() + " requires '-r <threshold>'")
      [obs,fcst] = data.getScores(["obs", "fcst"])
      value = np.nan
      if(len(fcst) > 0):
         # Compute frequencies
         a    = np.ma.sum((self.within(fcst,tRange)) & (self.within(obs, tRange))) # Hit
         b    = np.ma.sum((self.within(fcst,tRange)) & (self.within(obs, tRange)==0)) # FA
         c    = np.ma.sum((self.within(fcst,tRange)==0) & (self.within(obs, tRange))) # Miss
         d    = np.ma.sum((self.within(fcst,tRange)==0) & (self.within(obs, tRange)==0)) # CR
         value = self.calc(a, b, c, d)
         if(np.isinf(value)):
            value = np.nan

      return value
Пример #4
0
 def computeCore(self, data, tRange):
    [obsP, p] = Bs.getP(data, tRange)
    bs = np.nan*np.zeros(len(p), 'float')
    meanObs = np.mean(obsP)
    for i in range(0, len(self._edges)-1):
       I = np.where((p >= self._edges[i]) & (p < self._edges[i+1]))[0]
       if(len(I) > 0):
          meanObsI = np.mean(obsP[I])
          bs[I] = (meanObsI - meanObs)**2
    return Common.nanmean(bs)
Пример #5
0
   def computeCore(self, data, tRange):
      [obsP,p] = Bs.getP(data, tRange)

      # Break p into bins, and comute reliability
      bs = np.nan*np.zeros(len(p), 'float')
      for i in range(0, len(self._edges)-1):
         I = np.where((p >= self._edges[i]) & (p < self._edges[i+1]))[0]
         if(len(I) > 0):
            meanObsI = np.mean(obsP[I])
            bs[I] = (np.mean(p[I]) - meanObsI)**2
      return Common.nanmean(bs)
Пример #6
0
   def computeCore(self, data, tRange):
      [obsP,p] = Bs.getP(data, tRange)
      bs = np.nan*np.zeros(len(p), 'float')
      for i in range(0, len(self._edges)-1):
         I = np.where((p >= self._edges[i]) & (p < self._edges[i+1]))[0]
         if(len(I) > 0):
            bs[I] = (np.mean(p[I]) - obsP[I])**2
      bs   = Common.nanmean(bs)
      bsunc = np.mean(obsP)*(1-np.mean(obsP))
      if(bsunc == 0):
         bss = np.nan
      else:
         bss = (bsunc - bs)/bsunc

      return bss
Пример #7
0
   def computeCore(self, data, tRange):
      # Compute probabilities based on thresholds
      p0 = 0
      p1 = 1
      if(tRange[0] != -np.inf and tRange[1] != np.inf):
         var0 = data.getPvar(tRange[0])
         var1 = data.getPvar(tRange[1])
         [obs, p0, p1] = data.getScores(["obs", var0, var1])
      elif(tRange[0] != -np.inf):
         var0 = data.getPvar(tRange[0])
         [obs, p0] = data.getScores(["obs", var0])
      elif(tRange[1] != np.inf):
         var1 = data.getPvar(tRange[1])
         [obs, p1] = data.getScores(["obs", var1])
      obsP = self.within(obs, tRange)
      p    = p1 - p0 # Prob of obs within range
      bs = np.nan*np.zeros(len(p), 'float')

      # Split into bins and compute Brier score on each bin
      for i in range(0, len(self._edges)-1):
         I = np.where((p >= self._edges[i]) & (p < self._edges[i+1]))[0]
         if(len(I) > 0):
            bs[I] = (np.mean(p[I]) - obsP[I])**2
      return Common.nanmean(bs)
Пример #8
0
 def test_simple(self):
    self.assertEqual([2], Common.parseNumbers("2"))
    with self.assertRaises(SystemExit):
       Common.parseNumbers("test")
Пример #9
0
 def test_simple(self):
    self.assertEqual(20150207, Common.getDate(20150206, 1))
    self.assertEqual(20150205, Common.getDate(20150206, -1))
    self.assertEqual(20150215, Common.getDate(20150210, 5))
Пример #10
0
 def test_mix(self):
    self.assertEqual([3,4,3,2,3,4,5], Common.parseNumbers("3:4,3,2:5"))
    with self.assertRaises(SystemExit):
       Common.parseNumbers("2,5:8,3,test")
       Common.parseNumbers("2,5:8,test,5")
       Common.parseNumbers("2,5:test,3,5")
       Common.parseNumbers("2,5:test,3,5")
       Common.parseNumbers("2,test:8,3,5")
       Common.parseNumbers("test,5:8,3,5")
Пример #11
0
 def test_vectorInc(self):
    self.assertEqual([2,5,8], Common.parseNumbers("2:3:8"))
    self.assertEqual([2,5], Common.parseNumbers("2:3:7"))
    self.assertEqual([], Common.parseNumbers("2:-1:7"))
    self.assertEqual([2,1,0], Common.parseNumbers("2:-1:0"))
    self.assertEqual([8,5,2], Common.parseNumbers("8:-3:0"))
    with self.assertRaises(SystemExit):
       Common.parseNumbers("2:3:test")
       Common.parseNumbers("test:3:5")
       Common.parseNumbers("2:test:5")
Пример #12
0
def run(argv):
    ############
    # Defaults #
    ############
    ifiles = list()
    ofile = None
    metric = None
    locations = None
    latlonRange = None
    training = 0
    thresholds = None
    dates = None
    climFile = None
    climType = "subtract"
    leg = None
    ylabel = None
    xlabel = None
    title = None
    offsets = None
    xdim = None
    sdim = None
    figSize = None
    dpi = 100
    showText = False
    showMap = False
    noMargin = False
    binType = None
    markerSize = None
    lineWidth = None
    tickFontSize = None
    labFontSize = None
    legFontSize = None
    type = "plot"
    XRotation = None
    MajorLength = None
    MinorLength = None
    MajorWidth = None
    Bottom = None
    Top = None
    Right = None
    Left = None
    Pad = None
    showPerfect = None
    cType = "mean"
    doHist = False
    doSort = False
    doAcc = False
    xlim = None
    ylim = None
    clim = None
    version = None

    # Read command line arguments
    i = 1
    while (i < len(argv)):
        arg = argv[i]
        if (arg[0] == '-'):
            # Process option
            if (arg == "-nomargin"):
                noMargin = True
            elif (arg == "--version"):
                version = True
            elif (arg == "-sp"):
                showPerfect = True
            elif (arg == "-hist"):
                doHist = True
            elif (arg == "-acc"):
                doAcc = True
            elif (arg == "-sort"):
                doSort = True
            else:
                if (arg == "-f"):
                    ofile = argv[i + 1]
                elif (arg == "-l"):
                    locations = Common.parseNumbers(argv[i + 1])
                elif (arg == "-llrange"):
                    latlonRange = Common.parseNumbers(argv[i + 1])
                elif (arg == "-t"):
                    training = int(argv[i + 1])
                elif (arg == "-x"):
                    xdim = argv[i + 1]
                elif (arg == "-o"):
                    offsets = Common.parseNumbers(argv[i + 1])
                elif (arg == "-leg"):
                    leg = unicode(argv[i + 1], 'utf8')
                elif (arg == "-ylabel"):
                    ylabel = unicode(argv[i + 1], 'utf8')
                elif (arg == "-xlabel"):
                    xlabel = unicode(argv[i + 1], 'utf8')
                elif (arg == "-title"):
                    title = unicode(argv[i + 1], 'utf8')
                elif (arg == "-b"):
                    binType = argv[i + 1]
                elif (arg == "-type"):
                    type = argv[i + 1]
                elif (arg == "-fs"):
                    figSize = argv[i + 1]
                elif (arg == "-dpi"):
                    dpi = int(argv[i + 1])
                elif (arg == "-d"):
                    # Either format is ok:
                    # -d 20150101 20150103
                    # -d 20150101:20150103
                    if (i + 2 < len(argv) and argv[i + 2].isdigit()):
                        dates = Common.parseNumbers(
                            "%s:%s" % (argv[i + 1], argv[i + 2]), True)
                        i = i + 1
                    else:
                        dates = Common.parseNumbers(argv[i + 1], True)
                elif (arg == "-c"):
                    climFile = argv[i + 1]
                    climType = "subtract"
                elif (arg == "-C"):
                    climFile = argv[i + 1]
                    climType = "divide"
                elif (arg == "-xlim"):
                    xlim = Common.parseNumbers(argv[i + 1])
                elif (arg == "-ylim"):
                    ylim = Common.parseNumbers(argv[i + 1])
                elif (arg == "-clim"):
                    clim = Common.parseNumbers(argv[i + 1])
                elif (arg == "-s"):
                    sdim = argv[i + 1]
                elif (arg == "-ct"):
                    cType = argv[i + 1]
                elif (arg == "-r"):
                    thresholds = Common.parseNumbers(argv[i + 1])
                elif (arg == "-ms"):
                    markerSize = float(argv[i + 1])
                elif (arg == "-lw"):
                    lineWidth = float(argv[i + 1])
                elif (arg == "-tickfs"):
                    tickFontSize = float(argv[i + 1])
                elif (arg == "-labfs"):
                    labFontSize = float(argv[i + 1])
                elif (arg == "-legfs"):
                    legFontSize = float(argv[i + 1])
                elif (arg == "-xrot"):
                    XRotation = float(argv[i + 1])
                elif (arg == "-majlth"):
                    MajorLength = float(argv[i + 1])
                elif (arg == "-minlth"):
                    MinorLength = float(argv[i + 1])
                elif (arg == "-majwid"):
                    MajorWidth = float(argv[i + 1])
                elif (arg == "-bot"):
                    Bottom = float(argv[i + 1])
                elif (arg == "-top"):
                    Top = float(argv[i + 1])
                elif (arg == "-right"):
                    Right = float(argv[i + 1])
                elif (arg == "-left"):
                    Left = float(argv[i + 1])
                elif (arg == "-pad"):
                    Pad = argv[i + 1]
                elif (arg == "-m"):
                    metric = argv[i + 1]
                else:
                    Common.error("Flag '" + argv[i] + "' not recognized")
                i = i + 1
        else:
            ifiles.append(argv[i])
        i = i + 1

    if (version):
        print "Version: " + Version.__version__
        return

    # Deal with legend entries
    if (leg != None):
        leg = leg.split(',')
        for i in range(0, len(leg)):
            leg[i] = leg[i].replace('_', ' ')

    if (latlonRange != None and len(latlonRange) != 4):
        Common.error("-llRange <values> must have exactly 4 values")

    if (len(ifiles) > 0):
        data = Data.Data(ifiles,
                         clim=climFile,
                         climType=climType,
                         dates=dates,
                         offsets=offsets,
                         locations=locations,
                         latlonRange=latlonRange,
                         training=training)
    else:
        data = None
    if (len(argv) == 1 or len(ifiles) == 0 or metric == None):
        showDescription(data)
        return

    if (figSize != None):
        figSize = figSize.split(',')
        if (len(figSize) != 2):
            print "-fs figSize must be in the form: width,height"
            sys.exit(1)

    m = None

    # Handle special plots
    if (doHist):
        pl = Output.Hist(metric)
    elif (doSort):
        pl = Output.Sort(metric)
    elif (metric == "pithist"):
        m = Metric.Pit("pit")
        pl = Output.PitHist(m)
    elif (metric == "obsfcst"):
        pl = Output.ObsFcst()
    elif (metric == "timeseries"):
        pl = Output.TimeSeries()
    elif (metric == "qq"):
        pl = Output.QQ()
    elif (metric == "cond"):
        pl = Output.Cond()
    elif (metric == "against"):
        pl = Output.Against()
    elif (metric == "count"):
        pl = Output.Count()
    elif (metric == "scatter"):
        pl = Output.Scatter()
    elif (metric == "change"):
        pl = Output.Change()
    elif (metric == "spreadskill"):
        pl = Output.SpreadSkill()
    elif (metric == "taylor"):
        pl = Output.Taylor()
    elif (metric == "error"):
        pl = Output.Error()
    elif (metric == "freq"):
        pl = Output.Freq()
    elif (metric == "droc"):
        pl = Output.DRoc()
    elif (metric == "droc0"):
        pl = Output.DRoc0()
    elif (metric == "drocnorm"):
        pl = Output.DRocNorm()
    elif (metric == "reliability"):
        pl = Output.Reliability()
    elif (metric == "invreliability"):
        pl = Output.InvReliability()
    elif (metric == "igncontrib"):
        pl = Output.IgnContrib()
    elif (metric == "marginal"):
        pl = Output.Marginal()
    else:
        # Standard plots
        '''
      # Attempt at automating
      metrics = Metric.getAllMetrics()
      m = None
      for mm in metrics:
         if(metric == mm[0].lower() and mm[1].isStandard()):
            m = mm[1]()
            break
      if(m == None):
         m = Metric.Default(metric)
         '''

        # Determine metric
        if (metric == "rmse"):
            m = Metric.Rmse()
        elif (metric == "obs"):
            m = Metric.Obs()
        elif (metric == "fcst"):
            m = Metric.Fcst()
        elif (metric == "rmsf"):
            m = Metric.Rmsf()
        elif (metric == "crmse"):
            m = Metric.Crmse()
        elif (metric == "cmae"):
            m = Metric.Cmae()
        elif (metric == "dmb"):
            m = Metric.Dmb()
        elif (metric == "num"):
            m = Metric.Num()
        elif (metric == "corr"):
            m = Metric.Corr()
        elif (metric == "rankcorr"):
            m = Metric.RankCorr()
        elif (metric == "kendallcorr"):
            m = Metric.KendallCorr()
        elif (metric == "bias"):
            m = Metric.Bias()
        elif (metric == "ef"):
            m = Metric.Ef()
        elif (metric == "stderror"):
            m = Metric.StdError()
        elif (metric == "mae"):
            m = Metric.Mae()
        # Contingency metrics
        elif (metric == "ets"):
            m = Metric.Ets()
        elif (metric == "threat"):
            m = Metric.Threat()
        elif (metric == "pc"):
            m = Metric.Pc()
        elif (metric == "diff"):
            m = Metric.Diff()
        elif (metric == "edi"):
            m = Metric.Edi()
        elif (metric == "sedi"):
            m = Metric.Sedi()
        elif (metric == "eds"):
            m = Metric.Eds()
        elif (metric == "seds"):
            m = Metric.Seds()
        elif (metric == "biasfreq"):
            m = Metric.BiasFreq()
        elif (metric == "hss"):
            m = Metric.Hss()
        elif (metric == "baserate"):
            m = Metric.BaseRate()
        elif (metric == "yulesq"):
            m = Metric.YulesQ()
        elif (metric == "or"):
            m = Metric.Or()
        elif (metric == "lor"):
            m = Metric.Lor()
        elif (metric == "yulesq"):
            m = Metric.YulesQ()
        elif (metric == "kss"):
            m = Metric.Kss()
        elif (metric == "hit"):
            m = Metric.Hit()
        elif (metric == "miss"):
            m = Metric.Miss()
        elif (metric == "fa"):
            m = Metric.Fa()
        elif (metric == "far"):
            m = Metric.Far()
        # Other threshold
        elif (metric == "bs"):
            m = Metric.Bs()
        elif (metric == "bss"):
            m = Metric.Bss()
        elif (metric == "bsrel"):
            m = Metric.BsRel()
        elif (metric == "bsunc"):
            m = Metric.BsUnc()
        elif (metric == "bsres"):
            m = Metric.BsRes()
        elif (metric == "ign0"):
            m = Metric.Ign0()
        elif (metric == "spherical"):
            m = Metric.Spherical()
        elif (metric == "within"):
            m = Metric.Within()
        # Probabilistic
        elif (metric == "pit"):
            m = Metric.Mean(Metric.Pit())
        elif (metric == "pitdev"):
            m = Metric.PitDev()
        elif (metric == "marginalratio"):
            m = Metric.MarginalRatio()
        # Default
        else:
            m = Metric.Mean(Metric.Default(metric))

        m.setAggregator(cType)

        # Output type
        if (type == "plot" or type == "text" or type == "map"
                or type == "maprank"):
            pl = Output.Default(m)
            pl.setShowAcc(doAcc)
        else:
            Common.error("Type not understood")

    # Rest dimension of '-x' is not allowed
    if (xdim != None and not pl.supportsX()):
        Common.warning(metric + " does not support -x. Ignoring it.")
        xdim = None

    # Reset dimension if 'threshold' is not allowed
    if (xdim == "threshold"
            and ((not pl.supportsThreshold()) or (not m.supportsThreshold()))):
        Common.warning(metric +
                       " does not support '-x threshold'. Ignoring it.")
        thresholds = None
        xdim = None

    # Create thresholds if needed
    if ((thresholds == None) and (pl.requiresThresholds() or
                                  (m != None and m.requiresThresholds()))):
        data.setAxis("none")
        obs = data.getScores("obs")[0]
        fcst = data.getScores("fcst")[0]
        smin = min(min(obs), min(fcst))
        smax = max(max(obs), max(fcst))
        thresholds = np.linspace(smin, smax, 10)
        Common.warning(
            "Missing '-r <thresholds>'. Automatically setting thresholds.")

    # Set plot parameters
    if (markerSize != None):
        pl.setMarkerSize(markerSize)
    if (lineWidth != None):
        pl.setLineWidth(lineWidth)
    if (labFontSize != None):
        pl.setLabFontSize(labFontSize)
    if (legFontSize != None):
        pl.setLegFontSize(legFontSize)
    if (tickFontSize != None):
        pl.setTickFontSize(tickFontSize)
    if (XRotation != None):
        pl.setXRotation(XRotation)
    if (MajorLength != None):
        pl.setMajorLength(MajorLength)
    if (MinorLength != None):
        pl.setMinorLength(MinorLength)
    if (MajorWidth != None):
        pl.setMajorWidth(MajorWidth)
    if (Bottom != None):
        pl.setBottom(Bottom)
    if (Top != None):
        pl.setTop(Top)
    if (Right != None):
        pl.setRight(Right)
    if (Left != None):
        pl.setLeft(Left)
    if (Pad != None):
        pl.setPad(None)
    if (binType != None):
        pl.setBinType(binType)
    if (showPerfect != None):
        pl.setShowPerfect(showPerfect)
    if (xlim != None):
        pl.setXLim(xlim)
    if (ylim != None):
        pl.setYLim(ylim)
    if (clim != None):
        pl.setCLim(clim)
    pl.setFilename(ofile)
    pl.setThresholds(thresholds)
    pl.setLegend(leg)
    pl.setFigsize(figSize)
    pl.setDpi(dpi)
    pl.setAxis(xdim)
    pl.setShowMargin(not noMargin)
    pl.setYlabel(ylabel)
    pl.setXlabel(xlabel)
    pl.setTitle(title)

    if (type == "text"):
        pl.text(data)
    elif (type == "map"):
        pl.map(data)
    elif (type == "maprank"):
        pl.setShowRank(True)
        pl.map(data)
    else:
        pl.plot(data)
Пример #13
0
 def getScores(self, metric):
    metric = self._toPvarComps(metric)
    temp = Common.clean(self._file.variables[metric])
    return temp
Пример #14
0
 def getScores(self, metric):
    if(metric == "obs"):
       return self._obs
    elif(metric == "fcst"):
       return self._fcst
    elif(metric == "pit"):
       if(self._pit is None):
          Common.error("File does not contain 'pit'")
       return self._pit
    elif(metric[0] == "p"):
       threshold = float(metric[1:])
       I = np.where(abs(self._thresholds - threshold) < 0.0001)[0]
       if(len(I) == 0):
          Common.error("Cannot find " + metric)
       elif(len(I) > 1):
          Common.error("Could not find unique threshold: " + str(threshold))
       return self._cdf[:,:,:,I[0]]
    elif(metric[0] == "q"):
       quantile = float(metric[1:])
       I = np.where(abs(self._quantiles - quantile) < 0.0001)[0]
       if(len(I) == 0):
          Common.error("Cannot find " + metric)
       elif(len(I) > 1):
          Common.error("Could not find unique quantile: " + str(quantile))
       return self._x[:,:,:,I[0]]
    elif(metric == "Offset"):
       return self._offsets
    elif(metric == "Date"):
       return self._dates
    elif(metric == "Location"):
       stations = np.zeros(len(self._stations), 'float')
       for i in range(0, len(self._stations)):
          stations[i] = self._stations[i].id()
       return stations
    elif(metric in ["Lat", "Lon", "Elev"]):
       values = np.zeros(len(self._stations), 'float')
       for i in range(0, len(self._stations)):
          station = self._stations[i]
          if(metric == "Lat"):
             values[i] = station.lat()
          elif(metric == "Lon"):
             values[i] = station.lon()
          elif(metric == "Elev"):
             values[i] = station.elev()
       return values
    else:
       Common.error("Cannot find " + metric)
Пример #15
0
 def computeCore(self, data, tRange):
    Common.error("Metric '" + self.getClassName() + "' has not been implemented yet")
Пример #16
0
 def _computeObsFcst(self, obs, fcst):
    Common.error("Metric " + self.name() + " has not implemented _computeObsFcst()")
Пример #17
0
   def __init__(self, filename):
      import csv
      Input.__init__(self, filename)
      file = open(filename, 'r')
      self._units = "Unknown units"
      self._variable = "Unknown"
      self._pit = None

      self._dates = set()
      self._offsets = set()
      self._stations = set()
      self._quantiles = set()
      self._thresholds = set()
      fields = dict()
      obs = dict()
      fcst = dict()
      cdf = dict()
      pit = dict()
      x   = dict()
      indices = dict()
      header = None

      # Default values if columns not available
      offset  = 0
      date    = 0
      lat     = 0
      lon     = 0
      elev    = 0

      import time
      start = time.time()
      # Read the data into dictionary with (date,offset,lat,lon,elev) as key and obs/fcst as values
      for rowstr in file:
         if(rowstr[0] == "#"):
            curr = rowstr[1:]
            curr = curr.split()
            if(curr[0] == "variable:"):
               self._variable = curr[1]
            elif(curr[0] == "units:"):
               self._units = curr[1]
            else:
               Common.warning("Ignoring line '" + rowstr.strip() + "' in file '" + filename + "'")
         else:
            row = rowstr.split()
            if(header is None):
               # Parse the header so we know what each column represents
               header = row
               for i in range(0, len(header)):
                  att = header[i]
                  if(att == "date"):
                     indices["date"] = i
                  elif(att == "offset"):
                     indices["offset"] = i
                  elif(att == "lat"):
                     indices["lat"] = i
                  elif(att == "lon"):
                     indices["lon"] = i
                  elif(att == "elev"):
                     indices["elev"] = i
                  elif(att == "obs"):
                     indices["obs"] = i
                  elif(att == "fcst"):
                     indices["fcst"] = i
                  else:
                     indices[att] = i

               # Ensure we have required columns
               requiredColumns = ["obs", "fcst"]
               for col in requiredColumns:
                  if(not indices.has_key(col)):
                     msg = "Could not parse %s: Missing column '%s'" % (filename, col)
                     Common.error(msg)
            else:
               if(len(row) is not len(header)):
                  Common.error("Incorrect number of columns (expecting %d) in row '%s'"
                        % (len(header), rowstr.strip()))
               if(indices.has_key("date")):
                  date = self._clean(row[indices["date"]])
               self._dates.add(date)
               if(indices.has_key("offset")):
                  offset = self._clean(row[indices["offset"]])
               self._offsets.add(offset)
               if(indices.has_key("id")):
                  id = self._clean(row[indices["id"]])
               else:
                  id = np.nan
               if(indices.has_key("lat")):
                  lat = self._clean(row[indices["lat"]])
               if(indices.has_key("lon")):
                  lon = self._clean(row[indices["lon"]])
               if(indices.has_key("elev")):
                  elev = self._clean(row[indices["elev"]])
               station = Station.Station(id, lat, lon, elev)
               self._stations.add(station)
               obs[(date,offset,lat,lon,elev)]  = self._clean(row[indices["obs"]])
               fcst[(date,offset,lat,lon,elev)] = self._clean(row[indices["fcst"]])
               quantileFields = self._getQuantileFields(header)
               thresholdFields = self._getThresholdFields(header)
               for field in quantileFields:
                  quantile = float(field[1:])
                  self._quantiles.add(quantile)
                  key = (date,offset,lat,lon,elev,quantile)
                  x[key] = self._clean(row[indices[field]])
               for field in thresholdFields:
                  threshold = float(field[1:])
                  self._thresholds.add(threshold)
                  key = (date,offset,lat,lon,elev,threshold)
                  cdf[key] = self._clean(row[indices[field]])
               if indices.has_key("pit"):
                  pit[(date, offset,lat,lon,elev)] = self._clean(row[indices["pit"]])
      end = time.time()
      file.close()
      self._dates = list(self._dates)
      self._offsets = list(self._offsets)
      self._stations = list(self._stations)
      self._quantiles = list(self._quantiles)
      self._thresholds = np.array(list(self._thresholds))
      Ndates = len(self._dates)
      Noffsets = len(self._offsets)
      Nlocations = len(self._stations)
      Nquantiles = len(self._quantiles)
      Nthresholds = len(self._thresholds)

      # Put the dictionary data into a regular 3D array
      self._obs  = np.zeros([Ndates, Noffsets, Nlocations], 'float') * np.nan
      self._fcst = np.zeros([Ndates, Noffsets, Nlocations], 'float') * np.nan
      if(len(pit) != 0):
         self._pit  = np.zeros([Ndates, Noffsets, Nlocations], 'float') * np.nan
      self._cdf  = np.zeros([Ndates, Noffsets, Nlocations, Nthresholds], 'float') * np.nan
      self._x    = np.zeros([Ndates, Noffsets, Nlocations, Nquantiles], 'float') * np.nan
      for d in range(0,len(self._dates)):
         date = self._dates[d]
         end = time.time()
         for o in range(0, len(self._offsets)):
            offset = self._offsets[o]
            for s in range(0, len(self._stations)):
               station = self._stations[s]
               lat = station.lat()
               lon = station.lon()
               elev = station.elev()
               key = (date,offset,lat,lon,elev)
               if(obs.has_key(key)):
                  self._obs[d][o][s]  = obs[key]
               if(fcst.has_key(key)):
                  self._fcst[d][o][s] = fcst[key]
               if(pit.has_key(key)):
                  self._pit[d][o][s] = pit[key]
               for q in range(0, len(self._quantiles)):
                  quantile = self._quantiles[q]
                  key = (date,offset,lat,lon,elev,quantile)
                  if(x.has_key(key)):
                     self._x[d,o,s,q] = x[key]
               for t in range(0, len(self._thresholds)):
                  threshold = self._thresholds[t]
                  key = (date,offset,lat,lon,elev,threshold)
                  if(cdf.has_key(key)):
                     self._cdf[d,o,s,t] = cdf[key]
      end = time.time()
      maxStationId = np.nan
      for station in self._stations:
         if(np.isnan(maxStationId)):
            maxStationId =  station.id()
         elif(station.id() > maxStationId):
            maxStationId = station.id()

      counter = 0
      if(not np.isnan(maxStationId)):
         counter = maxStationId + 1

      for station in self._stations:
         if(np.isnan(station.id())):
            station.id(counter)
            counter = counter + 1
      self._dates = np.array(self._dates)
      self._offsets = np.array(self._offsets)
Пример #18
0
 def getScores(self, metric):
    temp = Common.clean(self._file.variables[metric])
    return temp
Пример #19
0
 def getObs(self):
    return Common.clean(self._file.variables["obs"])
Пример #20
0
 def getFcst(self):
    return Common.clean(self._file.variables["fcst"])
Пример #21
0
 def getDates(self):
    return Common.clean(self._file.variables["Date"])
Пример #22
0
 def getEns(self):
    return Common.clean(self._file.variables["ens"])
Пример #23
0
def showDescription(data=None):
    desc = "Program to compute verification scores for weather forecasts. Can be used to compare forecasts from different files. In that case only dates, offsets, and locations that are common to all forecast files are used."
    print textwrap.fill(desc, Common.getTextWidth())
    print ""
    print "usage: verif files -m metric [options]"
    print "       verif --version"
    print ""
    print Common.green("Arguments:")
    print Common.formatArgument(
        "files",
        "One or more verification files in NetCDF or text format (see 'File Formats' below)."
    )
    print Common.formatArgument(
        "-m metric", "Which verification metric to use? See 'Metrics' below.")
    print Common.formatArgument("--version", "What version of verif is this?")
    print ""
    print Common.green("Options:")
    print "Note: vectors can be entered using commas, or MATLAB syntax (i.e 3:5 is 3,4,5 and 3:2:7 is 3,5,7)"
    #print Common.formatArgument("","For vector options, the following are supported:")
    #print Common.formatArgument("","  start:end       e.g. 3:5 gives 3, 4, 5")
    #print Common.formatArgument("","  start:inc:end   e.g. 3:2:7 gives 3, 5, 7")
    #print Common.formatArgument("","  vector1,vector2 e.g. 3:5,1:2 gives 3, 4, 5, 1, 2")
    # Dimensions
    print Common.green("  Dimensions and subset:")
    print Common.formatArgument(
        "-d dates",
        "A vector of dates in YYYYMMDD format, e.g.  20130101:20130201.")
    print Common.formatArgument(
        "-l locations", "Limit the verification to these location IDs.")
    print Common.formatArgument(
        "-llrange range",
        "Limit the verification to locations within minlon,maxlon,minlat,maxlat."
    )
    print Common.formatArgument(
        "-o offsets", "Limit the verification to these offsets (in hours).")
    print Common.formatArgument(
        "-r thresholds",
        "Compute scores for these thresholds (only used by some metrics).")
    print Common.formatArgument(
        "-t period",
        "Allow this many days of training, i.e. remove this many days from the beginning of the verification."
    )
    print Common.formatArgument(
        "-x dim",
        "Plot this dimension on the x-axis: date, offset, location, locationId, locationElev, locationLat, locationLon, threshold, or none. Not supported by all metrics. If not specified, then a default is used based on the metric. 'none' collapses all dimensions and computes one value."
    )

    # Data manipulation
    print Common.green("  Data manipulation:")
    print Common.formatArgument(
        "-acc", "Plot accumulated values. Only works for non-derived metrics")
    print Common.formatArgument(
        "-b type",
        "One of 'below', 'within', or 'above'. For threshold plots (ets, hit, within, etc) 'below/above' computes frequency below/above the threshold, and 'within' computes the frequency between consecutive thresholds."
    )
    print Common.formatArgument(
        "-c file",
        "File containing climatology data. Subtract all forecasts and obs with climatology values."
    )
    print Common.formatArgument(
        "-C file",
        "File containing climatology data. Divide all forecasts and obs by climatology values."
    )
    print Common.formatArgument(
        "-ct type",
        "Collapsing type: 'min', 'mean', 'median', 'max', 'std', and 'range'. Some metrics computes a value for each value on the x-axis. Which function should be used to do the collapsing? Default is 'mean'. Only supported by some metrics."
    )
    print Common.formatArgument(
        "-hist",
        "Plot values as histogram. Only works for non-derived metrics")
    print Common.formatArgument(
        "-sort", "Plot values sorted. Only works for non-derived metrics")

    # Plot options
    print Common.green("  Plotting options:")
    print Common.formatArgument(
        "-bot value", "Bottom boundary location for saved figure [range 0-1]")
    print Common.formatArgument(
        "-clim limits", "Force colorbar limits to the two values lower,upper")
    print Common.formatArgument(
        "-dpi value", "Resolution of image in dots per inch (default 100)")
    print Common.formatArgument("-f file", "Save image to this filename")
    print Common.formatArgument(
        "-fs size", "Set figure size width,height (in inches). Default 8x6.")
    print Common.formatArgument(
        "-leg titles",
        "Comma-separated list of legend titles. Use '_' to represent space.")
    print Common.formatArgument("-lw width", "How wide should lines be?")
    print Common.formatArgument("-labfs size", "Font size for axis labels")
    print Common.formatArgument(
        "-left value", "Left boundary location for saved figure [range 0-1]")
    print Common.formatArgument("-legfs size", "Font size for legend")
    print Common.formatArgument("-majlth length", "Length of major tick marks")
    print Common.formatArgument(
        "-majtwid width", "Adjust the thickness of the major tick marks")
    print Common.formatArgument("-minlth length", "Length of minor tick marks")
    print Common.formatArgument("-ms size", "How big should markers be?")
    print Common.formatArgument(
        "-nomargin", "Remove margins (whitespace) in the plot not x[i] <= T.")
    print Common.formatArgument(
        "-right value", "Right boundary location for saved figure [range 0-1]")
    print Common.formatArgument("-sp",
                                "Show a line indicating the perfect score")
    print Common.formatArgument("-tickfs size", "Font size for axis ticks")
    print Common.formatArgument("-title text", "Custom title to chart top")
    print Common.formatArgument(
        "-top value", "Top boundary location for saved figure [range 0-1]")
    print Common.formatArgument(
        "-type type", "One of 'plot' (default), 'text', 'map', or 'maprank'.")
    print Common.formatArgument("-xlabel text", "Custom x-axis label")
    print Common.formatArgument(
        "-xlim limits", "Force x-axis limits to the two values lower,upper")
    print Common.formatArgument("-xrot value",
                                "Rotation angle for x-axis labels")
    print Common.formatArgument("-ylabel text", "Custom y-axis label")
    print Common.formatArgument(
        "-ylim limits", "Force y-axis limits to the two values lower,upper")
    print ""
    metrics = Metric.getAllMetrics()
    outputs = Output.getAllOutputs()
    print Common.green("Metrics (-m):")
    metricOutputs = metrics + outputs
    metricOutputs.sort(key=lambda x: x[0].lower(), reverse=False)
    for m in metricOutputs:
        name = m[0].lower()
        desc = m[1].summary()
        if (desc != ""):
            print Common.formatArgument(name, desc)
            #print "   %-14s%s" % (name, textwrap.fill(desc, 80).replace('\n', '\n                 ')),
            #print ""
    if (data != None):
        print ""
        print "  Or one of the following, which plots the raw score from the file:"
        print " ",
        metrics = data.getMetrics()
        for metric in metrics:
            print metric,
    print ""
    print ""
    print Common.green("File formats:")
    print Input.Text.description()
    print Input.Comps.description()
Пример #24
0
 def getCdf(self, threshold):
    #thresholds = getThresholds()
    #I = np.where(thresholds == threshold)[0]
    #assert(len(I) == 1)
    temp = Common.clean(self._file.variables["cdf"])
    return temp
Пример #25
0
 def test_comma(self):
    self.assertEqual([2,5], Common.parseNumbers("2,5"))
    self.assertEqual([3,3], Common.parseNumbers("3,3"))
    with self.assertRaises(SystemExit):
       Common.parseNumbers("test")
Пример #26
0
 def getOffsets(self):
    return Common.clean(self._file.variables["offset"])
Пример #27
0
 def test_date(self):
    self.assertEqual([20141230,20141231,20150101,20150102,20150103], Common.parseNumbers("20141230:20150103", True))
    self.assertEqual([20141230,20150101,20150103], Common.parseNumbers("20141230:2:20150104", True))
Пример #28
0
 def getThresholds(self):
    return Common.clean(self._file.variables["thresholds"])
Пример #29
0
 def test_endofyear(self):
    self.assertEqual(20150101, Common.getDate(20141231, 1))
    self.assertEqual(20141226, Common.getDate(20150105, -10))
    self.assertEqual(20150105, Common.getDate(20141226, 10))
    self.assertEqual(20141231, Common.getDate(20150101, -1))
Пример #30
0
 def getQuantiles(self):
    return Common.clean(self._file.variables["quantiles"])
Пример #31
0
 def test_vector(self):
    self.assertEqual([2,3,4,5], Common.parseNumbers("2:5"))
    self.assertEqual([], Common.parseNumbers("2:1"))
    with self.assertRaises(SystemExit):
       self.assertEqual([2], Common.parseNumbers("2:test"))
Пример #32
0
def showDescription(data=None):
   desc = "Program to compute verification scores for weather forecasts. Can be used to compare forecasts from different files. In that case only dates, offsets, and locations that are common to all forecast files are used."
   print textwrap.fill(desc, Common.getTextWidth())
   print ""
   print "usage: verif files -m metric [options]"
   print "       verif --version"
   print ""
   print Common.green("Arguments:")
   print Common.formatArgument("files", "One or more verification files in NetCDF or text format (see 'File Formats' below).")
   print Common.formatArgument("-m metric","Which verification metric to use? See 'Metrics' below.")
   print Common.formatArgument("--version","What version of verif is this?")
   print ""
   print Common.green("Options:")
   print "Note: vectors can be entered using commas, or MATLAB syntax (i.e 3:5 is 3,4,5 and 3:2:7 is 3,5,7)"
   #print Common.formatArgument("","For vector options, the following are supported:")
   #print Common.formatArgument("","  start:end       e.g. 3:5 gives 3, 4, 5")
   #print Common.formatArgument("","  start:inc:end   e.g. 3:2:7 gives 3, 5, 7")
   #print Common.formatArgument("","  vector1,vector2 e.g. 3:5,1:2 gives 3, 4, 5, 1, 2")
   # Dimensions
   print Common.green("  Dimensions and subset:")
   print Common.formatArgument("-d dates","A vector of dates in YYYYMMDD format, e.g.  20130101:20130201.")
   print Common.formatArgument("-l locations","Limit the verification to these location IDs.")
   print Common.formatArgument("-llrange range","Limit the verification to locations within minlon,maxlon,minlat,maxlat.")
   print Common.formatArgument("-o offsets","Limit the verification to these offsets (in hours).")
   print Common.formatArgument("-r thresholds","Compute scores for these thresholds (only used by some metrics).")
   print Common.formatArgument("-t period","Allow this many days of training, i.e. remove this many days from the beginning of the verification.")
   print Common.formatArgument("-x dim","Plot this dimension on the x-axis: date, offset, location, locationId, locationElev, locationLat, locationLon, threshold, or none. Not supported by all metrics. If not specified, then a default is used based on the metric. 'none' collapses all dimensions and computes one value.")

   # Data manipulation
   print Common.green("  Data manipulation:")
   print Common.formatArgument("-acc","Plot accumulated values. Only works for non-derived metrics")
   print Common.formatArgument("-b type","One of 'below', 'within', or 'above'. For threshold plots (ets, hit, within, etc) 'below/above' computes frequency below/above the threshold, and 'within' computes the frequency between consecutive thresholds.")
   print Common.formatArgument("-c file","File containing climatology data. Subtract all forecasts and obs with climatology values.")
   print Common.formatArgument("-C file","File containing climatology data. Divide all forecasts and obs by climatology values.")
   print Common.formatArgument("-ct type","Collapsing type: 'min', 'mean', 'median', 'max', 'std', and 'range'. Some metrics computes a value for each value on the x-axis. Which function should be used to do the collapsing? Default is 'mean'. Only supported by some metrics.")
   print Common.formatArgument("-hist","Plot values as histogram. Only works for non-derived metrics")
   print Common.formatArgument("-sort","Plot values sorted. Only works for non-derived metrics")

   # Plot options
   print Common.green("  Plotting options:")
   print Common.formatArgument("-bot value","Bottom boundary location for saved figure [range 0-1]")
   print Common.formatArgument("-clim limits","Force colorbar limits to the two values lower,upper")
   print Common.formatArgument("-dpi value","Resolution of image in dots per inch (default 100)")
   print Common.formatArgument("-f file","Save image to this filename")
   print Common.formatArgument("-fs size","Set figure size width,height (in inches). Default 8x6.")
   print Common.formatArgument("-leg titles","Comma-separated list of legend titles. Use '_' to represent space.")
   print Common.formatArgument("-lw width","How wide should lines be?")
   print Common.formatArgument("-labfs size","Font size for axis labels")
   print Common.formatArgument("-left value","Left boundary location for saved figure [range 0-1]")
   print Common.formatArgument("-legfs size","Font size for legend")
   print Common.formatArgument("-majlth length","Length of major tick marks")
   print Common.formatArgument("-majtwid width","Adjust the thickness of the major tick marks")
   print Common.formatArgument("-minlth length","Length of minor tick marks")
   print Common.formatArgument("-ms size","How big should markers be?")
   print Common.formatArgument("-nomargin","Remove margins (whitespace) in the plot not x[i] <= T.")
   print Common.formatArgument("-right value","Right boundary location for saved figure [range 0-1]")
   print Common.formatArgument("-sp","Show a line indicating the perfect score")
   print Common.formatArgument("-tickfs size","Font size for axis ticks")
   print Common.formatArgument("-title text","Custom title to chart top")
   print Common.formatArgument("-top value","Top boundary location for saved figure [range 0-1]")
   print Common.formatArgument("-type type","One of 'plot' (default), 'text', 'map', or 'maprank'.")
   print Common.formatArgument("-xlabel text","Custom x-axis label")
   print Common.formatArgument("-xlim limits","Force x-axis limits to the two values lower,upper")
   print Common.formatArgument("-xrot value","Rotation angle for x-axis labels")
   print Common.formatArgument("-ylabel text","Custom y-axis label")
   print Common.formatArgument("-ylim limits","Force y-axis limits to the two values lower,upper")
   print ""
   metrics = Metric.getAllMetrics()
   outputs = Output.getAllOutputs()
   print Common.green("Metrics (-m):")
   metricOutputs = metrics + outputs
   metricOutputs.sort(key=lambda x: x[0].lower(), reverse=False)
   for m in metricOutputs:
      name = m[0].lower()
      desc = m[1].summary()
      if(desc != ""):
         print Common.formatArgument(name, desc)
         #print "   %-14s%s" % (name, textwrap.fill(desc, 80).replace('\n', '\n                 ')),
         #print ""
   if(data is not None):
      print ""
      print "  Or one of the following, which plots the raw score from the file:"
      print " ",
      metrics = data.getMetrics()
      for metric in metrics:
         print metric,
   print ""
   print ""
   print Common.green("File formats:")
   print Input.Text.description()
   print Input.Comps.description()