Пример #1
0
 def cultivar(self, ens, gid):
     """Retrieve Cultivar parameters for pixel and ensemble member."""
     db = dbio.connect(self.dbname)
     cur = db.cursor()
     if dbio.columnExists(self.dbname, "dssat", "cultivars", "name"):
         name_query = ",c.name"
     else:
         name_query = ""
     sql = "select p1,p2,p5,g2,g3,phint{3} from dssat.cultivars as c,{0}.agareas as a where crop='maize' and ensemble={1} and st_intersects(c.geom,a.geom) and a.gid={2}".format(
         self.name, ens + 1, gid, name_query)
     cur.execute(sql)
     if not bool(cur.rowcount):
         sql = "select p1,p2,p5,g2,g3,phint{3} from dssat.cultivars as c,{0}.agareas as a where crop='maize' and ensemble={1} and a.gid={2} order by st_centroid(c.geom) <-> st_centroid(a.geom)".format(
             self.name, ens + 1, gid, name_query)
         cur.execute(sql)
     if name_query:
         p1, p2, p5, g2, g3, phint, cname = cur.fetchone()
     else:
         p1, p2, p5, g2, g3, phint = cur.fetchone()
         cname = ""
     # FIXME: Should the name of the cultivar be reflected in the line below?
     cultivar = "990002 MEDIUM SEASON    IB0001  {0:.1f} {1:.3f} {2:.1f} {3:.1f}  {4:.2f} {5:.2f}".format(
         p1, p2, p5, g2, g3, phint)
     cur.close()
     db.close()
     self.cultivars[gid].append(cname)
     return cultivar
Пример #2
0
def calcSeverity(model, cid, varname="soil_moist"):
    """Calculate drought severity from *climatology* table stored in database."""
    log = logging.getLogger(__name__)
    outvars = model.getOutputStruct(model.model_path + "/global.txt")
    col = outvars[varname][1]
    if varname in ["soil_moist"]:
        p = np.loadtxt("{0}/{1}_{2:.{4}f}_{3:.{4}f}".format(model.model_path, outvars['runoff'][0], model.gid[cid][0], model.gid[cid][1], model.grid_decimal))[:, col:col+model.nlayers]
        p = pandas.Series(np.sum(p, axis=1), [datetime(model.startyear, model.startmonth, model.startday) + timedelta(t) for t in range(len(p))])
    else:
        p = np.loadtxt("{0}/{1}_{2:.{4}f}_{3:.{4}f}".format(model.model_path, outvars['runoff'][0], model.gid[cid][0], model.gid[cid][1], model.grid_decimal))[:, col]
        p = pandas.Series(p, [datetime(model.startyear, model.startmonth, model.startday) + timedelta(t) for t in range(len(p))])
    db = dbio.connect(model.dbname)
    cur = db.cursor()
    if dbio.tableExists(model.dbname, model.name, varname):
        if varname in ["soil_moist"]:
            lvar = ",layer"
        else:
            lvar = ""
        if dbio.columnExists(model.dbname, model.name, varname, "ensemble"):
            fsql = "with f as (select fdate{3},avg(st_value(rast,st_geomfromtext('POINT({0} {1})',4326))) as vals from {2}.{4} where st_intersects(rast,st_geomfromtext('POINT({0} {1})',4326)) group by fdate{3})".format(model.gid[cid][1], model.gid[cid][0], model.name, lvar, varname)
        else:
            fsql = "with f as (select fdate{3},st_value(rast,st_geomfromtext('POINT({0} {1})',4326)) as vals from {2}.{4} where st_intersects(rast,st_geomfromtext('POINT({0} {1})',4326)))".format(model.gid[cid][1], model.gid[cid][0], model.name, lvar, varname)
        sql = "{0} select fdate,sum(vals) from f group by fdate".format(fsql)
        cur.execute(sql)
        if bool(cur.rowcount):
            results = cur.fetchall()
            clim = pandas.Series([r[1] for r in results], [r[0] for r in results])
        else:
            clim = p
    else:
        log.warning("Climatology table does not exist. Severity calculation will be inaccurate!")
        clim = p
    s = 100.0 - np.array(map(lambda v: stats.percentileofscore(clim, v), p))
    return s
