Coder Social home page Coder Social logo

openmi-om's Introduction

openmi-om

A lightweight implementation of the OpenMI framework for building Object-oriented Meta-models.

INSTALLATION Currently installation is from tar.gz only. Use the following command:

# last working:
install.packages('https://github.com/HARPgroup/openmi-om/raw/master/R/openmi.om_0.0.0.9106.tar.gz', repos = NULL, type="source")
# Now try
library("devtools")
install_github("HARPgroup/openmi-om")

BUILDING

# From R command prompt
library('roxygen2')
setwd('/usr/local/home/git/openmi-om/R/openmi.om')
roxygenize()

cd R
R CMD build openmi.om

openmi-om's People

Contributors

hdaniel7 avatar jdkleiner avatar rburghol avatar

Watchers

 avatar  avatar  avatar

openmi-om's Issues

Implement dataMatrix component

See also pull request #15
Items:

  • Parsing table from openmi json
  • Method of lookup: See the following post for several options on how to implement flexible, and fast lookups. Includes:
    • using a lm() - this may not be appropriate for something like a reservoir, where we want no fuzziness, or perhaps the fuzziness is actually acceptable?
    • This could be an intriguing method of achieving the 3-d lookups (or any-d really) fo solving things like reservoir and channel outflow given storage(0), and Qin.
    • Or even as a method of initial guesses for a standard iterative solver

Overview
Basic class for performing lookups with:

Landuse + CBP flow widget

