#!/usr/bin/python
from __future__ import print_function
import sys, struct, numpy as np

class Wdq(object):
	"""
	read windaq / wdq files
	
	http://www.dataq.com/resources/techinfo/ff.htm
	header elements (h1-h35) and channel header elements c1-c10
	are described in file above
	this class support only a subset of unpacked wdq-files.
	"""
	__next__ = next

	def __init__(self, filename):
		self._data = open(filename, mode='rb')
		self._head = self._data.read(1156)
		self._i = 0
		self._parseHead()
		

	def _parseHead(self):
		h1 = struct.unpack_from("<H", self._head)[0]
		self.nChannel = h1&31
		self.factor = np.empty(self.nChannel)
		h6 = struct.unpack_from("<L", self._head, 8)[0]
		rateDivisor = 1 # to be implemented
		self.nSample = (h6/(2*self.nChannel)-1)/rateDivisor+1
		for i in range(self.nChannel):
			c3 = struct.unpack_from("<d", self._head, 110+36*i+8)[0]
			self.factor[i] = c3
		
	def printHead(self):
		print("samples            : {}".format(self.nSample))
		h1 = struct.unpack_from("<H", self._head)[0]
		h2 = struct.unpack_from("<H", self._head, 2)[0]
		nChannel = h1&31
		print("channels           : {}".format(nChannel))
		d = (h1>>5)&1023
		n = ((h1>>15)<<16) + h2
		print("sample rate        : {}/{} Hz".format(n, d))
		h3 = struct.unpack_from("B", self._head, 4)[0]
		print("offset of info     : {} bytes".format(h3))
		h4 = struct.unpack_from("B", self._head, 5)[0]
		print("channel self._header size: {} bytes".format(h4))
		h5 = struct.unpack_from("<h", self._head, 6)[0]
		print("file self._header size   : {} bytes".format(h5))
		h6 = struct.unpack_from("<L", self._head, 8)[0]
		print("unpacked data size : {} bytes".format(h6))
		for i in range(nChannel):
			print("channel {}:".format(i))
			c1 = struct.unpack_from("<f", self._head, 110+36*i)[0]
			c2 = struct.unpack_from("<f", self._head, 110+36*i+4)[0]
			c3 = struct.unpack_from("<d", self._head, 110+36*i+8)[0]
			c4 = struct.unpack_from("<d", self._head, 110+36*i+16)[0]
			print("  scaling slope    : {}".format(c1))
			print("  scaling intercept: {}".format(c2))
			print("  scaling factor   : {}".format(c3))
			print("  intercept factor : {}".format(c4))

	def __iter__(self):
		"""implement iterable"""
		return self
	
	def skip(self, n=1):
		"skip samples"
		self._data.seek(self.nChannel*2*n, 1)
		self._i += n
		
	def next(self, n=1):
		"implement iterator"
		if self._i >= self.nSample:
			raise StopIteration
		if n==1:
			d = self._data.read(self.nChannel*2)
			self._i += 1
			return np.array(struct.unpack("<"+"h"*self.nChannel, d), dtype="double")*self.factor
		else:
			if n == -1 or self._i + n > self.nSample:
				n = self.nSample-self._i
			d = self._data.read(n*self.nChannel*2)
			self._i += n
			a = np.array(struct.unpack("<"+"h"*(len(d)/2), d), dtype="double")
			return a.reshape([-1, self.nChannel])*self.factor
			
		
if __name__ == "__main__":
	if len(sys.argv) < 2:
		print("usage: import wdq")
		print("  or")
		print("usage: wdq.py <filename.wdq>")
		exit()

	f = Wdq(sys.argv[1])
	f.printHead()
	
	