C+ C NAME: C Connect C PURPOSE: C Connects separate data files into one big file C CATEGORY: C I/O: Helios C CALLING SEQUENCE: program Connect C INPUTS: C > The input files contain records in the usual structure (PHOTO_DATA or C 90DEG_DATA). They should contain only one particular color, but may C contain any number of photometers and filters. C > File names, start-, end- and transfer times (see procedure) C are read either from a file cFileL or from the keyboard. C > The file cFileL starts with an optional record containing two times C TBeg and TEnd indicating that only data between these two time limits C should be extracted. If this record is omitted TBeg=0 and TEnd=999. C Each subsequent record contains a file name and the corresponding C transfer time TNew, separated by a blank. C > All times are in day of year C OUTPUTS: C The output file name OUT (recl=37) is a 13 character string 'XYRLF_doy.ext' C C X = A or B for HELIOS A or B respectively; C YR = the year of observation (i.e. 78 for 1978); C L = U,B,V for U/B/V light respectively; C F = 1 through 5 depending on the filter (if the file contains C 15/30 deg photometer data); or C = 9 if the file contains only 90 deg photometer data (see NOTE); C doy = the day of year for the earliest data point. C ext = ZLD for unnormalized data files (i.e. original zodiacal light C data); or C = DAT for normalized data files C C The 90 deg data are optionally written to either a separate file C (with a '9' as fifth character and recl 6) or are appended to the file C OUT. C CALLS: C AskChar, AskI4, AskR4, AskWhat, AskYN, bOpenFile, iFreeLun, IndexR4 C Say, ArrR4Copy, ArrI4Index, ArrI4Zero, iHOSInfo, iHOSRead, iHOSWrite C iFilePath, iwhitespace, itrim, cFlt2Str, Str2StrSet, Str2Str, Int2Str C cInt2Str, iGetFileSpec, iSetFileSpec, iPutFileSpec, iUniqueName C INCLUDE: include 'dirspec.h' include 'filparts.h' include 'openfile.h' include 'str2str_inc.h' include 'hos_e9.h' C RESTRICTIONS: C > A zodiacal light model may already be subtracted ('normalized' data), C but not necesarily. All files should be of the same type: all or none C of the files are normalized; all files should contain the same color; C if this is not the case the program stops and no output is produced. C > WARNING: if you want to connect data from different years, say from C december 1976 to january 1977, 366 days should be added to the times C for the later year, e.g. doy 1.2345 of 1977 should become 367.2345. C There is an option in PANDORA which does that. C PROCEDURE: C > One specified filter will be extracted. The output file is sorted in C time. (Note that the program can also be run on one file, to extract C data for a specific time period, or to extract a specific filter). C > A period of time is covered by N subsequent (partly overlapping) data C files, file I+1 containing data later than file I (I=1,..,N-1). C Data will be copied to the output file using the following rules: C (1) Only data inside an overall time window TBeg <= T <= TEnd are C extracted C (2) The switch from one data file to the next is made at transfer times C TNew, which have to be specified for each file except the last C (if a value is given it should be larger than 999). C > For the I-th file data will be copied for which C TNew(I-1) <= T < TNew(I), C where TNew(0) = TBeg and TNew(N) = TEnd; C i.e. data up to the transfer time are copied; for the next file data C from the transfer time onwards are copied. C > The output files are created in the directory where the first data file C is found (usually, but not necessarily the working directory). C MODIFICATION HISTORY: C 1989, Paul Hick (UCSD) C- parameter (NBUF=100) ! Buffer size used for sorting times integer IBUF(3) /3*NBUF/ ! # empty buffer locations integer II(NBUF,3) ! Index array used for sorting real TT( NBUF,3) real RR( NBUF,3) real LL( NBUF,3) real ZZ(32,NBUF,3) character cFileL*80 ! List file character cFileI*80 ! Input file character cFileO*80 ! Output file character cFileS*80 ! Scratch file integer iUS(3) ! Unit number for scratch file integer iLS(3) ! Record length for scratch file integer iRS(3) ! Record number on scratch file character cColor(0:3) /'A','U','B','V'/ character cSc(2) /'A','B'/ character cNorm(0:1)*4 /'.dat','.zld'/ character cSay*7 /'Connect'/ character cStr*120 logical bOpenFile logical bYN integer Lst(3,11) real TDMP(3) /3*0./ integer P integer C integer F ! Arguments to iHOSRead, iHOSWrite real L real Z(32) character cFlt2Str*14 character cInt2Str*14 integer Str2Str integer Str2StrSet integer kCC(3) /HOS__C_1,HOS__C_2,HOS__C_3/ integer kFF(5) /HOS__F_1,HOS__F_2,HOS__F_3,HOS__F_4,HOS__F_5/ !------- ! Initialization of index arrays is needed to make sure the buffers ! are filled up properly call ArrI4Index(NBUF,II(1,1)) call ArrI4Index(NBUF,II(1,2)) call ArrI4Index(NBUF,II(1,3)) ! Initialize buffer arrays !------- ! The file names and corresponding transfer time may be stored on ! a list file cFileL, or alternatively the input is given directly ! from the console. call Say(cSay,'I','List','Specify a list file with names of Helios files#'// & 'STOP will be followed by prompts for individual file names') iRL = 0 ! Open list with HERDA file names: cFileL if (bOpenFile(OPN__TEXT+OPN__READONLY,iUL,cFileL,iRL)) then !------- ! Process first two records from file cFileL: read optional record ! with time limits TBeg and TEnd and read the name of the first ! data file. read (iUL,*,iostat=I) TBeg,TEnd ! Read optional record if (I .ne. 0) then ! If optional record not present ... TBeg = 0. ! .. set very wide time limits, and ... TEnd = 999. rewind (iUL) ! .. backspace to beginning of file end if read (iUL,'(A)',iostat=I) cFileI! Read second record from cFileL if (I .ne. 0) call Say(cSay,'E','Empty','list file specified '//cFileL) backspace (iUL) ! Same record will be read later on cFileI(index(cFileI,' '):) = ' '! Get file name from cFileL iOpen = OPN__REOPEN else ! Input read from console !------- ! Give input for TBeg, TEnd and the first file name cFileI ! through console TBeg = 0. TEnd = 999. call Say(cSay,'I','Specify','limits for requested time span (default: no limits)') call AskR4('Start time',TBeg) call AskR4('End time' ,TEnd) call Say(cSay,'I','Specify','name of first data file') iOpen = 0 end if if (iHOSInfo(iOpen,cFileI,iLI,iSc,iYr,TMin,TMax,kPCF,Lst) .eq. 0) call Say(cSay,'E','Stop','Exit') nSI = iLI-4.5 ! # sectors on first file iNorm = iand(kPCF,HOS__NONORM) ! Normalization of first file (0=Normalized, HOS__NONORM=Unnormalized if (iOpen .eq. 0) iOpen = -1 ! Bypasses prompt for first data file !------- ! Select a single color and filter to be processed. Only data for ! this color/filter combination are extracted from the files. The ! normalization is set by the first file. The normalization determines ! the extension of the output file name (.ZLD for unnormalized, .DAT ! for normalized data). The selected color kC determines the fourth ! character (U,B or V) ! The spacecraft iSc and year iYr determine the first two characters. I = 0 do while (I .eq. 0) ! Set kC (color) and kF (filter) call AskWhat('Colors: UV, Blue, Visual$1$3',kC) call AskWhat('Filters: 1,2,3,Clr,pB$1$4',kF) I = Lst(kC,kF)+Lst(kC,5+kF) ! Photometer 1+2 if (kF .ge. 4) I = I+Lst(kC,11) ! Photometer 3 end do kPCFbase = HOS__P_ALL+kCC(kC)+kFF(kF) ! Photometer/color/filter selection !------- ! Open scratch files in $TUB (used to store the output data ! temporarily) I = iFilePath(cEnvi//'TUB',0,' ','connect.hos',cStr) do P=1,3 I = iUniqueName(cStr,cFileS) bYN = bOpenFile(OPN__HOS+OPN__REOPEN+OPN__SCRATCH+OPN__STOP,iUS(P),cFileS,iLS(P)) end do call ArrI4Zero(3,iRS) ! Initialize record counters to zero iLS(1) = iLI ! Set record length (determined by 1st input file) iLS(2) = iLI iLS(3) = 6 !----- ! Start reading data. Read filename cFileI and corresponding transfer ! time TNew from cFileL or console and open the file. TNew = 0. do while (TNew .lt. 999.) TOld = TNew ! Start time on next data file if (iOpen .gt. 0) then ! Input read from list file cFileL read (iUL,'(A)') cFileI ! Contains file name and transfer time I = index(cFileI,' ') ! Length of file name on cFileL read (cFileI(I+1:30),*,iostat=J) TNew! Transfer time for cFileI if (J .ne. 0) TNew = 999. ! Last file name on cFileL cFileI(I:) = ' ' bYN = bOpenFile(OPN__HOS+OPN__READONLY+OPN__STOP+iOpen,iUI,cFileI,iLI) else ! Input through console if (iOpen .eq. 0) bYN = bOpenFile(OPN__HOS+OPN__READONLY+OPN__STOP,iUI,cFileI,iLI) iOpen = 0 ! Activates prompt for input file on next pass TNew = 999. call AskR4('Transfer time (999 for last file)$0$999.1',TNew) end if !------- ! Read first record of file cFileI and determine whether the ! normalization is the same as for the first file. If not stop ! execution. kPCF = kPCFbase iRI = 0 if (iHOSRead(kPCF,iUI,iLI,iRI,T,P,C,F,R,L,nSI,Z) .eq. 0) then if (iand(kPCF,HOS__NONORM) .ne. iNorm) call Say(cSay,'E','Wrong','normalization '//cFileI) T1 = max(TOld,TBeg) T2 = min(TNew,TEnd) cStr = 'time span '//cFlt2Str(T1,2)//' through '//cFlt2Str(T2,2) I = iwhitespace(cStr) call Say(cSay,'I',cFileI,cStr) !------- ! Read and process next record from file cFileI. IBUF keeps ! track of the free buffer locations. The data read from cFileI ! are first read into a buffer. As long as the buffer is not ! full, it gets filled up from the bottom up. When the buffer ! is full (IBUF=0) the data for the smallest time in the buffer ! is written to one of scratch files. The next data read from ! cFileI are then stored in the free buffer location. The data ! on the scratch files are thus ordered in time. If the buffer ! array declaration NBUF is not big enough an error message is ! issued and the program stops. ! ! Note that the photometer, color and filter info does not ! need to be stored in the buffer arrays. The photometer is ! determined by which buffer is used (P=1,2,3); the selection ! process ensures that the color entry is always C=kC and the ! filter always F=kF at this point (unless filter 5 was ! requested and P=3: then kF=5 and F=4, but the filter value ! is not used for photometer 3). iRI = 0 ! Start at first record do while (iHOSRead(kPCF,iUI,iLI,iRI,T,P,C,F,R,L,nSI,Z) .eq. 0) ! Error presumably is EOF if (T1 .le. T .and. T .le. T2) then ! If inside time limits if (IBUF(P) .eq. 0) then ! Buffer full call IndexR4(1,NBUF,1,NBUF,TT(1,P),II(1,P))! Sort buffer I = II(1,P) ! Smallest time in buffer TDMP(P) = TT(I,P) ! Last time written to scratch file I = iHOSWrite(iNorm,iUS(P),iLS(P),iRS(P),TT(I,P),P,C,F,RR(I,P),LL(I,P),nSI,ZZ(1,I,P)) IBUF(P) = 1 ! Now there's one free buffer location end if if (T .lt. TDMP(P)) call Say(cSay,'E','Buffer','too small; increase NBUF') I = II(IBUF(P),P) ! Buffer location I is free TT(I,P) = T RR(I,P) = R ! Fill free buffer location LL(I,P) = L call ArrR4Copy(nSI,Z,ZZ(1,I,P)) IBUF(P) = IBUF(P)-1 ! One free buffer location less end if end do end if iUI = iFreeLun(iUI) ! Close data file end do if (iOpen .gt. 0) iUL = iFreeLun(iUL) ! All data are read. Close list file cFileL !------- ! When the last record is read from the files the data present in the ! buffer still have to be written to the scratch file. If the buffer ! is not full (IBUF(P)=0) then only the first NBUF-IBUF(P) locations ! of the buffer arrays are in use. do P=1,3 K = NBUF-IBUF(P) ! # buffer locations in use if (K .gt. 0) then ! Buffer not empty call IndexR4(1,K,1,NBUF,TT(1,P),II(1,P))! Sort used part of buffer do J=1,K ! Write buffer to scratch file I = II(J,P) I = iHOSWrite(iNorm,iUS(P),iLS(P),iRS(P),TT(I,P),P,kC,kF,RR(I,P),LL(I,P),nSI,ZZ(1,I,P)) end do end if end do !------- ! At this point only the scratch files are open, one for each ! photometer, each with iRS(P) records. First we copy the data for ! photometers 1 and 2 (if present) in chronological order to the ! final output file cFileO. if (iRS(1) .eq. 0) call Say(cSay,'I','16 deg','no data for filter '//cInt2Str(kF)) if (iRS(2) .eq. 0) call Say(cSay,'I','31 deg','no data for filter '//cInt2Str(kF)) !------- ! Check whether 90 deg data are present and, if yes, decide how to ! store them. bYN = .FALSE. if (iRS(3) .ne. 0) then call AskYN('Do you need the 90 deg data$yes',bYN) if (bYN) then call AskYN('Same output file as 16/31 deg data$yes',bYN) else iRS(3) = 0 end if end if kPCF = kPCFbase do P=1,3 if (iRS(P) .eq. 0) then iUS(P) = iFreeLun(iUS(P)) ! Empty scratch file TDMP(P) = 999. ! Set to big value else iRS(P) = 0 ! Get earliest time; also sets iRS(P) = 1 K = iHOSRead(kPCF,iUS(P),iLS(P),iRS(P),TDMP(P),P,C,F,R,L,nSI,Z) end if end do ! iRSP(P) is now 0 or 1. !------- ! kPCF now contains the data selection (kPCFbase), the proper ! normalization setting (iNorm), and the proper architecture setting. !------- ! bYN=.TRUE.: there are 90 deg data and they will be stored with the ! 16/31 deg data T = min(TDMP(1),TDMP(2)) ! Earliest time if (bYN) T = min(T,TDMP(3)) I = iGetFileSpec(0,FIL__DIRECTORY,cFileO) iStr = Str2StrSet(STR__ZERORIGHTADJUST) I = Str2Str(cSc(iSc) , cFileO(I+1:)) ! Spacecraft ID I = Int2Str(iYr-1900 , cFileO(I+1:)) ! Year ID I = Str2Str(cColor(kC) , cFileO(I+1:)) ! Color ID I = Int2Str(kF , cFileO(I+1:)) ! Filter ID I = Str2Str('_' , cFileO(I+1:)) ! Underscore I = Int2Str(nint(T) , cFileO(I+1:)) ! Day of year I = Str2Str(cNorm(min(1,iand(iNorm,HOS__NONORM))), cFileO(I+1:)) iStr = Str2StrSet(iStr) I = iSetFileSpec(cFileO) iUO = FIL__NOUNIT ! Just in case iRS(1)=iRS(2)=0 iRO = 0 ! Counts # records written to cFileO POld = 0 if (iRS(1)+iRS(2) .gt. 0) then ! If 15/30 deg data are present T1 = min(TDMP(1),TDMP(2)) ! Earliest time for combined 15/30 deg data iLO = iLI ! Output record length=input record length if (bOpenFile(OPN__HOS+OPN__REOPEN+OPN__NEW+OPN__STOP,iUO,cFileO,iLO)) then do while (iRS(1)+iRS(2) .gt. 0) ! Stop when units 1 and 2 are closed P = 1 ! Select scratch file from which ... if (TDMP(2) .lt. TDMP(1)) P = 2 ! .. the next record is to be read I = kPCF-kPCFbase ! Read record iRS(P) I = iHOSRead (I,iUS(P),iLS(P),iRS(P),T,P,C,F,R,L,nSI,Z) ! Write next record (iRO+1) I = iHOSWrite(kPCF,iUO ,iLO ,iRO ,T,P,C,F,R,L,nSI,Z) ! Read next record of buffer P if (iHOSRead (kPCF,iUS(P),iLS(P),iRS(P),T,P,C,F,R,L,nSI,Z) .eq. 0) then TDMP(P) = T ! New earliest time in buffer P else iUS(P) = iFreeLun(iUS(P))! Scratch file deleted TDMP(P) = 999. ! Set to big value iRS(P) = 0 end if end do cStr = 'data for time span '//cFlt2Str(T1,2)//'-'//cFlt2Str(T,2)//' written to '//cFileO I = iwhitespace(cStr) call Say(cSay,'I','16/31 deg',cStr) end if end if P = 3 if (iRS(P) .eq. 0) then iUO = iFreeLun(iUO) call Say(cSay,'I','90 deg','no data for this filter '//cInt2Str(kF)) end if !------- ! Write the 90 deg data to output file cFileO. If the data are to be ! stored on a separate file than a file with recl=6 is opened. If the ! data are to be appended to the 15/30 deg data file and N1=0 (no ! 15/30 deg data found previously; no output file opened yet) then ! a file with recl 37 is opened. if (.not. bYN) then ! Separate file for 90 deg data if (iUO .ne. FIL__NOUNIT) iUO = iFreeLun(iUO) ! Close 16/31 deg data file iStr = Str2StrSet(STR__ZERORIGHTADJUST) I = Str2Str(cSc(iSc) , cFileO(I+1:))! Spacecraft ID I = Int2Str(iYr-1900 , cFileO(I+1:))! Year ID I = Str2Str(cColor(kC), cFileO(I+1:))! Color ID I = Int2Str(9 , cFileO(I+1:))! Filter ID=9 I = Str2Str('_' , cFileO(I+1:))! Underscore I = Int2Str(nint(TDMP(P)), cFileO(I+1:))! Day of year iStr = Str2StrSet(iStr) I = iPutFileSpec(FIL__NAME,FIL__NAME,cFileO) I = iGetFileSpec(0,0,cFileO) iLO = 6 ! Sufficient for 90 deg data bYN = bOpenFile(OPN__HOS+OPN__REOPEN+OPN__NEW+OPN__STOP,iUO,cFileO,iLO) iRO = 0 ! Reset record counter end if iRS(P) = 0 do while (iHOSRead(kPCF,iUS(P),iLS(P),iRS(P),T,P,C,F,R,L,nSI,Z) .eq. 0) I = iHOSWrite(kPCF,iUO,iLO,iRO,T,P,C,F,R,L,nSI,Z) end do cStr = 'data for time span '//cFlt2Str(TDMP(P),2)//'-'//cFlt2Str(T,2)//' written to '//cFileO I = iwhitespace(cStr) call Say(cSay,'I','90 deg',cStr) call Say(cSay,'S','StopPlay','Normal exit') end