C+ C NAME: C HERDISK C PURPOSE: C Reads data from the HELIOS optical platter (5 or 12 inch) C (the CDs contain a Windows NT executable herdisk.exe to read C the raw data files. It writes 'packed' Helios data (see RESTRICTIONS). C CATEGORY: C I/O C CALLING SEQUENCE: program HERDISK C INPUTS: C To get info on command line arguments: C herdisk -? (Linux) C herdisk /? (Windows) C C Data read from 12 inch optical disk, 5 inch optical disks or CD. C All media have subdirectories AR,AZ,BZ and BR (A=Helios 1, B=Helios 2, C R=Reduced data, Z=Zodiacal light data). HERDISK needs the name of the C parent directory of these subdirectories to locate the data. C This Helios 'root directory' is determined using one of the following C steps in sequence: C C 1. Check the command line C To read from the 5 or 12 inch optical disks specify HER5 C or HER12, respectively. In this case the symbol LIB_OD_UNIT C should be set to the optical drive where the platter is mounted C 2. Check the symbol LIB__OD_UNIT C (On VMS this symbol is set automatically if LIBDEV is used to C mount the optical disk) C 3. Prompt the user for the root directory C OUTPUTS: C Disk file C CALLS: C BadR4, ForeignArg, Say, iGetSymbol, iGetLogical, iGetDefaultDir, AskChar C AskWhat, AskYN, AskI4, AskR4, iFilePath, iCheckDirectory, iSearch C iSetFileSpec, iPutFileSpec, iGetFileSpec, bOpenFile, iFreeLun C OGetRecord, OCv2Int, OCv2Flt, CvR4, DATE_DOY, Julian C Str2Str, Int2Str, ArrR4Copy, iArrR4ValuePresent C iHOSWrite, iHOSInfo C INCLUDE: include 'hos_e9.h' include 'filparts.h' include 'dirspec.h' include 'openfile.h' C COMMON BLOCKS: C common /OPEN_NEXT_FILE/ iYr,iMon,INDX,INDXTOT,ISP,IDT,cDir,cAim C RESTRICTIONS: C (the following is no longer true. Structures are no longer used, so C the alignment problem no longer arises). C C The Helios data are written to a binary disk file (i.e. open for C direct, unformatted access) using the structures defined in include C file E9_HOS.H. C C For photometers 1 and 2 (16 and 31 degrees) the structure is: C C structure /DATA_STRUCT/ C real*4 TIME !Day of year C integer*2 PHOTOM !16 or 31 degree photometer C integer*2 COLOR !+100 if not NODATted C integer*2 FILTER !Filter wheel setting C real*4 DISTANCE !Distance of spacecraft from Sun (AU) C real*4 POSITION !Position of spacecraft w.r.t Sun C real*4 INTENS(32) !Intensities in the 32 sectors C end structure C C For photometer 3 (90 degree) the structure is: C C structure /DEG90_STRUCT/ C real*4 TIME !Day of year C integer*2 PHOTOM !90 degree photometer C integer*2 COLOR !+100 if not NODATted C real*4 DISTANCE !Distance of spacecraft from Sun (AU) C real*4 POSITION !Position of spacecraft w.r.t Sun C real*4 INTENS !Intensity C real*4 POLARIZ !Polarization C end structure C C Note that the definition of the 16/32 photometer record is nonaligned C (three integer*2 variables in a row). Many Fortran compilers will by default C add 2 bytes after the color entry, extending the length of the structure C to 148 bytes, rather than 146. Usually the compiler will have a switch to C 'pack' the structure, i.e. force the compiler NOT to insert the 2 extra bytes. C Historically, Helios data at UCSD have been 'packed' (on older VMS computers C this was the default). To remain compatible, programs using E9_HOS.H should C be compiled with the 'pack' switch turned on: C For VAX Fortran this is the /NOALIGN switch, e.g. use C FORTRAN/NOALIGN/WARNING=NOALIGN C For Absoft Fortran for NT, this is the -N33 switch (available under C F77 Options/Miscellaneous/Pack structure elements) C EXAMPLES: C Linux: herdisk -ha -zld -ascii -silent C Windows: herdisk /ha /zld /ascii /silent C VMS: run HERDISK ! Runs 5 inch version C $ HERDISK HER5 ! Runs 5 inch version C $ HERDISK HER12 ! Runs 12 inch version C (The last two versions must be stored in a DCL symbol) C PROCEDURE: C 12 - inch platter: C The two sides of the optical disk are labeled HELIOS01 and HELIOS02. C HELIOS01 contains HELIOS A reduced data and HELIOSB zodiacal light data; C HELIOS02 contains HELIOS A zodiacal light data and HELIOSB reduced data. C 5 - inch platters: C There are three double-sided disks labeled HELIOS01 through HELIOS06 C HELIOS01 : Helios A reduced data C HELIOS02 : Helios A reduced data; Helios A zodiacal light data C HELIOS03 : Helios A zodiacal light data C HELIOS04 : Helios B reduced data C HELIOS05 : Helios B zodiacal light data C HELIOS06 : Helios B zodiacal light data C CD set: C There are three CDs with label HELIOS_AR, HELIOS_AZ and HELIOS_B C HELIOS_AR : Helios A reduced data C HELIOS_AZ : Helios A zodiacal light data C HELIOS_B : Helios B reduced and zodiacal light data C C Data selection is determined by choosing among the following options: C C (1) HELIOS A or HELIOS B C (2) Zodiacal light data or reduced data C (3) Color UV, Blue, Visual or all three C (4) Only the 90 deg. photometer or all three photometers C (5) If all three photometers [option 4]: one filter 1-5, filter 4 and C 5, or all 5 filters (4=Clear,5=Polarization brightness). C C For the 90 deg. photometer both clear and PB are read, unless the selected C filter is 1,2 or 3 (in which case the 90 deg photometer is omitted completely). C C To run on the VMS Vax: C $ $COM:LIBDEV ODMOUNT (to mount optical disk) C $ run $EXE:HERDISK C $ $COM:LIBDEV ODMOUNT (to dismount optical disk) C C HERDISK can be run most easily using the LIBPLAY procedure (type PLAY C HELIOS and use the options ODMOUNT and HER5 or HER12) C ???? HERDISK can also be submitted as a batchjob using option K of the C HELIOS command procedure. Make sure you have the optical disk mounted C before you submit the job (using LIBDEV ODMOUNT). You will also need C an input file containing the answers to all the questions HERDISK asks C in interactive mode: C C A or B (HELIOS A or B) C Z or R (Zodiacal light or reduced data) C Y or N (Only 90 deg data (1) or all photometers (0)) C A,U,B,V (Color; A = all colors) C A,1,2,3,4,5,C (Filter; A = all filters; C = Clear+pB) C year1 C doy1 (start date) C year2 C doy2 (end date) C filename (name for the outputfile) C C - Bad (negative) data are flagged as BadR4(). C - The color value is offset by 100 to indicate that the data have C not been normalized (run NODAT or THEFIT to normalize the data). C - The output file will always have the extension .HER C C The arrays IAZ,IBZ,IAR,IBR contain the number of measurement cycles in C each month (each non-zero entry in one of these arrays stands for one C magnetic tape of HELIOS data). C The array IDENT contains locations in the INTA and REALA arrays where C the values for various quantities are located. C C Zodiacal light data (see Description of the zodiacal-light-data-tape C of the HELIOS Zodiacal Light Experiment E9): C C INTA( IDENT(1,1) ) --> year C REALA( IDENT(2,1) ) --> distance Sun-spacecraft in AU C REALA( IDENT(2,1)+1 ) --> ecliptic longitude Sun (seen from spacecraft; C equinox 1975) C REALA( IDENT(3,1)+I ) (I=1,32) --> for photometers 1 and 2: clear C intensities for filters 1 through 4; for filter 5 (polarization C data) the intensities are stored after location 352 instead of C 608). C REALA( IDENT(4,1) ) --> clear brightness for photometer 3 C REALA( IDENT(5,1) ) --> polarization brightness for photometer 3 C C Reduceced data (Description of the reduced-data-tape of the HELIOS C Zodiacal Light Experiment E9): C C INTA( IDENT(1,2) ) --> year C REALA( IDENT(2,2) ) --> distance Sun-spacecraft in AU C REALA( IDENT(2,2)+1 ) --> ecliptic longitude Sun C REALA( IDENT(3,2)+I ) (I=1,32) --> for photometers 1 and 2: clear C intensities for filters 1 through 5 C REALA( IDENT(4,2)+COLOR ) --> clear brightness for photometer 3 C REALA( IDENT(5,2)+COLOR ) --> polarization brightness for photometer 3 C (COLOR = 1,2,3 for UV,Blue and Visual, respectively) C C ERRORS ON OPTICAL PLATTER: C AZ75JAN.128 read errors (empty file on CD?) C AZ75MAR.002 'Funny INTA(1) = 0'; seemingly no data C AZ76SEP.038 last 11 logical records contain nonsensical data C BZ76AUG.002 one bad logical record C BZ76AUG.032 no data C BZ76AUG.038 no data C BZ76NOV.114 (last 18 logical records) and ... C BZ76NOV.115 (first 8 records) give wrong year 1911 (error is corrected by C software). C BZ78DEC.### contain data for January 1979 C MODIFICATION HISTORY: C FEB-1992, Paul Hick (UCSD/CASS) C Modified for use on 5 inch optical disk on VMS C JUN-1998, Paul Hick (UCSD/CASS) C Modified to run from CD in Windows NT C NOV-2001, Paul Hick (UCSD/CASS; pphick@ucsd.edu) C Modified to run on from CD in Linux C Fixes needed to compile under g77: C - main program: introduced IREAL array equivalenced to REALA C for use in call to OCv2Flt. C - href=OGetRecord=: now uses bOpenFile to open the raw Helios files C On VMS the files are opened as sequential, unformatted files; C on NT and Linux they are opened as direct acess, unformatted files C with the proper record length in bytes. C On NT the files must be opened readonly to access the CD. C - href=OCv2Int=: integer*2 argument to MVBITS replaced by integer*4 C - href=OCv2Flt=: removed calls to intrinsic IIOR C Also added command line argument /silent (On NT the program C sometimes crashes when lines are written to the screen too fast; C setting /silent circumvents this problem). C OCT-2002, Paul Hick (UCSD/CASS; pphick@ucsd.edu) C Minor revision of help display when specifying /? or -? switch. C Also added ascii command line argument to produce ascii output files C- character*1 cInfo(3530) ! Input record as character string integer*2 iInfo(1765) ! Input record as int*2 array equivalence (iInfo,cInfo) integer INTA(706) ! Input converted to int*4 integer IREAL(706) real REALA(706) ! Input converted to floating point equivalence (REALA, IREAL) integer LININ(2) /3530,1430/ ! Length logical records integer LORIN(2) /640,138/ ! Do loop delimiter used in OCv2Flt integer IDENT(5,2) /13, 25,608,60 ,61, ! Zodiacal light INTA array & 17,135,84 ,128,125/! Reduced data INTA array logical bOnly90 /.FALSE./ logical bOpenFile logical bSay logical bAscii character cUBV(3)*6 /'UV ','Blue ','Visual'/ character cSP(2)*2 /'ha','hb'/ character cDT(2)*3 /'zld','red'/ character cAR*2 character cAZ*2 character cBR*2 character cBZ*2 character cMonths(12)*3 /'jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'/ character cInch*5 /' '/ character cSay*7 /'herdisk'/ character cRootDir*40 character cFileOut*80 character cTypeOut*10 character cStr*80 character cMon*3 character cArg*20 integer Str2Str integer iRec /0/ integer iDayOld /0/ integer Lst(3,11) real ZZ(32) real LL real*8 LAUNCH(2) /2442391.84097d0,2442792.73194d0/ !Launch in Julian days real*8 DEATH(2) /2446131.98958d0,2444307.23958d0/ !Death in Julian days real*8 JD real*8 JDS real*8 JDE real*8 JEpoch integer INDXTOT(12,74:85,2,2) !Month,year,spacecraft,data type character cDir*40 character cAim*11 common /OPEN_NEXT_FILE/ iYr,iMon,INDX,INDXTOT,ISP,IDT,cDir,cAim ! HELIOS A; Zodiacal light data (side 2; label HELIOS02; 6658 files) integer IAZ(12,12) & / 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, ! 74 & 143, 127, 142, 85, 11, 65, 109, 101, 113, 107, 103, 0, ! 75 & 71, 91, 123, 123, 115, 70, 18, 55, 54, 127, 138, 136, ! 76 & 120, 114, 139, 124, 139, 136, 53, 94, 119, 113, 154, 136, ! 77 & 0, 42, 126, 126, 132, 130, 0, 0, 0, 63, 94, 138, ! 78 & 39, 0, 0, 92, 133, 120, 29, 0, 0, 53, 101, 120, ! 79 & 69, 0, 0, 0, 130, 135, 52, 0, 0, 0, 77, 75, ! 80 & 73, 0, 0, 0, 44, 135, 88, 0, 0, 0, 0, 104, ! 81 & 71, 0, 0, 0, 0, 109, 73, 0, 0, 0, 0, 0, ! 82 & 0, 0, 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, ! 83 & 0, 18, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, ! 84 & 14, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 / ! 85 ! HELIOS B; Zodiacal light data (side 1; label HELIOS01; 3723 files) integer IBZ(12,12) & / 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 74 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 75 & 75, 139, 146, 144, 66, 34, 23, 47, 29, 95, 133, 106, ! 76 & 119, 130, 142, 130, 91, 0, 50, 70, 83, 93, 135, 139, ! 77 & 138, 0, 136, 132, 144, 45, 0, 0, 0, 38, 105, 159, ! 78 & 0, 0, 0, 95, 128, 98, 0, 0, 0, 76, 119, 91, ! 79 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 80 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 81 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 82 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 83 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 84 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 / ! 85 ! HELIOS A; Reduced data (side 1; label HELIOS01; 6712 files) integer IAR(12,12) & / 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, ! 74 & 142, 126, 140, 84, 10, 64, 108, 100, 112, 102, 102, 102, ! 75 & 70, 90, 122, 122, 114, 69, 17, 54, 53, 126, 137, 135, ! 76 & 119, 113, 138, 123, 138, 135, 52, 93, 118, 140, 153, 134, ! 77 & 0, 41, 125, 125, 131, 129, 0, 0, 0, 62, 93, 137, ! 78 & 38, 0, 0, 91, 132, 119, 28, 0, 0, 52, 100, 119, ! 79 & 68, 0, 0, 0, 129, 134, 51, 0, 0, 0, 76, 74, ! 80 & 72, 0, 0, 0, 43, 134, 87, 0, 0, 0, 0, 103, ! 81 & 70, 0, 0, 0, 0, 108, 72, 0, 0, 0, 0, 0, ! 82 & 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, ! 83 & 0, 17, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, ! 84 & 14, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 / ! 85 ! HELIOS B; Reduced data (side 2; label HELIOS02; 3619 files) integer IBR(12,12) & / 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 74 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 75 & 71, 135, 173, 140, 62, 30, 19, 43, 25, 92, 129, 102, ! 76 & 115, 135, 138, 126, 87, 0, 46, 66, 79, 89, 131, 135, ! 77 & 134, 0, 133, 128, 140, 41, 0, 0, 0, 34, 101, 155, ! 78 & 0, 0, 0, 91, 124, 94, 0, 0, 0, 72, 117, 87, ! 79 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 80 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 81 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 82 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 83 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 84 & 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 / ! 85 equivalence (INDXTOT(1,74,1,1),IAZ(1,1)) equivalence (INDXTOT(1,74,2,1),IBZ(1,1)) equivalence (INDXTOT(1,74,1,2),IAR(1,1)) equivalence (INDXTOT(1,74,2,2),IBR(1,1)) Bad = BadR4() I = 1 call ForeignArg(',',I,cRootDir,cArg) call lowercase(cArg) if (index(cArg,cSwitch//'?') .ne. 0 .or. index(cArg,cSwitch//'help') .ne. 0) then write (*,*) ' Usage: herdisk root' write (*,*) ' root fully qualified directory name' write (*,*) ' ' write (*,*) ' Linux : the CDROM device will be e.g. /mnt/cdrom' write (*,*) ' Windows: the CDROM device will be e.g. D:' write (*,*) ' VMS : if root=HER5 or root=HER12 then the VMS' write (*,*) ' symbol LIB__OD_UNIT is read to set the root directory' write (*,*) ' ' write (*,*) ' Switches:' write (*,*) ' '//cSwitch//cSP(1)//', '//cSwitch//cSP(2)//' selects Helios A or Helios B' write (*,*) ' '//cSwitch//cDT(1)//', '//cSwitch//cDT(2)//' selects zodiacal light, or reduced data' write (*,*) ' ' //cSwitch//cUBV(1)(:itrim(cUBV(1)))//', '// & cSwitch//cUBV(2)(:itrim(cUBV(2)))//', '// & cSwitch//cUBV(3)(:itrim(cUBV(3)))//' selects single color filter' write (*,*) ' '//cSwitch//'only90 selects only data for 90 deg photometer' write (*,*) ' '//cSwitch//'ascii produces ascii instead of binary files' write (*,*) ' '//cSwitch//'silent suppresses informational messages' write (*,*) ' ' write (*,*) ' Omitted switches will result in a prompt for the required info' write (*,*) ' Additial prompts are for pB filter selection and time limits' call Say(cSay,'I','Stop','Exit') end if bSay = index(cArg,cSwitch//'silent') .eq. 0 if (.not. bSay) call Say(cSay,'I','Silent','....... silent running') bAscii = index(cArg,cSwitch//'ascii') .ne. 0 if (bAscii) call Say(cSay,'I','Ascii','output') if (cRootDir .eq. 'HER5' .or. cRootDir .eq. 'HER12' .or. cRootDir .eq. ' ') then cInch = cRootDir if (iGetSymbol('LIB__OD_UNIT',cRootDir) .eq. 0) call Say(cSay,'W','Symbol', & 'LIB__OD_UNIT does not exist.#Optical disk not mounted?') end if if (cRootDir .eq. ' ') then I = iGetDefaultDir(cRootDir) call AskChar('Helios root directory$dir',cRootDir) end if ISP = 0 if (index(cArg,cSwitch//cSP(1)) .ne. 0) ISP = 1 if (index(cArg,cSwitch//cSP(2)) .ne. 0) ISP = 2 if (ISP .eq. 0) call AskWhat('Helios: ' //cSP(1)//','//cSP(2),ISP) IDT = 0 if (index(cArg,cSwitch//cDT(1)) .ne. 0) IDT = 1 if (index(cArg,cSwitch//cDT(2)) .ne. 0) IDT = 2 if (IDT .eq. 0) call AskWhat('Data type: '//cDT(1)//','//cDT(2),IDT) cAim(:2) = cSP(ISP)(2:2)//cDT(IDT)(1:1) ! AZ, AR, BZ or BR cAZ = cSP(1)(2:2)//cDT(1)(1:1) cAR = cSP(1)(2:2)//cDT(2)(1:1) cBZ = cSP(2)(2:2)//cDT(1)(1:1) cBR = cSP(2)(2:2)//cDT(2)(1:1) !------- ! There is only one 12-inch platter, so we can check here whether the ! correct side is mounted. Side 1 contains Helios A, reduced data, and ! Helios B, zodiacal light data, i.e. data with ISP .ne. IDT. Side 2 ! contains Helios B, reduced data, and Helios A, zodiacal light data, ! i.e. data with ISP .eq. IDT if (cInch .eq. 'HER12') then I = iFilePath(cRootDir,1,'HELIOS',' ',cDir) ! Fully qualified directory name I = Str2Str(cDir,cStr) if (ISP .eq. IDT) I = Str2Str(cAZ//'74'//cMonths(12)//'.001',cStr(I+1:)) ! 'AZ74DEC.001' if (ISP .ne. IDT) I = Str2Str(cAR//'74'//cMonths(12)//'.001',cStr(I+1:)) ! 'AR74DEC.001' ! Test for correct side of optical platter if (iSearch(1,cStr,cStr) .ne. 1) call Say(cSay,'E','Data','are on other side of disk') else I = iFilePath(cRootDir,1,cAim(:2),' ',cDir) ! Fully qualified directory name if (iCheckDirectory(cDir) .eq. 0) call Say(cSay,'E','NoDir','directory not found: '//cDir) end if if (ISP .ne. 1 .or. IDT .ne. 1) then ! No 90 deg zodiacal light data for Helios A bOnly90 = index(cArg,cSwitch//'only90') .ne. 0 if (.not. bOnly90) call AskYN('Only 90 deg photometer',bOnly90) end if iColAsk = 0 ! Select color if (index(cArg,cSwitch//cUBV(1)) .ne. 0) iColAsk = 1 if (index(cArg,cSwitch//cUBV(2)) .ne. 0) iColAsk = 2 if (index(cArg,cSwitch//cUBV(3)) .ne. 0) iColAsk = 3 if (iColAsk .eq. 0) call AskWhat('Color: All,UV,Blue,Visual$0',iColAsk) iFiltAsk = 6 ! Select filter if (.not. bOnly90) call AskWhat('Filter: All,1,2,3,Clr,pB,Clr+pB$0',iFiltAsk) call Julian(1,ISYR,SDOY,LAUNCH(ISP),JEpoch) ! Start of mission call Julian(1,IEYR,EDOY,DEATH (ISP),JEpoch) ! End of mission write (cStr,'(2(A,I4))') 'Start year$',ISYR,'$',IEYR iYr = ISYR call AskI4(cStr,iYr) ! Select start year if (iYr .ne. ISYR) then ISYR = iYr SDOY = 1. end if cMon = cMonths(12) call DATE_DOY(0,ISYR,cMon,iMon,31,iDoy) write (cStr,'(A,F6.2,A,I3)') 'Start doy$',SDOY,'$',iDoy+1 call AskR4(cStr,SDOY) ! Select start day write (cStr,'(2(A,I4))') 'End year$',ISYR,'$',IEYR IEYR = ISYR call AskI4(cStr,IEYR) ! Select end year EDOY = 1. if (IEYR .eq. ISYR) EDOY = SDOY cMon = cMonths(12) call DATE_DOY(0,IEYR,cMon,iMon,31,iDoy) write (cStr,'(A,F6.2,A,I3)') 'End doy$',EDOY,'$',iDoy+1 call AskR4(cStr,EDOY) ! Select end day call Julian(0,ISYR,SDOY,JDS,JEpoch) ! Start Julian date call Julian(0,IEYR,EDOY,JDE,JEpoch) ! End Julian date call DATE_DOY(1,ISYR,cMon,iMon,I,int(SDOY)) ! Get month iMon (=1,12) iYr = ISYR-1900 if (JDS-I-SDOY+J+1 .gt. LAUNCH(ISP)) then ! Julian day at beginning of month iMon = 11+mod(iMon-sign(1,iMon-2)*12,12) ! Go back one month to ... if (iMon .eq. 12) iYr = iYr-1 ! .. make sure you don't miss any data end if if (cInch .ne. 'HER12') then ! Test for correct optical platter I = 0 I = I+Str2Str(cDir ,cStr(I+1:)) I = I+Str2Str(cAim(:2) ,cStr(I+1:)) ! cAim(1:2) = 'AR' I = I+Int2Str(ISYR-1900 ,cStr(I+1:)) ! Add year: '79' I = I+Str2Str(cSingle//cSingle//cSingle//'.001',cStr(I+1:)) ! Add '???.001' if (iSearch(1,cStr,cStr) .ne. 1) call Say(cSay,'E',' ',' ') end if if (bAscii) then iRecl = 0 cTypeOut = '.txt' else iRecl = 37 ! Record length in 4-byte words if (bOnly90) iRecl = 6 cTypeOut = '.her' end if if (iGetLogical(cTemp,cFileOut) .ne. 0) then ! Put output in cTemp (if defined) I = iFilePath(cTemp,0,' ',cSay//cTypeOut,cFileOut) else if (cOpSys .eq. OS__DOS) then ! DOS: assume HERDISK is run from CD I = iFilePath('C' ,0,' ',cSay//cTypeOut,cFileOut)! .. don't write to CD else ! Try to write to current directory cFileOut = cSay//cTypeOut end if call AskChar('Output file$parse',cFileOut) I = iSetFileSpec(cFileOut) I = iPutFileSpec(FIL__TYPE,FIL__TYPE,cTypeOut) ! Always use default extension I = iGetFileSpec(0,FIL__TYPE,cFileOut) iAct = OPN__NEW+OPN__TRYINPUT+OPN__STOP if (bAscii) then iAct = iAct+OPN__TEXT else iAct = iAct+OPN__HOS end if if (bOpenFile(iAct,iUOut,cFileOut,iRecl)) continue kPCF = HOS__NONORM+HOS__PCF_ALL ! Write unnormalized data to disk file call Say(cSay,'I','Files',' Input: '//cDir//'#Output: '//cFileOut// & '#Begin reading from Helios raw data files') ! Reading form the optical disk is done in OGetRecord. The next record ! will be read from the optical disk file located IHOP files ahead of ! cAim (IHOP=0 means that the same file is used as for the previous ! record). INDX = 0 !1 IHOP = 1 20 continue call OGetRecord(bSay,LININ(IDT),cInfo,IHOP,cAR,cMonths) ! Read the next logical record call OCv2Int(LININ(IDT),cInfo,INTA) ! Convert logical rec to integers if ( (IDT .eq. 1 .and. & INTA(1) .ne. 1 .and. & INTA(1) .ne. 2 .and. & INTA(1) .ne. 11 .and. & INTA(1) .ne. 13 .and. & INTA(1) .ne. 15) .or. & (IDT .eq. 2 .and. & INTA(1) .ne. 1 .and. & INTA(1) .ne. 2 .and. & INTA(1) .ne. 11 .and. & INTA(1) .ne. 10 .and. & INTA(1) .ne. 20) ) then if (cAim .ne. cAZ//'75'//cMonths(3)//'.002' .and. ! 'AZ75MAR.002' & cAim .ne. cAZ//'76'//cMonths(9)//'.038' .and. ! 'AZ76SEP.038' & cAim .ne. cBZ//'76'//cMonths(8)//'.002') then ! 'BZ76AUG.002' write (*,'(1X,3A,I10)') 'WARNING - ',cAim,' : Funny INTA(1) = ',INTA(1) end if end if ! Check to make sure logical record contains the specified data if (INTA(1) .ne. 11 .and. (IDT .eq. 2 .or. INTA(1) .ne. 13) ) go to 20 ! 11 is science block; 13 is polarization block I = INTA(IDENT(1,IDT)) ! Year if (cAim(:7) .eq. cBZ//'76'//cMonths(11) .and. INTA(9) .eq. 332 .and. I .eq. 1911) I = 1976 ! 'BZ76NOV' if (I .ne. 1900+iYr) then if (cAim(:7) .ne. cBZ//'78'//cMonths(12) .or. I .ne. 1979) ! 'BZ78DEC' & write (*,'(/,1X,3A,I8)') 'WARNING - ',cAim,' : Funny year = ',I end if Time = INTA(9)+(INTA(10)+INTA(11)/60.)/24. call Julian(0,I,Time,JD,JEpoch) Time = SDOY+(JD-JDS) ! Time>365 if time range spans two years iDay = Time if (iRec .eq. 0 .and. iDay .ne. iDayOld) then if (bSay) write (*,'(A,I3)') ' READING DAY ',iDay iDayOld = iDay end if if (IDT .eq. 1) then ! If zodiacal light data iPhot = INTA(4) iCol = INTA(5) if (iPhot .eq. 3) then if (iColAsk .ne. 0 .and. iCol .ne. iColAsk) then !Wrong color IHOP = 1 ! Go to next file go to 20 end if if (JD .gt. JDE) then if (iColAsk .ne. 0 .or. INDX .eq. INDXTOT(iMon,iYr,ISP,IDT)-1) go to 30 IHOP = 1 go to 20 end if if (iFiltAsk .ne. 0 .and. iFiltAsk .lt. 4) go to 20 else ! 16/31 deg photometer if (JD .gt. JDE .or. bOnly90) then if (cAim(:2) .eq. cAZ) go to 30 ! No 90 deg photometer data IHOP = max(1,INDXTOT(iMon,iYr,ISP,IDT)-3-INDX) go to 20 ! Go to 90 deg data end if RDUM = JDS-JD ! Skip whole files if far enough before start time if (RDUM .gt. 1.) then ! Skip only if more than one day ahead IHOP = 1 ! Take next file if (RDUM .gt. 5.) IHOP = min(5.1,RDUM) !Skip RDUM/2 days if (INDX+IHOP .ge. INDXTOT(iMon,iYr,ISP,IDT)-3) IHOP = IHOP+3 go to 20 end if if (iColAsk .ne. 0 .and. iCol .ne. iColAsk) go to 20 iFilt = 5 ! PB is treated as imaginary filter 5 if (INTA(1) .eq. 11) iFilt = INTA(14) ! Filter 1 through 4 if (iFiltAsk .ne. 0 .and. iFiltAsk .ne. iFilt .and. & (iFiltAsk .ne. 6 .or. iFilt .lt. 4) ) go to 20 end if if (JD .lt. JDS) go to 20 else ! If reduced data RDUM = JDS-JD ! Skip whole files if far enough before start time if (RDUM .gt. 1.) then ! Skip only if more than one day ahead IHOP = 1 ! Take next file if (RDUM .gt. 5.) IHOP = min(5.1,RDUM) ! Skip ca. RDUM/2 day go to 20 end if if (JD .lt. JDS) go to 20 if (JD .gt. JDE) go to 30 if (INTA(20) .eq. 0 .and. INTA(21) .eq. 1) then if (INTA(22) .lt. 4 .or. INTA(22) .gt. 15) go to 20 iPhot = 1 iFilt = 1+mod(INTA(22),4) iCol = INTA(22)/4 else if (INTA(20) .eq. 1 .and. INTA(21) .eq. 0) then if (INTA(22) .lt. 7 .or. INTA(22) .gt. 13) go to 20 iPhot = 2 iFilt = 4 iCol = INTA(22)-6 if (INTA(22) .ge. 10) then iFilt = max(1,INTA(22)-10) iCol = (INTA(22)+1)/4 end if else if (INTA(20) .eq. 0 .and. INTA(21) .eq. 0) then if (INTA(22) .lt. 29) go to 20 iPhot = 3 iCol = iColAsk iFilt = max(4,iFiltAsk) end if ! Wrong color if (iColAsk .ne. 0 .and. iCol .ne. iColAsk) go to 20 if (bOnly90 .and. iPhot .ne. 3) go to 20 ! Wrong photometer if (iFiltAsk .ne. 0 .and. iFiltAsk .ne. iFilt .and. & (iFiltAsk .ne. 6 .or. iFilt .lt. 4) ) go to 20 end if ! Write data to disk file if (iRec .eq. 0 .or. iDay .ne. iDayOld) then if (bSay) write (*,'(A,I4,A,I2)') ' WRITING DAY',iDay,', PHOTOMETER',iPhot iDayOld = iDay end if call OCv2Flt(iInfo,LORIN(IDT),IREAL) ! Convert logical record to floating point if (cOpSys .ne. OS__VMS) call CvR4(OS__VMS,LORIN(IDT),REALA) if (iPhot .ne. 3) then ! 15/31 deg photometer IPOINT = IDENT(3,IDT) if (INTA(1) .eq. 13) IPOINT = 352 ! Zodiacal light polarization data do I=IPOINT+1,IPOINT+32 if (REALA(I) .le. 0.) REALA(I) = Bad end do call ArrR4Copy(32,REALA(IPOINT+1),ZZ) I = iArrR4ValuePresent(32,ZZ,Bad) if (bSay .and. I .ne. 0) write (*,'(1X,I2,A,I1,A,I1,A,F9.4)') & I,' BAD VALUE(S) IN FILTER ',iFilt,', PHOTOMETER ',iPhot,' AT =',Time if (I .ne. 32) then ! Skip totally bad data RR = REALA(IDENT(2,IDT)) LL = REALA(IDENT(2,IDT)+1) if (bAscii) then iRec = iRec+1 if (iRec .eq. 1) write (iUOut,'(A,32I13)') '; Time P C F R L',(J,J=1,32) write (iUOut,'(F8.3,3I4,2F10.5,32E13.5)') Time,iPhot,100+iCol,iFilt,RR,LL,(ZZ(J),J=1,32) else I = iHOSWrite(kPCF,iUOut,iRecl,iRec,Time,iPhot,iCol,iFilt,RR,LL,32,ZZ) end if end if else ! 90 deg photometer IC1 = iCol IC2 = iCol if (IDT .eq. 2 .and. iColAsk .eq. 0) then IC1 = 1 IC2 = 3 end if call ArrR4Bad(32,ZZ) do IC=IC1,IC2 I = (IDT-1)*IC J = IDENT(4,IDT)+I if (REALA(J) .le. 0.) REALA(J) = Bad ZZ(1) = REALA(J) J = IDENT(5,IDT)+I if (REALA(J) .le. 0.) REALA(J) = Bad ZZ(2) = REALA(J) if (ZZ(1) .eq. Bad .and. ZZ(2) .eq. 0) then if (bSay) write (*,'(A,F9.4)') ' BAD INTENSITY AND pB IN 90 DEG PHOTOM AT T =',Time else if (ZZ(1) .eq. Bad) then if (bSay) write (*,'(A,F9.4)') ' BAD INTENSITY IN 90 DEG PHOTOM AT T =',Time else if (ZZ(2) .eq. Bad) then if (bSay) write (*,'(A,F9.4)') ' BAD pB IN 90 DEG PHOTOM AT T =',Time else RR = REALA(IDENT(2,IDT)) LL = REALA(IDENT(2,IDT)+1) if (bAscii) then iRec = iRec+1 if (iRec .eq. 1) write (iUOut,'(A,32I13)') '; Time P C F R L',(J,J=1,32) write (iUOut,'(F8.3,3I4,2F10.5,32E13.5)') Time,iPhot,100+IC,4,RR,LL,(ZZ(J),J=1,32) else I = iHOSWrite(kPCF,iUOut,iRecl,iRec,Time,iPhot,IC,4,RR,LL,32,ZZ) end if end if end do end if goto 20 30 continue iUOut = iFreeLun(iUOut) call Say(cSay,'I','Files',' Input: '//cDir//'#Output: '//cFileOut) if (IDT .eq. 1) then write (*,'(6X,A)') 'HELIOS '//cAim(:1)//' zodiacal light data' else write (*,'(6X,A)') 'HELIOS '//cAim(:1)//' reduced data' end if if (bOnly90) then write (*,'(6X,A)') 'Only 90 degree photometer' else write (*,'(6X,A)') 'All three photometers' end if if (iColAsk .eq. 0) then write (*,'(6X,A)') 'All three colors' else write (*,'(6X,A)') 'Only color '//cUBV(iColAsk) end if if (.not. bOnly90) then if (iFiltAsk .eq. 0) then write (*,'(6X,A)') 'All five filters' else if (iFiltAsk .eq. 6) then write (*,'(6X,A)') 'Only clear and polarization brightness' else write (*,'(6X,A,I1)') 'Only filter ',iFiltAsk end if end if write (*,'(6X,A,I4,A,F6.2)') 'Start date : ',ISYR,' DOY ',SDOY write (*,'(6X,A,I4,A,F6.2)') ' End date : ',IEYR,' DOY ',EDOY if (.not. bAscii) I = iHOSInfo(OPN__REOPEN,cFileOut,iRecl,iSc,iYr,TMin,TMax,iD,Lst) call Say(cSay,'I','Stop','Done') end C+ C NAME: C OGetRecord C CALLING SEQUENCE: subroutine OGetRecord(bSay, LIN,cData,IHOP,cAR,cMonths) C INCLUDE: include 'filparts.h' include 'dirspec.h' include 'openfile.h' C CALLS: C bOpenFile, iFreeLun, Say, iFilePath, cInt2Str C PROCEDURE: C Read physical records until whole logical record is read. C Save leftover from last-read physical record for next logical record. C Usually there is an extra 5-byte word at the beginning of each physical C record (LPHYS=5) and two 5-byte words at the end of each logical record. C However, when the second extra 5-byte word for the logical record is the C first word of a physical record, there is no other extra 5-byte word at C the beginning of that physical record (LPHYS=0). The same happens in the C HELIOS A reduced data for 1983, 1984 and 1985, when the first extra 5-byte C word for the logical record is the first word of a physical record. C C The value of IHOP determines from which file the next record is read C (IHOP=0: same file; IHOP>0: move IHOP files ahead on optical disk) C C The original files on the HELIOS optical disks are variable length files. C The physical records are 640 bytes long, separated by a 2-byte EOR marker. C The files are opened as unformatted, sequential access files. C On VMS the records are read by a LVMS=640 element character array. C On NT the records are read by a LDOS=641 element character array. C- logical bSay integer LIN character cData(LIN) integer IHOP character cAR*2 character cMonths(12)*3 logical bOpenFile parameter (LVMS=640) ! Originally set up for VMS character cInput(LVMS) character cSave (LVMS) parameter (LDOS=LVMS+1) ! Need one extra byte in DOS and LINUX?? character cInputDOS(LDOS) equivalence (cInput,cInputDOS) byte bInput(LVMS) equivalence (cInput,bInput) character cFile*80 character cInt2Str*14 character cSay*9 /'OGetReord'/ integer INDXTOT(12,74:85,2,2) ! Month,year,spacecraft,data type character cDir*40 character cAim*11 common /OPEN_NEXT_FILE/ iYr,iMon,INDX,INDXTOT,ISP,IDT,cDir,cAim integer iUIn /FIL__NOUNIT/ save cSave,NSAVE,iUIn, iR 30 if (IHOP .gt. 0) then ! Move IHOP files ahead if (iUIn .ne. FIL__NOUNIT) then iUIn = iFreeLun(iUIn) iR = 0 end if ! Close the current optical disk file ! Skip IHOP files ahead on the optical platter and open a new data file. do while (IHOP .ne. 0) ! The while loop intercepts INDXTOT()=0 (or 1 if IDT=1). ! This needs to be done at the first pass when no files have yet ! been opened (INDX=0,IHOP=1), and every time the program jumps ! to a new month (INDEX=0,IHOP>0; see below where INDX is set to ! 0). If at this point INDX .ne. 0 then this refers to an ! existing file in the current month, i.e. ! INDXTOT(iMon,iYr,ISP,IDT) .ne. 0 do while (INDXTOT(iMon,iYr,ISP,IDT) .le. 2-IDT) iMon = 1+mod(iMon,12) if (iMon .eq. 1) iYr = iYr+1 if (iYr .gt. 85) call Say(cSay,'E','NoData','moved past last data file') end do INDX0 = INDX ! Skip last file if IDT=1 INDX = min(INDX0+IHOP,INDXTOT(iMon,iYr,ISP,IDT)-2+IDT) IHOP = INDX0+IHOP-INDX ! # remaining files to be skipped C if (INDX .le. 0) IHOP = 1 ! Needed for opening of very first file ... ! .. in case INDXTOT() = 0 if (IHOP .ne. 0) then ! If not yet sufficient files skipped ... iMon = 1+mod(iMon,12) ! .. go to files for next month if (iMon .eq. 1) iYr = iYr+1 INDX = 0 ! 1 ! Reset file index end if end do write (cAim(3:),'(I2.2,A,A,I3.3)') iYr,cMonths(iMon),'.',INDX I = iFilePath(cDir,0,' ',cAim,cFile) !----- ! The original open statement on VMS (also works in Absoft Fortran, ! but not in g77) C iUIn = iGetLun(cFile) C open (iUIn,readonly,status='OLD',file=cFile,form='UNFORMATTED',access='SEQUENTIAL') iAct = OPN__READONLY+OPN__REOPEN+OPN__STOP+OPN__NOMESSAGE if (cOpSys .eq. OS__VMS) then ! Sequential, unformatted access iRecl = LVMS/4 iAct = iAct+OPN__SEQUENTIAL ! NOT TESTED YET else ! Direct, unformatted access iRecl = LDOS iAct = iAct+OPN__RECLBYTE end if if (bOpenFile(iAct,iUIn,cFile,iRecl)) then if (bSay) write (*,'(66X,A)') cAim end if if (iR .ne. 0) stop 'oops iR' ISPEC = 0 if (cAim(:4) .eq. cAR//'83' .or. cAim(:4) .eq. cAR//'84' .or. cAim(:4) .eq. cAR//'85') ISPEC = 1 NDATA = 0 ! Start new logical record else do I=1,NSAVE ! Begin new logical record with data ... cData(I) = cSave(I) ! .. saved from last physical record read end do NDATA = NSAVE end if NSAVE = 0 IERR = 0 ! Counter for read errors LPHYS = 5 ! Extra 5 bytes at beginning of physical record do while (NDATA .lt. LIN+10) ! As long as logical record not complete if (cOpSys .eq. OS__VMS) then read (iUIn,iostat=I) cInput ! Read physical record else iR = iR+1 read (iUIn,rec=iR,iostat=I) cInputDOS ! Read physical record !read (iUIn,iostat=I) cInputDOS ! Read physical record !print *, bInput(1), bInput(2), bInput(3), bInput(4), bInput(5), bInput(6), bInput(7) end if if (I .eq. 0) then ! Physical record succesfully read if (NDATA .eq. LIN+5) LPHYS = 0 if (ISPEC .eq. 1 .and. NDATA .eq. LIN) LPHYS = 0 do I=LPHYS+1,LVMS if (NDATA .lt. LIN) then ! Logical record not complete NDATA = NDATA+1 cData(NDATA) = cInput(I)! Add physical rec to log rec else if (NDATA .lt. LIN+10) then NDATA = NDATA+1 ! Skip 10 bytes at end log rec else ! Logical rec complete NSAVE = NSAVE+1 ! Save remaining part of phys rec cSave(NSAVE) = cInput(I) end if end do else if (I .lt. 0) then ! End of file, but no read error IHOP = 1 ! Move one file ahead go to 30 else ! Genuine read error IERR = IERR+1 if (IERR .ge. 100) then call Say(cSay,'W','BadFil','Bad data file '//cAim//'. Error code = '//cInt2Str(I)) IHOP = 1 go to 30 end if NDATA = 0 NSAVE = 0 end if end do return end C+ C NAME: C OCv2Flt C PURPOSE: C Translates data in array INP from 40-bit floating point format to a C two 32-bit word format returned in IREAL. C Called by HERDISK.FOR, HERDA.FOR and HERDRED.FOR C CALLING SEQUENCE: subroutine OCv2Flt(INP,LOR,IREAL) C INPUTS: C INP(*) integer*2 input array in 40-bit format C LOR integer # 5 byte words in INP to be processed ?? C OUTPUTS: C IREAL(*) integer output array in 32-bit format C CALLS: C CvSwap C MODIFICATION HISTORY: C MAY-2000, Paul Hick (UCSD/CASS) C NOV-2001, Paul Hick (UCSD/CASS; pphick@ucsd.edu) C Originally bytes were moved by using a bitwise SHIFT over C 8 bits combined with a bitwise OR, e.g. IWA and IWB C were calculated by C IWA = IIOR(IISHFT(IW3,I8),IISHFT(IW4,-I8)) C IWB = IIOR(IISHFT(IW4,I8),IISHFT(IW5,-I8)) C Using equivalenced variables instead reduces dependence on C intrinsic functions (g77 doesn't yet support IIOR for instance). C- integer*2 INP(*) integer LOR integer IREAL(LOR) integer O1 / 'FF80'X/ ! 0000 0000 0000 0000 1111 1111 1000 0000 integer O2 / '7F80'X/ ! 0000 0000 0000 0000 0111 1111 1000 0000 integer O3 / '003F'X/ ! 0000 0000 0000 0000 0000 0000 0011 1111 integer O4 / 'FFFF'X/ ! 0000 0000 0000 0000 1111 1111 1111 1111 integer O5 /'3FFFFF'X/ ! 0000 0000 0011 1111 1111 1111 1111 1111 integer*2 IWA integer*2 IWB integer*2 IW (5) byte BWA(2) byte BWB(2) byte BW (2,5) equivalence (IWA,BWA), (IWB, BWB), (IW,BW) do N=1,LOR/2 N5 = (N-1)*5 do J=1,5 IW(J) = INP(N5+J) end do call CvSwap(1,2,5,BW) ! Moving bytes ! Calculate reals from the 10 bytes. (THERE ARE TWO 36 BIT # PER ! 10 BYTES). In IAND(IWA,O1) and IAND(IWA,O3) the int*2 IWA is ! sign-extended to int*4 before evaluation. IWA = IW(1) IWB = IW(2) do J=1,2 IEXP = IAND(IWA,O1) ! Exponent and sign if (IWA .lt. 0) IEXP = IEOR(IEXP,O2) ILF = IAND(IWA,O3) ! Fraction ILF = ISHFT(ILF,16) IRF = IWB IRF = IAND(IRF,O4) IFRAC = IOR(ILF,IRF) if (IWA .lt. 0) IFRAC = IEOR(IFRAC,O5)+1 IFRAC = ISHFT(IFRAC,1) ITEMP = IOR(ISHFT(IFRAC,16),ISHFT(IFRAC,-16)) ! Combine backwards ITEMP = IOR(IEXP,ITEMP) IREAL((N-1)*2+J) = ITEMP BWA(1) = BW(2,4) ! Moving bytes .. BWA(2) = BW(1,3) ! .. for the second real BWB(1) = BW(2,5) BWB(2) = BW(1,4) end do end do return end C+ C NAME: C OCv2Int C PURPOSE: C Convert five-byte words to integer*4. C Called by HERDISK.FOR, HERDA.FOR and HERDRED.FOR C CALLING SEQUENCE: subroutine OCv2Int(iLen,cData,iData) C INPUTS: C iLen integer length of logical cData record C cData(iLen) character*1 logical record C OUTPUTS: C iData(iLen/5) integer logical record converted to integer*4 C CALLS: C MVBITS C MODIFICATION HISTORY: C MAY-2000, Paul Hick (UCSD/CASS) C NOV-2001, Paul Hick (UCSD/CASS; pphick@ucsd.edu) C Originally nTemp was declared as integer*2. g77 complains about C a type-mismatch in MVBITS. Apparently it wants integer*4 arguments. C- integer iLen character cData(iLen) integer iData(iLen/5) character cNull /0/ character cTemp*6 integer nTemp(2) equivalence (nTemp,cTemp) do N=1,iLen,5 cTemp = cData(N+1)//cData(N)//cData(N+3)//cData(N+2)//cNull//cData(N+4) call MVBITS(nTemp(1), 0,12,I,20) call MVBITS(nTemp(1),16,16,I, 4) call MVBITS(nTemp(2), 8, 4,I, 0) iData((N-1)/5+1) = I end do return end