Пример #3
0
def calcSMDI(model, cid):
    """Calculate Soil Moisture Deficit Index (Narasimhan & Srinivasan, 2005)."""
    log = logging.getLogger(__name__)
    outvars = model.getOutputStruct(model.model_path + "/global.txt")
    col = outvars['soil_moist'][1]
    p = np.loadtxt("{0}/{1}_{2:.{4}f}_{3:.{4}f}".format(
        model.model_path, outvars['soil_moist'][0], model.gid[cid][0],
        model.gid[cid][1], model.grid_decimal))[:, col:col + model.nlayers]
    p = pandas.Series(np.sum(p, axis=1), [
        datetime(model.startyear, model.startmonth, model.startday) +
        timedelta(t) for t in range(len(p))
    ])
    db = dbio.connect(model.dbname)
    cur = db.cursor()
    if dbio.tableExists(model.dbname, model.name, "soil_moist"):
        if dbio.columnExists(model.dbname, model.name, "soil_moist",
                             "ensemble"):
            fsql = "with f as (select fdate,layer,avg(st_value(rast,st_geomfromtext('POINT({0} {1})',4326))) as sm from {2}.soil_moist where st_intersects(rast,st_geomfromtext('POINT({0} {1})',4326)) group by fdate,layer)".format(
                model.gid[cid][1], model.gid[cid][0], model.name)
        else:
            fsql = "with f as (select fdate,layer,st_value(rast,st_geomfromtext('POINT({0} {1})',4326)) as sm from {2}.soil_moist where st_intersects(rast,st_geomfromtext('POINT({0} {1})',4326)))".format(
                model.gid[cid][1], model.gid[cid][0], model.name)
        sql = "{0} select fdate,sum(sm) from f group by fdate".format(fsql)
        cur.execute(sql)
        if bool(cur.rowcount):
            results = cur.fetchall()
            clim = pandas.Series([r[1] for r in results],
                                 [r[0] for r in results])
        else:
            clim = p
    else:
        log.warning(
            "Climatology table does not exist. SMDI calculation will be inaccurate!"
        )
        clim = p
    smdi = np.zeros(len(p))
    MSW = clim.median()
    maxSW = clim.max()
    minSW = clim.min()
    for i in range(7, len(smdi)):
        SW = np.median(p[i - 7:i + 1])
        if SW == MSW:
            SD = (SW - MSW) / (MSW - minSW) * 100.0
        else:
            SD = (SW - MSW) / (maxSW - MSW) * 100.0
        if i > 7:
            smdi[i] = 0.5 * smdi[i - 1] + SD / 50.0
        else:
            smdi[i] = SD / 50.0
    cur.close()
    db.close()
    return smdi
Пример #4
0
Файл: nmme.py Проект: nasa/RHEAS
def _setEnsemble(dbname, sname, ens):
    """Set ensemble column in NMME data table."""
    db = dbio.connect(dbname)
    cur = db.cursor()
    cur.execute("select * from raster_resampled where sname='{0}' and tname like 'nmme_%'".format(sname))
    tables = [r[1] for r in cur.fetchall()]
    for table in tables:
        if not dbio.columnExists(dbname, sname, table, "ensemble"):
            cur.execute("alter table {0}.{1} add column ensemble int".format(sname, table))
            db.commit()
        sql = "update {0}.{1} set ensemble = {2} where ensemble is null".format(sname, table, ens)
        cur.execute(sql)
    db.commit()
    cur.close()
    db.close()
Пример #5
0
def _setEnsemble(dbname, sname, ens):
    """Set ensemble column in NMME data table."""
    db = dbio.connect(dbname)
    cur = db.cursor()
    cur.execute("select * from raster_resampled where sname='{0}' and tname like 'nmme_%'".format(sname))
    tables = [r[1] for r in cur.fetchall()]
    for table in tables:
        if not dbio.columnExists(dbname, sname, table, "ensemble"):
            cur.execute("alter table {0}.{1} add column ensemble int".format(sname, table))
            db.commit()
        sql = "update {0}.{1} set ensemble = {2} where ensemble is null".format(sname, table, ens)
        cur.execute(sql)
    db.commit()
    cur.close()
    db.close()
