Skip to content

Instantly share code, notes, and snippets.

@pyRobShrk
Created November 30, 2017 22:02
Show Gist options
  • Save pyRobShrk/7339d86fed92f628ab5b3b558801e5f8 to your computer and use it in GitHub Desktop.
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
# 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