Overall Workflow for Openmi-OM component

  • Generate shell script to loop through all landsegment outflow WDMs for all land uses in a segment, see WDM Formatting below
  • take input from CBP runoff/iflow/gwflow WDM exports (see below WDM Data Formatting)
  • multiply by landuse grid (rows match csv columns)
    • Obtain from VAHydro (TBD - for now, play with
  • sum all runoff
  • produce text file with date and runoff total and gw iflow totals, and total Qout, and Runit
  • make sure file format is compatible with OM runtime timeseries file used in cache mode
  • save file name with OM runfile convention with elementid and runid

WDM Data Formatting
This will be a preliminary step in this evaluation, exporting the data to use in your widget. For the short term, we will just export the data for one land segment, for a river segment of interest

  • Options:
  • Locate CBP runoff/iflow/gwflow WDMs - these WDM files contain "unit area" runoff values
    • Example:
      • river segment: OR2_8130_7900
      • land segment: A51121
      • wdm: p532c-sova/wdm/land/for/p532cal_062211/forA51121.wdm
      • uci: p532c-sova/uci/land/for/p532cal_062211/forA51121.uci
      • DSN: 111 (SURO, ak surface runoff)
  • Export Data from WDM (will produce 3 fils fro each land use IFWO, SURO, AGWO)
    Use quick_wdm_2_txt_hour_2_hour to convert wdms to csvs. Steps are as follows:
    • ssh into deq2.bse.vt.edu
    • cd /opt/model/p53/p532c-sova/tmp/wdm/land/(3 LETTER LAND USE)/p532cal_062211
    • /opt/model/p53/p532c-sova/code/bin/quick_wdm_2_txt_hour_2_hour
    • input wdm name, start year, end year, dsn
      • ex: afoA51121.wdm, 1984, 2005, 111
    • navigate to location on http://deq2.bse.vt.edu/p532c-sova/ in web browser, download -- EDIT: this step is obsolete -- the script can pull the wdms straight from the URL, no need to download files.
  • Reformat WDM files into best format (we may need to experiment, the first option is easy and simple):
    • 1 File per Land Segment, 1 column for each land use with summed IFWO, SURO and AGWO
      • timestamp: the timestamp of the model output
      • afo
      • for
      • ...
    • Try 1 file per landuse and land segment, with 4 columns
      • timestamp: the timestamp of the model output
      • suro: suface runoff -- DSN 111
      • ifwo: interflow -- DSN 211
      • agwo: "active" groundwater -- DSN 411
  • Model Output file: a csv output
    • Name: runlog[runid].[vahydro om elementid].log -- example: runlog2.256687.log
    • Columns (at minimum, you may include more than this, and we may later REQUIRE more than this)
      • timestamp
      • Qout
      • area_sqmi

image

Example Land Use Table
This is a Phase 5.3 table example, so some names may have changed in 5.3.2.

luname 1984 1987 1992 1997 2002 2005
afo 0.91 0.86 0.86 0.79 0.66 0.66
alf 9.83 10.27 11.29 9.13 11.91 7.83
bar 0.80 0.80 0.81 0.84 0.87 0.87
css 0.00 0.00 0.00 0.00 0.00 0.00
ext 25.40 25.40 25.40 25.40 25.40 25.40
for 1187.98 1190.02 1184.11 1197.78 1203.24 1216.05
hom 1.26 1.17 1.72 1.56 2.06 1.90
hvf 12.00 12.02 11.96 12.10 12.15 12.28
hwm 8.79 6.85 5.94 2.28 3.84 3.86
hyo 8.61 11.09 7.19 9.54 7.62 6.91
hyw 31.24 33.18 33.08 36.18 38.81 39.90
imh 12.30 12.30 12.30 12.80 13.20 13.30
iml 28.80 28.80 28.80 28.80 28.80 28.80
lwm 18.29 16.39 17.83 14.26 11.32 11.39
nal 0.00 0.00 0.00 0.00 0.00 0.00
nhi 0.00 0.00 0.00 0.00 0.00 0.00
nho 0.00 0.00 0.00 0.00 0.00 0.00
nhy 0.00 0.00 0.00 0.00 0.00 0.00
nlo 0.00 0.00 0.00 0.00 0.00 0.00
npa 0.00 0.00 0.00 0.00 0.00 0.00
pas 130.87 128.08 135.54 125.50 117.21 108.50
puh 11.40 11.40 11.40 11.80 12.10 12.00
pul 144.00 144.00 144.00 144.00 144.00 144.00
trp 6.89 6.74 7.13 6.61 6.17 5.71
urs 0.00 0.00 0.00 0.01 0.00 0.00
wat 4.00 4.00 4.00 4.00 4.00 4.00

Table 2: Sam[ple export from http://deq2.bse.vt.edu/p532c-sova/wdm/land/p532cal_062211_A51121_eos_all.csv

 ix Year Month Day Hour afo_0111 afo_0211 afo_0411 alf_0111 alf_0211 alf_0411 ccn_0111 ccn_0211 ccn_0411 cex_0111 cex_0211 cex_0411 cfo_0111 cfo_0211
1 1984 1 1 1 0.000171 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 0.000171 0
2 1984 1 1 2 0.0001 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 0.0001 0
3 1984 1 1 3 6.61E-05 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 6.61E-05 0
4 1984 1 1 4 4.67E-05 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 4.67E-05 0
5 1984 1 1 5 3.47E-05 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 3.47E-05 0
6 1984 1 1 6 2.68E-05 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 2.68E-05 0
7 1984 1 1 7 0.000179 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 0.000179 0
8 1984 1 1 8 0 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 0 0
9 1984 1 1 9 0 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 0 0
10 1984 1 1 10 0 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 0 0
11 1984 1 1 11 0 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 0 0
12 1984 1 1 12 0 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 0 0
13 1984 1 1 13 0 0 0 0 0 1.98E-05 0 0 1.98E-05 0 0 1.98E-05 0 0

Interpolation/date-matching for R timeseries objects

Overview

Current implementation of timeseries objects in opemi-om R version is ultra-simplistic, only considering exact match of timestamp, and failing catastrophically if no match is found (the data retrieval line doesn't fail, just the method of setting the state variable). This needs to be more robust to be sure (handle missing/mismatched data and fail gracefully with error). Also, there needs to be means to do interpolation. The PHP version of vahydro timeseries object had the following modes:

  • 0: linear,
  • 1: previous value,
  • 2: next value,
  • 3: period mean,
  • 4: period min,
  • 5: period max,
  • 6: period sum

Using SQL to create a perfectly matched and interpolated timeseries before run execution

See https://github.com/HARPgroup/openmi-om/blob/master/examples/timestamp_queries.R

  • before model run, use SQL to create a timeseries that matches the timestamp of the timer exactly.
  • Should make all data in UTC format in order to avoid daylight savings time weirdness

xts date range retrieval functions

The xts class (extending zoo) allows for retrieval of date ranges:

# now create an instance of the timeSeriesInput class we've just made
k <- openmi.om.timeSeriesInput();
# Create dat by reading tmp_file
tmp_file = "http://deq2.bse.vt.edu/files/icprb/potomac_111518_precip_in.tsv"
dat <- read.table(tmp_file, sep="\t", header=TRUE)
# Convert dat into xts
k$tsvalues <- xts(dat, order.by = as.POSIXct(dat$Date, format="%m/%d/%Y"))
# use xts timespan notation, i.e.:
# tr = "1999-01-09/1999-01-10 12:00:00"
tr = paste(as.POSIXct('1999-01-9'),(as.POSIXct('1999-01-9') + hours(36)), sep="/")
k$tsvalues[tr]

Produces:

           Date        Northern Shenandoah
1999-01-09 "1/9/1999"  "0.48"   "0.52"    
1999-01-10 "1/10/1999" "0.07"   "0.01"  

To which could be applied the functions:

> mean(as.numeric(k$tsvalues[tr]$Northern))
[1] 0.275
> min(as.numeric(k$tsvalues[tr]$Northern))
[1] 0.07
> max(as.numeric(k$tsvalues[tr]$Northern))
[1] 0.48

Benchmarking/Performance

Previous versions of the model employed timeseries inputs that were pre-processed to do all interpolation prior to execution, allowing easy, exact-matching at run-time. (Example: CBP runoff timeseries input https://github.com/HARPgroup/vahydro/issues/7 )

  • Benchmark exact matching to period summing
  • examine methods of pre-run period summing , benchmark time taken

NPS "Unit hydrograph" type export function

CBP discussed using what I interpreted as a "unit-hydrograph" type of approach to NPS pollutant export from the landscape. In other words,:

  • Rather than a mechanistic approach (accumulation/washoff like SQO in HSPF), this had some pre-determined, calibrated P = f(RO) function.
  • This then led to very easy to use "scenario builder" systems for allocation planning.
  • Does this apply to the hourly timestep simulation or just the "scenario builder" simulation?
  • Need to get with Gary and Gopal to insure that my interpretation is correct

If this is correct:

  • If part of hourly simulation, can we implement this component rapidly in Openmi-om?
  • Can we pilot the same sort of thing for a fecal coliform in Openmi-om?
  • Does it do a good job of understanding outliers like the 2001-2002 ultra dry period (meaning lots of accumulation) followed by the 2003-2004 ultra-wet period (lots of flushing of pollutants) and explain the "banana curves" of the time.
  • If not, would a neural net approach be better?
  • Does their scenario builder provide for seasonally varying simulation solutions?
  • Is the S builder robust in the face of hydrologic alterations instream?

Transforming an object from the old "reference class" or S4 verfsion of object to R6:

  • Base class declaration function: Change SetRefClass(... to R6Class(
  • Syntax for inheritance: Change: contains = "openmi.om.linkableComponent", to inherit = openmi.om.linkableComponent, (notice no quot3es around class name -- very important)
  • referencing the object local fields. In R6, need to use the self$ prefix before class attributes, so data changes to self$data
  • Referencing super class methods:
    • change "callSuper()" to "super$methodname()"
  • The "<<-" for assignment of self attributes goes to "<-"

S4 version:

#****************************
# Override logState() method and has write method on finish()
#****************************
#' The base class for logging component data.
#'
#' @param
#' @return reference class of type openmi.om.linkableComponent
#' @seealso
#' @export openmi.om.logger
#' @examples
openmi.om.logger <- setRefClass(
  "openmi.om.logger",
  fields = list(
    directory = "character",
    path = "character",
    filename = "character",
    outputs = "ANY"
  ),
  contains = "openmi.om.linkableComponent",
  # Define the logState method in the methods list
  methods = list(
    update = function () {
      callSuper()
    },
    initialize = function () {
      callSuper()
    },
    logState = function () {
      callSuper()
      if (!is.xts(outputs)) {
        # first time, we need to initialize our data columns which includes timestamp
        # @todo: be more parsimonius?
        outputs <<- xts(data.frame(data), order.by = as.POSIXct(data$thistime))
      } else {
        outputs <<- rbind(outputs, xts(data.frame(data), order.by = as.POSIXct(data$thistime)))
      }
    }
  )
)

R6 version

#****************************
# Override logState() method and has write method on finish()
#****************************
#' The base class for logging component data.
#'
#' @param
#' @return reference class of type openmi.om.linkableComponent
#' @seealso
#' @export openmi.om.logger
#' @examples
openmi.om.logger <- RClass(
  "openmi.om.logger",
  inherit = openmi.om.linkableComponent,
  public = list(
    directory = "character",
    path = "character",
    filename = "character",
    outputs = "ANY"
  ),
  inherit = openmi.om.linkableComponent,
  # Define the logState method in the methods list
  methods = list(
    update = function () {
      callSuper()
    },
    initialize = function () {
      callSuper()
    },
    logState = function () {
      callSuper()
      if (!is.xts(outputs)) {
        # first time, we need to initialize our data columns which includes timestamp
        # @todo: be more parsimonius?
        outputs <<- xts(data.frame(data), order.by = as.POSIXct(data$thistime))
      } else {
        outputs <<- rbind(outputs, xts(data.frame(data), order.by = as.POSIXct(data$thistime)))
      }
    }
  )
)

Basic OpenMI components in R

Martins Lake

# give the existing OM model a runoff container
php copy_element.php 140 353071 340286 1

# copy the runoff container back to vahydro element
drush scr modules/om/src/om.migrate.element.php prop_feature 353075 6787091
# copy the cbp6 child
drush scr modules/om/src/om.migrate.element.php prop_feature 353077 6787337
# copy the landseg child

# use nhd to populate the landuse matrix
php set_elemNHDlanduse.php 353079 landuse cova_parent acres cbp6

# migrate back to vahydro

set ar_data in components (processors) during prepare()

  • OM subcomponents get values from the parent state via a push from the parent (not a pull)
    • om did this at the beginning of execProcessors(), which was called by step():
      • checked to see if it already had an $arData array, if so, it merged arData with state, otherwise, just use state
    • But should this be done as a "pull" from the child in getInputs()?
      • the step() method is called for each sub-comp in parent execProcessors()
      • step() in turn calls preStep(), execProcessors(), evaluate() (if present), and postStep()
      • preStep() calls the local objects setStateTimerVars(), readParentBroadCasts(), getInputs(), and sendChildBroadCasts()
      • possibly "getInputs" would be an appropriate place for subcomp to retrieve $ar_data from parent as a pull?
  • OM wrote values to the parent state in 2 different ways:
    • The parent harvested the child "value" property at the end of execProcessors(), instead of letting the child push to the parent.
    • Some children definitely set values on their parent using local subcomp values in the $wvars array
      • particularly those with multiple things to set, with special names like "impoundment" setting "impoundment_Qout", "impoundment_use_remain_mg" and dataMatrix components which can be configured to automatically set a variable with the compname + "_" + column_header_name ...
      • Base Class functions:
        • called in child method postStep()
        • method writeToParent($vars = array()) - if $vars is empty, writes all in property $this->wvars
        • Variable to write must be present in the object $state array
        • Calls parent method setStateVar(), as $this->parentobject->setStateVar($this->getParentVarName($thisvar), $this->state[$thisvar])
        • the only thing that is not written on parent in this method is the $value attribute
      • Examples:
        • dataMatrix:
          • This has a subclass implementation to add extra variables to write to parent if object property$autosetvars evaluates to TRUE
          • subState() method adds the names in the header row of the $matrix_rowcol to the $wvars array
          • evaluate() method calls setStateVar() for each column name in $autovars, these are then
  • Structure/Design: The pushing from parent to child $ar_data is one area where the distinction between contained entities and sub-components is very useful, since:
    • we have a default behavior for sub-comps to set a value in the parent state array for use by other sub-comps.
    • BUT! We could simply make this a feature of the contained child, if it is a descendent of a sub-comp or implements a sub-comp interface then it could simply set a value, if not, it could do nothing. Then, perhaps the question of sub-comp or standalone becomes moot?
    • OR we could simply query every child getValue() (get_value()) method after update() by the parent, and set a state variable with the name of the child, and be done with it. This would only be problematic if the child had a reserved keyword as a name, in which case we could enforce that by using child$id, and insuring no reserved words there... but that sucks because then subcomps could have name conflicts with children.
    • Why is this bad? In a given model container domain, it may be very reasonable to have unique names required. We work hard to provide that with the localhost:id:name:... so maybe it can be used effectively for this, and for tracking linkages.
function step() {
  $this->preStep(); # calls getInputs()
  $this->execComponents(); # calls step() on all child objects, not sub-comps)
  $this->execProcessors(); # calls each sub-comp om this object
...
}
function execProcessors() {
  ...
  if (is_array($this->arData)) {
    $statearr = array_merge($this->state,$this->arData);
  } else {
    $statearr = $this->state;
  }
  $this->processors[$thisvar]->arData = $statearr;
...
}

In R we will:

  • put this into the update() function

R implementation of modelObject, modelSubObject and basic equation object OM

Equation Evaluation

  • evaluate() function uses "tryCatch"
  • see also #1

    evaluate = function(){
      value <- tryCatch(
        {
          safe_envir <- c(self$data, self$arithmetic_operators)
          #value <-eval(parse(text=self$equation), envir=safe_envir)
          value <-eval(self$eq, envir=safe_envir)
        },
        error=function(cond) {
          # if no. of errors not exceeded,
          self$numnull <- self$numnull + 1
          if (self$numnull <= 5) {
            message(paste("Could not evaluate"))
            message(cond)
          }
          # Choose a return value in case of error
          value <- self$defaultvalue
        }
      )
      if (typeof(value) == 'closure') {
        # Choose a return value in case of error
        self$numnull <- self$numnull + 1
        if (self$numnull <= 5) {
          message(paste("Eval returned a function - check equation names for reserved words with undefined local values"))
          message(self$data)
        }
        value <- self$defaultvalue
      }
      return(value)
    }

References

Objects

Time-stepping issue adding 86400 seconds sporadically results in increase of 18 hours instead of 24

We had to use lubridate to increment dates because without lubridate, daylight savings time causes the increment of days in seconds to cause a shift in time (i.e. 1 hour forward or back). When initially starting Rstudio and running a simulation, the time-stepping behaves predictably. i.e.:
'''

as.POSIXlt('1999-03-14')
[1] "1999-03-14 EST"
as.POSIXct('1999-03-14') + seconds(86400)
[1] "1999-03-15 EST"
'''

Then, later simulations show an error (not sure if there is a specific time that this error occurs or not).
'''

as.POSIXlt('1999-03-14')
[1] "1999-03-14 EST"
as.POSIXct('1999-03-14') + seconds(86400)
[1] "1999-03-14 19:00:00 EST"

'''

Check Components for Missing Inputs at preStep() or init(), handle missing values gracefully

If someone creates an equation that references variables that don't exist, this should not cause a catastrophic error, but should result in very stern warnings to the user. Default values of 0.0 should be set for any missing var.

  • Each variable should be checked at start of simulation, maybe init() method or preStep() first time (see code below)
  • Handle bad values after init(): Current behavior uses tryCatch() and proceeds without failing, but is less descriptive than the proposed approach would yield. See: #55

Pre Evaluation of Present Variables in init()

Consider this snippet of code, where for_suro is DEFINED, but pas_suro is UNDEFINED in the array data:

data <- list(
  for_suro = 1.1
)
eqstring <- 'for_suro + pas_suro'
eqx <- parse(text=eqstring)
eval(eqx, data)
   Error in eval(eqx, data) : object 'pas_suro' not found

We should be able to use getParseData(), which returns the following info about our expression:

eqinfo = getParseData(eqx)
  line1 col1 line2 col2 id parent  token terminal     text
7     1    1     1   19  7      0   expr    FALSE         
1     1    1     1    8  1      3 SYMBOL     TRUE for_suro
3     1    1     1    8  3      7   expr    FALSE         
2     1   10     1   10  2      7    '+'     TRUE        +
4     1   12     1   19  4      6 SYMBOL     TRUE pas_suro
6     1   12     1   19  6      7   expr    FALSE     

To extract those variables that are requested, we can use:

eqvars <- eqinfo[eqinfo$token == "SYMBOL",]
eqvars
  line1 col1 line2 col2 id parent  token terminal     text
1     1    1     1    8  1      3 SYMBOL     TRUE for_suro
4     1   12     1   19  4      6 SYMBOL     TRUE pas_suro

And then set defaults appropriately, perhaps at the "getInputs()" method of the Equation class.

Flatlick Branch Model

  • Create shape in db:
    • cd /var/www/html/om/; php get_nhd_basins.php "Flatlick Branch" 38.8823899 -77.4319047
Successfully connected to:
Outlet COMID : 22338645
Outlet Cumulative Area : 4.217393882757
Outlet Local Area : 3.151
Finding Merged Shape 38.8823899 -77.4319047
Shape NOT in NHD+ Merged basin geometry cache .. calculating.

Basin Info flow_segmentsArray
(
    [0] => 22338645
    [1] => 22338597
    [2] => 22338567
    [3] => 22340947
    [4] => 22338591
    [5] => 22338649
)
  • Export to vahydro format
psql -h dbase1 va_hydro
  copy (
    select 'Flatlick Branch' as name, comid as hydrocode, 
    st_astext(the_geom) as wkt, 'watershed' as bundle, 'vahydro' as ftype 
    from nhd_fulldrainage 
    where comid = '22338645'
  ) to '/tmp/flatlick_branch.wkt' WITH HEADER CSV DELIMITER AS E'\t';
  • Retrieve via sftp
cd ../files/vahydro/
sftp dbase1 
get /tmp/flatlick_branch.wkt
bye
  • Import to vahydro
cd /var/www/html/d.dh
drush scr modules/dh/src/import_features.php /var/www/html/files/vahydro/flatlick_branch.wkt

> Saving Flatlick Branch 8468831
> hydroid = 485176 
  • add blank component to local tribs folder of containing watershed
cd ../om
php fn_copy_element.php 37 337676  241227
> elementid = 353061
  • migrate back to vahydro
cd ../d.dh
drush scr modules/om/src/om.migrate.element.php feature 353061 485176
  • Set to "push always" in vahydro
  • Get channel info from nhd+, and manually update vahydro model object:
php fn_getNHDChannelInfo.php 38.8823899 -77.4319047
Initializing nhdPlusDataSource <br>  select comid, areasqkm from nhdplus_catchment  where st_contains(the_geom, st_setsrid(st_makePoint(-77.4319047, 38.8823899),4269))     AND the_geom && st_setsrid(st_makePoint(-77.4319047, 38.8823899),4269)  ; <br>

  select b.*, a.areasqkm, (0.386102159 * c.cumdrainag) as cumdrainag  from nhdplus_catchment as a, nhdplus_catt_nlcd as b,      nhdplus_flatt_flow as c  where a.comid = 22338645      and b.comid = 22338645      and c.comid = 22338645 ; <br>

Searching for coords: 38.8823899, -77.4319047 <br>NLCD Land Use: Array
(
    [nlcd_11] => 21.1284534411975
    [nlcd_12] => 0
    [nlcd_21] => 883.850090038175
    [nlcd_22] => 0
    [nlcd_23] => 277.336823114622
    [nlcd_31] => 0
    [nlcd_32] => 0
    [nlcd_33] => 87.845467764541
    [nlcd_41] => 603.376674942068
    [nlcd_42] => 119.216374084159
    [nlcd_43] => 143.234865971071
    [nlcd_51] => 0
    [nlcd_61] => 0
    [nlcd_71] => 0
    [nlcd_81] => 420.801716832116
    [nlcd_82] => 0.2223296843585
    [nlcd_83] => 0
    [nlcd_84] => 0
    [nlcd_85] => 105.641123579337
    [nlcd_91] => 32.6927501864815
    [nlcd_92] => 3.7809906460395
    [area_cn] => 0
    [area_mx] => 0
    [sum_pct] => 99.9999966666667
)
<br>Channel Slope: 0.007<br>Channel Length(mi): 2.7<br>Channel Drainage Area (Sq. Mi.): 4.22<br>
  • Add a runoff object (this is important here in this urban watershed)
omid=353061 # OM element
drid=6785282 # Drupal element
landseg='N51059'
riverseg='PL2_4970_5250'
unrseg="_$riverseg"
lrseg="$landseg$unrseg"
hydroid=485176# drupal shape

# Copy "1. Local Runoff Inflows" sub-components
drush scr modules/om/src/om_create_pair.php cmd 352125 $omid $drid om_model_element "1. Local Runoff Inflows" prop_feature
lrid=`drush scr modules/om/src/om_getpid.php dh_properties $drid "1. Local Runoff Inflows"`
omlrid=`drush scr modules/om/src/om_getval.php dh_properties $lrid "om_element_connection"`

# Copy a "CBP6 Flows" object as child of newly created Local Runoff...
drush scr modules/om/src/om_create_pair.php cmd 352127 $omlrid $lrid om_model_element "CBP6 Flows" prop_feature
cbid=`drush scr modules/om/src/om_getpid.php dh_properties $lrid "CBP6 Flows"`
omcbid=`drush scr modules/om/src/om_getval.php dh_properties $cbid "om_element_connection"`

# create a first land segment
drush scr modules/om/src/om_create_pair.php cmd 352129 $omcbid $cbid om_class_cbp_eos_file "$lrseg" prop_feature CBPLandDataConnectionFile 37
lrsid=`drush scr modules/om/src/om_getpid.php dh_properties $cbid "$lrseg"`
omlrsid=`drush scr modules/om/src/om_getval.php dh_properties $lrsid "om_element_connection"`
# set land and river seg
drush scr modules/om/src/om_setprop.php cmd dh_properties $lrsid om_class_AlphanumericConstant landseg 0.0 $landseg 
drush scr modules/om/src/om_setprop.php cmd dh_properties $lrsid om_class_AlphanumericConstant riverseg 0.0 $riverseg 

  • Set the runoff element shape
echo "copy (select a.name, a.hydrocode, st_astext(b.dh_geofield_geom) as wkt, a.bundle, a.ftype from dh_feature as a left outer join field_data_dh_geofield as b on (a.hydroid = b.entity_id and b.entity_type = 'dh_feature') where a.hydroid = $hydroid) to '/tmp/$hydroid.wkt' WITH HEADER CSV DELIMITER E'\t';" | psql -h dbase1 drupal.dh03
  • set land use areas
cd ../om
php set_elemNHDlanduse.php $omlrsid landuse cova_parent acres cbp6
cd ../d.dh
drush scr modules/om/src/om.migrate.element.php pid $omlrsid $lrsid landuse "" "" "" varcode

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.