Пример #6
0
def calcSMDI(model, cid):
    """Calculate Soil Moisture Deficit Index (Narasimhan & Srinivasan, 2005)."""
    log = logging.getLogger(__name__)
    outvars = model.getOutputStruct(model.model_path + "/global.txt")
    col = outvars['soil_moist'][1]
    p = np.loadtxt("{0}/{1}_{2:.{4}f}_{3:.{4}f}".format(model.model_path, outvars['soil_moist'][0], model.gid[cid][0], model.gid[cid][1], model.grid_decimal))[:, col:col+model.nlayers]
    p = pandas.Series(np.sum(p, axis=1), [datetime(model.startyear, model.startmonth, model.startday) + timedelta(t) for t in range(len(p))])
    db = dbio.connect(model.dbname)
    cur = db.cursor()
    if dbio.tableExists(model.dbname, model.name, "soil_moist"):
        if dbio.columnExists(model.dbname, model.name, "soil_moist", "ensemble"):
            fsql = "with f as (select fdate,layer,avg(st_value(rast,st_geomfromtext('POINT({0} {1})',4326))) as sm from {2}.soil_moist where st_intersects(rast,st_geomfromtext('POINT({0} {1})',4326)) group by fdate,layer)".format(model.gid[cid][1], model.gid[cid][0], model.name)
        else:
            fsql = "with f as (select fdate,layer,st_value(rast,st_geomfromtext('POINT({0} {1})',4326)) as sm from {2}.soil_moist where st_intersects(rast,st_geomfromtext('POINT({0} {1})',4326)))".format(model.gid[cid][1], model.gid[cid][0], model.name)
        sql = "{0} select fdate,sum(sm) from f group by fdate".format(fsql)
        cur.execute(sql)
        if bool(cur.rowcount):
            results = cur.fetchall()
            clim = pandas.Series([r[1] for r in results], [r[0] for r in results])
        else:
            clim = p
    else:
        log.warning("Climatology table does not exist. SMDI calculation will be inaccurate!")
        clim = p
    smdi = np.zeros(len(p))
    MSW = clim.median()
    maxSW = clim.max()
    minSW = clim.min()
    for i in range(7, len(smdi)):
        SW = np.median(p[i-7:i+1])
        if SW == MSW:
            SD = (SW - MSW) / (MSW - minSW) * 100.0
        else:
            SD = (SW - MSW) / (maxSW - MSW) * 100.0
        if i > 7:
            smdi[i] = 0.5 * smdi[i-1] + SD / 50.0
        else:
            smdi[i] = SD / 50.0
    cur.close()
    db.close()
    return smdi
Пример #7
0
 def cultivar(self, ens, gid):
     """Retrieve Cultivar parameters for pixel and ensemble member."""
     db = dbio.connect(self.dbname)
     cur = db.cursor()
     if dbio.columnExists(self.dbname, "dssat", "cultivars", "name"):
         name_query = ",c.name"
     else:
         name_query = ""
     sql = "select p1,p2r,p5,p2o,g1,g2,g3,g4{3} from dssat.cultivars as c,{0}.agareas as a where crop='rice' and ensemble={1} and st_intersects(c.geom,a.geom) and a.gid={2}".format(self.name, ens + 1, gid, name_query)
     cur.execute(sql)
     if not bool(cur.rowcount):
         sql = "select p1,p2r,p5,p2o,g1,g2,g3,g4{3} from dssat.cultivars as c,{0}.agareas as a where crop='rice' and ensemble={1} and a.gid={2} order by st_centroid(c.geom) <-> st_centroid(a.geom)".format(self.name, ens + 1, gid, name_query)
         cur.execute(sql)
     if name_query:
         p1, p2r, p5, p2o, g1, g2, g3, g4, cname = cur.fetchone()
     else:
         p1, p2r, p5, p2o, g1, g2, g3, g4 = cur.fetchone()
         cname = ""
     # FIXME: Should the name of the cultivar be reflected in the line below?
     cultivar = "IB0012 IR 58            IB0001{0:6.1f}{1:6.1f}{2:6.1f}{3:6.1f}{4:6.1f}{5:6.4f}{6:6.2f}{7:6.2f}".format(p1, p2r, p5, p2o, g1, g2, g3, g4)
     cur.close()
     db.close()
     self.cultivars[gid].append(cname)
     return cultivar
Пример #8
0
 def writeToDB(self, data, dates, tablename, initialize, ensemble=False, skipsave=0):
     """Writes output data into database."""
     db = dbio.connect(self.dbname)
     cur = db.cursor()
     if dbio.tableExists(self.dbname, self.name, tablename) and ensemble and not dbio.columnExists(self.dbname, self.name, tablename, "ensemble"):
         print("WARNING! Table {0} exists but does not contain ensemble information. Overwriting entire table!")
         cur.execute("drop table {0}.{1}".format(self.name, tablename))
         db.commit()
     if dbio.tableExists(self.dbname, self.name, tablename):
         if initialize:
             for dt in [self.startdate + timedelta(t) for t in range((self.enddate - self.startdate).days+1)]:
                 dbio.deleteRasters(self.dbname, "{0}.{1}".format(self.name, tablename), dt)
     else:
         sql = "create table {0}.{1} (id serial not null primary key, rid int not null, fdate date not null, rast raster)".format(
             self.name, tablename)
         cur.execute(sql)
         if data.shape[1] > 1:
             cur.execute("alter table {0}.{1} add column layer int".format(self.name, tablename))
         if ensemble:
             cur.execute("alter table {0}.{1} add column ensemble int".format(self.name, tablename))
         db.commit()
     startyear, startmonth, startday = self.startyear, self.startmonth, self.startday
     if skipsave > 0:
         ts = date(self.startyear, self.startmonth,
                   self.startday) + timedelta(skipsave)
         data = data[skipsave:]
         startyear, startmonth, startday = ts.year, ts.month, ts.day
     tiffiles = []
     for t in range(data.shape[0]):
         dt = date(startyear, startmonth, startday) + timedelta(t)
         for lyr in range(data.shape[1]):
             filename = "{0}/{1}_{2}{3:02d}{4:02d}_{5:02d}.tif".format(
                 self.model_path, tablename, dt.year, dt.month, dt.day, lyr + 1)
             self._writeRaster(data[t, lyr, :, :], filename)
             tiffiles.append(filename)
     ps1 = subprocess.Popen(["{0}/raster2pgsql".format(rpath.bins), "-s", "4326", "-F", "-d", "-t", "auto"] + tiffiles + ["temp"], stdout=subprocess.PIPE)
     ps2 = subprocess.Popen(["{0}/psql".format(rpath.bins), "-d", self.dbname], stdin=ps1.stdout, stdout=subprocess.PIPE)
     ps1.stdout.close()
     ps2.communicate()[0]
     ps1.wait()
     cur.execute("alter table temp add column fdate date")
     cur.execute("update temp set fdate = date (concat_ws('-',substring(filename from {0} for 4),substring(filename from {1} for 2),substring(filename from {2} for 2)))".format(
         len(tablename) + 2, len(tablename) + 6, len(tablename) + 8))
     if data.shape[1] > 1:
         cur.execute("alter table temp add column layer int")
         cur.execute("update temp set layer=(substring(filename from {0} for 2))::int".format(
             len(tablename) + 11))
     cur.execute("select count(*) from temp")
     n = int(cur.fetchone()[0])
     ntiles = n / data.shape[0]
     if data.shape[1] > 1:
         cur.execute(
             "insert into {0}.{1} (rid,fdate,layer,rast) select ((rid+{2}) % {2})+1,fdate,layer,rast from temp".format(self.name, tablename, ntiles))
     else:
         cur.execute(
             "insert into {0}.{1} (rid,fdate,rast) select ((rid+{2}) % {2})+1,fdate,rast from temp".format(self.name, tablename, ntiles))
     if bool(ensemble):
         sql = "update {0}.{1} set ensemble = {2} where ensemble is null".format(
             self.name, tablename, int(ensemble))
         cur.execute(sql)
     cur.execute("drop index if exists {0}.{1}_dtidx".format(
         self.name, tablename))
     cur.execute("create index {1}_dtidx on {0}.{1}(fdate)".format(
         self.name, tablename))
     cur.execute("drop index if exists {0}.{1}_spidx".format(
         self.name, tablename))
     cur.execute("create index {1}_spidx on {0}.{1} using gist(st_convexhull(rast))".format(
         self.name, tablename))
     db.commit()
     cur.close()
     db.close()
