In version 6 of HEC-DSS, you can store a single 32-bit integer with each data value, which usually is reserved for a data quality flag. In version 7, the quality flag is not limited to a single 32-bit integer, but you specify the number of integers per value. (Although you can have more than one integer for a quality flag, older programs may not be compatible with this.)
Quality 32-bit ints are set in TimeSeriesContainer with the "setQuality" function:


public int setQuality(int quality[]);
JAVA


For larger than single int quality use the "setQuality7" function:

public int setQuality7(int quality[][]);  
JAVA

The extra columns of quality in version 7, allows for future expansion of more information about the quality flag.  For example, the first quality flag might say exceeded a maximum value, and the additional information might be what that maximum was, and another quality could be what a corrected estimate should be.


Where quality is dimensioned as int quality[number data][size quality in ints], for example quality[744][2];
To retrieve quality flags, use the following functions:


public int[] getQuality()
public int[][] getQuality7()
public int getQualitySize()
JAVA


Where getQualitySize will return 0 (zero) for no quality flags set, 1 (one) for single (32-bit) quality flags, or a value greater than one for multiple int quality flags stored in qulity7 (DSS version 7 only.) You cannot store both single int quality and multiple int quality.

Quality Bit Settings


Single int Quality flag conventions were adopted in 1980 (for program DATCHK) and set bits as follows (where 1 is first bit, often referred to as zero):
1: Screened - set when original data has been screened
Quality of original data:
2: Okay
3: Missing
4: Questionable
5: Reject
6-7: Range of current data- an integer in [0,3]
8: Current value is different from original value
9-11:  Program Modification: - an integer in [0,7]
   0 original value, no revision
   1 DATCHK
   2 DATVUE
   3 manual entry in DATVUE
   4 original value accepted in DATVUE
12-15: Replacement method- an integer in \[0, 15\]
   0 no revision
   1 linear interpolation
   2 manual change
   3 replace with missing value

Tests Failed:
16: absolute magnitude
17: constant value
18: rate-of-change
19: relative magnitude
20: duration-magnitude
21: negative incremental value
22: not defined
23: gage list
24: not defined
25: user-defined test
26: distribution test

32: protect value from automatically being changed.



Data Quality Rules:


  • Unless the Screened bit is set, no other bits can be set.
  • Unused bits (22, 24, 27-31, 32+) must be reset (zero).
  • The Okay, Missing, Questioned and Rejected bits are mutually exclusive.
  • No replacement cause or replacement method bits can be set unless the changed (different) bit is also set, and if the changed (different) bit is set, one of the cause bits and one of the replacement method bits must be set.
  • Replacement Cause integer is in range 0..4.
  • Replacement Method integer is in range 0..4
  • The Test Failed bits are not mutually exclusive (multiple tests can be marked as failed).



Bit Mappings



Example: Regular-interval time series data with single int Quality flags

import javax.swing.UIManager;
import hec.heclib.dss.*;
import hec.heclib.util.HecTime;
import hec.heclib.util.HecTimeArray;
import hec.io.TimeSeriesContainer;

//  Regular interval time series data with single int quality flags 
public class ExampleTimeSeries7 {

	public static void main (String args[])  {		

		try {
			javax.swing.UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch (Exception ignore) {}
		
		//  Write a regular interval data set.  Gen up the data			
		double values[] = new double[200];	
		int quality[] = new int[200];
		for (int i=0; i<values.length; i++) {
			values[i] = (double)i;
			//  set evens to 3, odds to 5
			if ((i & 1) == 0) {
				quality[i] = 3;
			}
			else {
				quality[i] = 5;
			}
		}
		
		TimeSeriesContainer tsc = new TimeSeriesContainer();		
		HecTime hecTime = new HecTime("20Jan2010", "2400");
		tsc.setStartTime(hecTime);
		tsc.setName("/Basin/Location/Flow//1Hour/Quality/");
		tsc.setValues(values);
		tsc.setQuality(quality);
		tsc.units = "CFS";
		tsc.type = "Inst-Val";
		
		HecTimeSeries dssTimeSeries = new HecTimeSeries();	
		dssTimeSeries.setDSSFileName("C:/temp/Example7.dss");		
		int status = dssTimeSeries.write(tsc);
		dssTimeSeries.done();		
		if (status != 0) return;
		
		//  Read data
		TimeSeriesContainer tscRead = new TimeSeriesContainer();
		//  Note - implicit time window given using D and E parts.
		//  A time window must be provided and there are several alternatives for doing this
		tscRead.fullName = "/Basin/Location/Flow/01Jan2010/1Hour/Quality/";
		HecTimeSeries dssTimeSeriesRead = new HecTimeSeries();
		dssTimeSeriesRead.setDSSFileName("C:/temp/Example7.dss");		
		status = dssTimeSeriesRead.read(tscRead, true);
		dssTimeSeriesRead.done();		
		if (status != 0) return;
		HecTimeArray hTimes = tscRead.getTimes();
		double vals[] = tscRead.getValues();
		int qual[] = tscRead.getQuality();
		if ((qual == null) || (vals == null) || (qual.length != vals.length)) return;
		for (int i=0; i<vals.length; i++) {
			System.out.println("Ordinate: " + i + ", time: " + hTimes.element(i).dateAndTime() + 
					", value: " + vals[i] + ", quality:" + qual[i] );
		}
		HecDataManager.closeAllFiles();
	}
}

JAVA