Created
November 30, 2017 22:02
-
-
Save pyRobShrk/7339d86fed92f628ab5b3b558801e5f8 to your computer and use it in GitHub Desktop.
HEC-DSSVue Jython script to import time series from HEC-RAS water quality output file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# name=HEC-YEAH | |
# description=HEC-YEAH | |
# description=Aimee Kindel and Rob Sherrick, HDR, Inc. | |
# description=This script unlocks the cryptic file storage of the HEC-RAS Water Quality Module output (*.wq##) | |
# description=On line 101: "range(1,ct+1,4):" says to output only every fourth WQ cell (for speed). | |
# description=On line 105: You may want to change "FPART" to something more descriptive. | |
# displayinmenu=false | |
# displaytouser=true | |
# displayinselector=false | |
from hec.script import * | |
from hec.heclib.dss import * | |
from hec.hecmath import * | |
from hec.io import TimeSeriesContainer | |
from hec.heclib.util import HecTime | |
from hec.dssgui import ListSelection | |
from javax.swing import JFileChooser | |
import java | |
import struct | |
LS = ListSelection.getMainWindow() | |
file = LS.getSelectedPathnames()[0].getFilename() | |
def fourByteFloat(str): | |
return struct.unpack('>f',str[::-1])[0] | |
def fourByteInt(str): | |
return struct.unpack('>I',str[::-1])[0] | |
def eightByteDouble(str): | |
return struct.unpack('>d',str[::-1])[0] | |
#print(fourByteInt("P\x15\x00\x00")) #5456 | |
wqFile = JFileChooser() | |
wqFile.showOpenDialog(None) | |
File = wqFile.getSelectedFile() | |
readWQ = open(File.getAbsolutePath(),"rb") | |
print readWQ.read(32) #FIRST TIME SERIES POINTER | |
tsPointer = fourByteInt(readWQ.read(4)) | |
print readWQ.read(32) #TIME SERIES POINTER OFFSET | |
tsCount = fourByteInt(readWQ.read(4)) - 3 | |
print readWQ.read(44) #VERSION | |
print readWQ.read(32) #STARTING DATE | |
stDate = readWQ.read(9) | |
print readWQ.read(3) #extra bytes after date | |
print readWQ.read(32) #STARTING TIME | |
stTime = readWQ.read(4) | |
print readWQ.read(36*4) #NUMBER OF STORAGE AREAS (SA), NUMBER OF REACHES, NUMBER OF VARIABLE GROUPS (VG), VG TIME SERIES OVERALL | |
print readWQ.read(32*2) #Time DOUBLE PRECISION DAYS | |
print readWQ.read(36) #VG CROSS SECTIONS (XS) | |
print readWQ.read(32) #Water Temperature | |
print readWQ.read(64) #C RIVER NAME, REACH NAME, NUM XS | |
riverName = readWQ.read(16) | |
print readWQ.read(16) #reachName | |
ct = fourByteInt(readWQ.read(4)) | |
bPartList = [] | |
for a in range(ct): | |
readWQ.read(36) #RIVER NAME, REACH NAME, NUM XS 0001 | |
bPartList.append('%03d-'%a + '-'.join([s for s in readWQ.read(32).split(' ') if s])) | |
readWQ.read(36) #blank space with last four as WQ Cell Length | |
print readWQ.read(32) #START OF TIME SERIES DATA | |
hecTime = HecTime() | |
hecTime.set(stDate + " " + stTime) | |
rowLen = (ct+2)*4 | |
#load TS data into memory, ~40 MB at a time | |
while True: | |
data = readWQ.read(rowLen * int(4e7 / rowLen)) | |
rowCt = len(data)/rowLen | |
timeOffset = int(eightByteDouble(data[0:8])*24*60) #in minutes | |
if timeOffset == 0: | |
timeStep = int(eightByteDouble(data[rowLen:rowLen+8])*24*60) #in minutes | |
if timeStep < 60: | |
tsText = "%iMIN" % timeStep | |
elif timeStep < 1440: | |
tsText = "%iHOUR" % int(timeStep/60) | |
else: | |
tsText = "%iDAY" % int(timeStep/1440) | |
print "Time Step is %i minutes. '%s'" % (timeStep,tsText) | |
#Set up template TimeSeriesContainer | |
tsc = TimeSeriesContainer() | |
tsc.watershed = riverName | |
tsc.parameter = "TEMP" | |
tsc.interval = timeStep | |
times = [] | |
for row in range(rowCt): | |
times.append(hecTime.value()) | |
hecTime.add(tsc.interval) | |
tsc.times = times | |
tsc.startTime = times[0] | |
tsc.endTime = times[-1] | |
tsc.numberValues = rowCt | |
tsc.units = "C" | |
tsc.type = "INST-VAL" | |
#write the data!!! | |
fOpen = DSS.open(file) | |
for a in range(1,ct+1,4): | |
col = (a+1)*4 | |
tsc.values = [ fourByteFloat( b[col:col+4] ) for b in [ data[c:c+rowLen] for c in range(0,rowCt*rowLen,rowLen) ]] | |
tsc.location = bPartList[a-1] | |
tsc.fullName = "/%s/%s/%s//%s/%s/" % (riverName,bPartList[a-1],"TEMP",tsText,"FPART") | |
theRecord = HecMath.createInstance(tsc) | |
fOpen.write(theRecord) | |
fOpen.close() | |
if len(data) < rowLen * int(4e7 / rowLen): | |
break | |
readWQ.close() | |
LS.refreshCatalog() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment