C+
C NAME:
C	iHOSRead
C PURPOSE:
C	Read record from Helios data file
C CATEGORY:
C	I/O
C CALLING SEQUENCE:
C	I = iHOSRead(iD,iU,iRecl,iR,T,P,C,F,R,L,N,Z)
C INPUTS:
C	iD	integer		iD=-1 : read record iR
C				iD>= 0: read next record (starting at iR+1) meeting input
C					restrictions on photometer, color and filter
C		Counting digits from the right (least-significant first)
C		1st digit	= 0 :	include all photometers
C				= 1 :	only 16 deg photometer
C				= 2 :	only 31 deg photometer
C				= 3 :	only 90 deg photometer
C				= 4 :	include 16 and 31 deg photometers
C				= 5 :	include 31 and 90 deg photometers
C				= 6 :	include 16 and 90 deg photometers
C		2nd digit	= 0 :	include all color filters
C				= 1 :	only color UV
C				= 2 :	only color Blue
C				= 3 :	only color Visual
C				= 4 :	include UV and Blue
C				= 5 :	include Blue and Visual
C				= 6 :	include UV and Visual
C		3rd digit	= 0 :	include all polarization filters
C				= 1 :	only color filter 1
C				= 2 :	only color filter 2
C				= 3 :	only color filter 3
C				= 4 :	only color filter 4 (clear filter)
C				= 5 :	only color 'filter' 5 (pB)
C				= 6 :	include filters 4 and 5 (clear and pB)
C		4th digit	= 1 :	negate photometer/color/filter selection
C	iU	integer		logical unit number for data file
C	iRecl	integer		record length in (4-byte) long words
C	iR	integer		record number to be read
C	N	integer		# sectors to be returned in Z
C				MUST BE EVEN. UNEVEN VALUES WILL BE ROUNDED DOWN TO AN EVEN VALUE
C				Sectors 1..N/2     will be put in Z(1)..Z(N/2)
C				Sectors 33-N/2..32 will be put in Z(N/2+1)..Z(N)
C OUTPUTS:
C	iR	integer		(negative iD only)
C				On read error (or EOF), iR will be the record number of the last
C				successfully read record. For iD=-1 this would be the same as the input
C				value.
C				If read was OK, then iR will be the number of the record read
C				successfully. For iD=-1 this will be iR+1 (i.e. record counter is
C				incremented by 1).
C	T	real		time (doy)
C	P	integer		photometer (1/2/3)
C	C	integer		color (1/2/3)
C	F	integer		filter (1..5) (if P=3 then F=4)(4=Clear,5=pB)
C	R	real		heliocentric distance (AU)
C	L	real		topocentric ecliptic longitude (deg) of the Sun
C	Z(N)	real		intensities
C				IP=3: Z(1) = intensity, Z(2) = pB
C FUNCTIONS/SUBROUTINES:
C	Signal, ArrR4NARN, cInt2Str, CvR4
C EXTERNAL:
C INCLUDE:
C COMMON BLOCKS:
C SIDE EFFECTS:
C RESTRICTIONS:
C PROCEDURE:
C MODIFICATION HISTORY:
C	SEP-1998, Paul Hick (UCSD; pphick@ucsd.edu)
C-
	function iHOSRead(iD,iU,iRecl,iR,T,PP,CC,FF,R,L,NN,ZZ)
	integer		PP,CC,FF
	integer*2	P, C, F, B		! Used to read/write file

	parameter	(nS=32)
	real		ZZ(*), Z(nS), L

	character	cStr*100, cInt2Str*14

	real		BadHOS		/-1E7/

	integer*2	POld		/3/
	save		POld

	integer		k2(0:6)		/4*0,3,1,2/

	logical		bAlign,
     &			bFirst		/.TRUE./
	character	cAlign
	save		bFirst, bAlign

	logical		bRead, bWrongType, bNegate, bNative
	bNative(T,R,L) =  0.25 .lt. R .and. R .lt. 1.05

	if (bFirst) then
	    bAlign = iGetSymbol('HOS_ALIGN',cAlign) .ne. 0
	    if (bAlign) bAlign = cAlign .eq. '1'
	    bFirst = .FALSE.
	end if

	N = NN/2*2				! Round down to even number

	Bad = BadR4()

	if (iRecl .eq. 6) POld = 3		! Force reading of phot 3 record (iS=0)
	iS  = (iRecl-4.5)/2			! Half # Sectors in phot 1 or 2 record

	kP = max(-1,iD)
						! Auto-Increment record counter
	if (kP .ge. 0) then			! No 16/31 deg records on 90 deg file
	    bNegate = kP .gt. 1000

	    kF = mod(kP,1000)/100		! Filter selection
	    kC = mod(kP, 100)/ 10		! Color selection
	    kP = mod(kP,  10)/  1 		! Photometer selection

	    if (kP .eq. 3) kF = 6		! Clear+pB

	    if ((kP .eq. 1 .or. kP .eq. 2 .or. kP .eq. 4) .and. iRecl .eq. 6) then
		iHOSRead = -1			! Simulate read error (note that iR is not incremented)
		return
	    end if
						! Make sure to read proper record type
C	    if (1 .le. kP .and. kP .le. 3) POld = kP
C	    if (kP .eq. 4) POld = 1
	    iR = iR+1				! Increment counter
	end if

	bRead = .TRUE.
	do while (bRead)
	    if (POld .eq. 3) then
		read (iU,rec=iR,iostat=iHOSRead) T,P,C,    R,L,(Z(I),I=1,2)
	    else if (bAlign) then
		read (iU,rec=iR,iostat=iHOSRead) T,P,C,F,B,R,L,(Z(I),I=1,iS),(Z(I),I=nS+1-iS,nS)
	    else
		read (iU,rec=iR,iostat=iHOSRead) T,P,C,F,  R,L,(Z(I),I=1,iS),(Z(I),I=nS+1-iS,nS)
	    end if

	    if (iHOSRead .ne. 0) then		! Read error
		if (iR .eq. 1) then
		    cStr = 'error '//cInt2Str(iHOSRead)//' on record '//cInt2Str(iR)//' of'
		    I = iwhitespace(cStr)
		    inquire(iU,name=cStr(I+2:))
		    if (itrim(cStr(I+2:)) .gt. 0) call Signal('iHOSRead','W','Read',cStr)
		end if
						! If error is EOF then IR becomes # records on file
		if (kP .ge. 0) iR = iR-1	! Decrement record counter
		return
	    end if

	    bWrongType = (POld .eq. 3 .and. P .ne. 3) .or. (POld .ne. 3 .and. P .eq. 3)

	    if (kP .eq. -1) then		! Read single record and return
		bRead = bWrongType
		if (bRead) POld = P		! Read same record if wrong type

	    else				! Use selection criteria
C-------
C Check whether the record just read passes the selection criteria on filter, color and photometer
C If it doesn't, set bRead = .TRUE.
C Note that if the record was read with the wrong type the filter F may not be available. In that
C case it is possible to positively reject the record if it doesn't fit the color and photometer
C selection, but it is not possible to determine whether it completely fits the selection.

		bRead = (1 .le. kP .and. kP .le. 3 .and. kP	.ne. P) .or.
     &			(4 .le. kP .and. kP .le. 6 .and. k2(kP) .eq. P)

		if (.not. bRead) bRead = 	! Unnormalized data have C=101,102,103
     &			(1 .le. kC .and. kC .le. 3 .and. kC	.ne. mod(C,100)) .or.
     &			(4 .le. kC .and. kC .le. 6 .and. k2(kC) .eq. mod(C,100))
						! F is not available if wrong record type was read
		if (.not. bRead .and. .not. bWrongType) bRead =
     &			(P .ne. 3 .and. 1 .le. kF .and. kF .le. 5 .and. kF .ne. F) .or.
     &			(P .ne. 3 .and. kF .eq. 6 .and. F  .ne. 4 .and. F  .ne. 5) .or.
     &			(P .eq. 3 .and. 1 .le. kF .and. kF .le. 3)

		if (bRead) then			! Record did not fit selection criteria
		    if (bNegate) then		! If negating ..
			bRead = bWrongType	! .. accept, or read same record again
			if (bRead) POld = P
		    else			! If regular selection ..
			iR = iR+1		! .. reject record and read next one
		    end if
		else if (bWrongType) then	! Record was read with wrong type, so read again
		    bRead = .TRUE.
		    POld = P			! This time with proper photometer setting
		else if (bNegate) then		! Record fit the selection criteria
		    bRead = .TRUE.
		    iR = iR+1			! If negating reject record and read next one
		end if

	    end if

     	end do

	if (.not. bNative(T,R,L)) then		! Real*4 conversion needed
	    call CvR4(1,1,T)
	    call CvR4(1,1,R)
	    call CvR4(1,1,L)

	    if (P .eq. 3) then
		call CvR4(1, 2,Z)
	    else
		call CvR4(1,iS,Z)
		call CvR4(1,iS,Z(nS+1-iS))
	    end if
	end if

	if (P .eq. 3) then
	    F = 4
	    call ArrR4Mask( -2,Z,BadHOS,Bad,0.,0.,1.,Z)	! Flag -1E7 (old Helios files)

	    call ArrR4Copy(2,Z,ZZ)			! Copy into output array
	    call ArrR4NARN(N-2,ZZ(3))			! Flag unused elements in output array
	else
	    call ArrR4NARN(nS-2*iS,Z(iS+1))		! Flag sectors which are not in file
	    call ArrR4Mask(-nS,Z,BadHOS,Bad,0.,0.,1.,Z)	! Flag -1E7 (old Helios files)

	    iS = N/2
	    call ArrR4Copy(iS,Z,ZZ)	    		! Copy sectors 1..iS
	    call ArrR4Copy(iS,Z(nS+1-iS),ZZ(N+1-iS))	! Copy sectors 33-iS..32
	end if

	PP = P						! Integer*4 output
	CC = C
	FF = F

	return

	entry iHOSWrite(iD,iU,iRecl,iR,T,PP,CC,FF,R,L,NN,ZZ)

	if (bFirst) then
	    bAlign = iGetSymbol('HOS_ALIGN',cAlign) .ne. 0
	    if (bAlign) bAlign = cAlign .eq. '1'
	    bFirst = .FALSE.
	end if

	N = NN/2*2				! Round down to even number

	P = PP					! Integer*4 input
	C = CC
	F = FF

	if (P .eq. 3) then
	    call ArrR4Copy(2,ZZ,Z)		! Copy into output array
	else
	    iS = N/2
	    call ArrR4Copy(iS,ZZ,Z)	    	! Copy sectors 1..iS
	    call ArrR4Copy(iS,ZZ(N+1-iS),Z(nS+1-iS)) ! Copy sectors 33-iS..32
	    call ArrR4NARN(nS-2*iS,Z(iS+1))	! Flag sectors which are not present
	end if

	iS  = (iRecl-4.5)/2			! Half # Sectors in phot 1 or 2 record
	if (iD .ge. 0) iR = iR+1		! Increment record counter

	if (P .eq. 3) then
	    write (iU,rec=iR,iostat=iHOSWrite) T,P,C,    R,L,(Z(I),I=1,2)
	else if (bAlign) then
	    write (iU,rec=iR,iostat=iHOSWrite) T,P,C,F,B,R,L,(Z(I),I=1,iS),(Z(I),I=nS+1-iS,nS)
	else
	    write (iU,rec=iR,iostat=iHOSWrite) T,P,C,F,  R,L,(Z(I),I=1,iS),(Z(I),I=nS+1-iS,nS)
	end if

	if (iHOSWrite .ne. 0) then		! Write error
	    cStr = 'error '//cInt2Str(iHOSWrite)//' on record '//cInt2Str(iR)//' of'
	    I = iwhitespace(cStr)
	    inquire(iU,name=cStr(I+2:))
	    call Signal('iHOSWrite','W','Write',cStr)

	    if (iD .ge. 0) iR = iR-1		! Decrement record counter
	end if

	return
	end