Пример #9
0
 def writeToDB(self,
               data,
               dates,
               tablename,
               initialize,
               ensemble=False,
               skipsave=0):
     """Writes output data into database."""
     db = dbio.connect(self.dbname)
     cur = db.cursor()
     if dbio.tableExists(self.dbname, self.name,
                         tablename) and ensemble and not dbio.columnExists(
                             self.dbname, self.name, tablename, "ensemble"):
         print(
             "WARNING! Table {0} exists but does not contain ensemble information. Overwriting entire table!"
         )
         cur.execute("drop table {0}.{1}".format(self.name, tablename))
         db.commit()
     if dbio.tableExists(self.dbname, self.name, tablename):
         if initialize:
             for dt in [
                     self.startdate + timedelta(t)
                     for t in range((self.enddate - self.startdate).days +
                                    1)
             ]:
                 dbio.deleteRasters(self.dbname,
                                    "{0}.{1}".format(self.name,
                                                     tablename), dt)
     else:
         sql = "create table {0}.{1} (id serial not null primary key, rid int not null, fdate date not null, rast raster)".format(
             self.name, tablename)
         cur.execute(sql)
         if data.shape[1] > 1:
             cur.execute("alter table {0}.{1} add column layer int".format(
                 self.name, tablename))
         if ensemble:
             cur.execute(
                 "alter table {0}.{1} add column ensemble int".format(
                     self.name, tablename))
         db.commit()
     startyear, startmonth, startday = self.startyear, self.startmonth, self.startday
     if skipsave > 0:
         ts = date(self.startyear, self.startmonth,
                   self.startday) + timedelta(skipsave)
         data = data[skipsave:]
         startyear, startmonth, startday = ts.year, ts.month, ts.day
     tiffiles = []
     for t in range(data.shape[0]):
         dt = date(startyear, startmonth, startday) + timedelta(t)
         for lyr in range(data.shape[1]):
             filename = "{0}/{1}_{2}{3:02d}{4:02d}_{5:02d}.tif".format(
                 self.model_path, tablename, dt.year, dt.month, dt.day,
                 lyr + 1)
             self._writeRaster(data[t, lyr, :, :], filename)
             tiffiles.append(filename)
     ps1 = subprocess.Popen([
         "{0}/raster2pgsql".format(rpath.bins), "-s", "4326", "-F", "-d",
         "-t", "auto"
     ] + tiffiles + ["temp"],
                            stdout=subprocess.PIPE)
     ps2 = subprocess.Popen(
         ["{0}/psql".format(rpath.bins), "-d", self.dbname],
         stdin=ps1.stdout,
         stdout=subprocess.PIPE)
     ps1.stdout.close()
     ps2.communicate()[0]
     ps1.wait()
     cur.execute("alter table temp add column fdate date")
     cur.execute(
         "update temp set fdate = date (concat_ws('-',substring(filename from {0} for 4),substring(filename from {1} for 2),substring(filename from {2} for 2)))"
         .format(
             len(tablename) + 2,
             len(tablename) + 6,
             len(tablename) + 8))
     if data.shape[1] > 1:
         cur.execute("alter table temp add column layer int")
         cur.execute(
             "update temp set layer=(substring(filename from {0} for 2))::int"
             .format(len(tablename) + 11))
     cur.execute("select count(*) from temp")
     n = int(cur.fetchone()[0])
     ntiles = n / data.shape[0]
     if data.shape[1] > 1:
         cur.execute(
             "insert into {0}.{1} (rid,fdate,layer,rast) select ((rid+{2}) % {2})+1,fdate,layer,rast from temp"
             .format(self.name, tablename, ntiles))
     else:
         cur.execute(
             "insert into {0}.{1} (rid,fdate,rast) select ((rid+{2}) % {2})+1,fdate,rast from temp"
             .format(self.name, tablename, ntiles))
     if bool(ensemble):
         sql = "update {0}.{1} set ensemble = {2} where ensemble is null".format(
             self.name, tablename, int(ensemble))
         cur.execute(sql)
     cur.execute("drop index if exists {0}.{1}_dtidx".format(
         self.name, tablename))
     cur.execute("create index {1}_dtidx on {0}.{1}(fdate)".format(
         self.name, tablename))
     cur.execute("drop index if exists {0}.{1}_spidx".format(
         self.name, tablename))
     cur.execute(
         "create index {1}_spidx on {0}.{1} using gist(st_convexhull(rast))"
         .format(self.name, tablename))
     db.commit()
     cur.close()
     db.close()