C++********************************************************************* C C OPENFIL.F ADAPTED FROM OPEN3.FOR OCT 88 ArDean Leith C LONG FILENAMES OCT 88 ArDean Leith C MERGED WITH OPENF AUG 96 ArDean Leith C -1, -3 & -7 FOURIER REMOVED AUG 96 ArDean Leith C F90 CHANGES APR 98 ArDean Leith C USED LUNHDR JAN 99 ArDean Leith C INDEXED STACKS JAN 03 ArDean Leith C HEADER COPY FEB 03 ArDean Leith C ENDEDNESS FEB 03 ArDean Leith C REMOVED IRTFLG INPUT APR 04 ARDEAN LEITH C MPI OPEN BUG & BCAST CHANGES OCT 08 ARDEAN LEITH C C ********************************************************************** C=* FROM: SPIDER - MODULAR IMAGE PROCESSING SYSTEM. AUTHOR: J.FRANK * C=* Copyright (C) 1985-2008 Health Research Inc. * C=* * C=* HEALTH RESEARCH INCORPORATED (HRI), * C=* ONE UNIVERSITY PLACE, RENSSELAER, NY 12144-3455. * C=* * C=* Email: spider@wadsworth.org * C=* * C=* This program is free software; you can redistribute it and/or * C=* modify it under the terms of the GNU General Public License as * C=* published by the Free Software Foundation; either version 2 of the * C=* License, or (at your option) any later version. * C=* * C=* This program is distributed in the hope that it will be useful, * C=* but WITHOUT ANY WARRANTY; without even the implied warranty of * C=* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * C=* General Public License for more details. * C=* * C=* You should have received a copy of the GNU General Public License * C=* along with this program; if not, write to the * C=* Free Software Foundation, Inc., * C=* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * C=* * C ********************************************************************** C C OPENFIL(LUNT,FILNAM,LUN,NSAM,NROW,NSLICE,NSTACK,DISP,IRTFLG) C C PURPOSE: OPEN NEW OR EXISTING DATA FILE FOR RANDOM C ACCESS READING/WRITING. CALLED FOR REGULAR FILES C AND OVERALL STACK HEADERS. THIS ROUTINE IS NOT C CALLED FOR CREATING STACKED IMAGES WITHIN A C STACK (ONLY FOR THE OVERALL STACK). NEITHER C IS IT USED FOR INLINE STACKS! C C PARAMETERS: C LUNT UNIT TO COPY HEADER VALUES FROM (SENT) C FILNAM CHARACTER ARRAY, CONTAINING FILE NAME (SENT) C LUN LOGICAL UNIT NUMBER FOR FILNAM. (SENT) C NSAM,NROW DIMENSIONS OF FILE (SENT OR RETURNED) C NSLICE NUMBER OF SLICES IN IMAGE (SENT OR RETURNED) C NSTACK STACK INDICATOR (SENT / RETURNED) C ON INPUT: C FOR NEW FILE 0 : NOT A STACK, C >0 : REGULAR STACK C <0 : INDEXED STACK, MAX TOTAL IMAGES C ON OUTPUT: C -2 : NOT A STACK C >=0 : MAX IMAGE NUMBER NOW IN STACK. C C DISP CHARACTER VARIABLE CONTAINING DISPOSITION (SENT) C SEE OPFIL.F FOR POSSIBLE VALUES C KEEPEXT TO KEEP EXTENSION (SENT) C IRTFLG ERROR RETURN FLAG. (RETURNED) C 0 : NORMAL RETURN C 1 : ERROR RETURN C 5 : NOT A SPIDER INPUT IMAGE C C CODING: BASED ON IMAGE PARAMETERS NSAM,NROW, & NSLICE, A C NEW FILE IS OPENED WITH IREC RECORDS, EACH NSAM * 4 C BYTES LONG. IREC ALLOWS SPACE FOR THE 3-D DISTRIBUTION, C PLUS NORMAL IMAGE HEADER. C C VARIABLES: ITYPE (TYPE) FILE TYPE SPECIFIER. C +1 R 2-D IMAGE C +3 R3 3-D VOLUME FILE C -11 O2 2-D FOURIER TRANSFORM, MIXED RADIX ODD C -12 E2 2-D FOURIER TRANSFORM, MIXED RADIX EVEN C -21 O3 3-D FOURIER TRANSFORM, MIXED RADIX ODD C -22 E3 3-D FOURIER TRANSFORM, MIXED RADIX EVEN C C CALL TREE: SEE OPFILEC C C23456789 123456789 123456789 123456789 123456789 123456789 123456789 12 C--********************************************************************* SUBROUTINE OPENFIL(LUNT,FILNAM,LUN,NSAM,NROW,NSLICE,NSTACK, & ITYPE,DISP,KEEPEXT,IRTFLG) INCLUDE 'CMLIMIT.INC' INCLUDE 'CMBLOCK.INC' INCLUDE 'LABLOCK.INC' COMMON /LUNARA/ LUNARA(100),LUNSTK(100),LUNARB(100) CHARACTER(LEN=*) :: FILNAM CHARACTER(LEN=MAXNAM) :: FILNM CHARACTER(LEN=2*MAXNAM) :: MSG CHARACTER(LEN=1) :: NULL,DISP LOGICAL :: EX,CALLERRT,OPENED,KEEPEXT #ifdef USE_MPI include 'mpif.h' LOGICAL :: USEBCAST COMMON /COMM_MPI/USEBCAST ICOMM = MPI_COMM_WORLD CALL MPI_COMM_RANK(ICOMM, MYPID, MPIERR) IF (.NOT. USEBCAST) MYPID = -1 !KLUDGE FOR 'AP REF' #else MYPID = -1 #endif NULL = CHAR(0) C SET FLAG FOR ERRONEOUS RETURN IRTFLG = 1 C CHECK IF USER WANTS TO USE THE IN-LINE BUFFER. INLNED = 0 IF (FILNAM(1:1) .EQ. '_') THEN CALL INLNBUF(FILNAM,NLET,INLNED,IRTFLGT) IF (IRTFLGT .NE. 0) RETURN IF (DISP .EQ. 'U' .OR. DISP .EQ. 'N') THEN EX = .FALSE. ELSE EX = .TRUE. ENDIF FILNM = FILNAM(1:NLET) ELSE C USE REGULAR FILE INLNED = 0 LUNC = LUN C NULLIFY THE INLINE POINTER (CLOSEINLN IS INSIDE OPENINLN.F) CALL CLOSEINLN(LUN,IRTFLGT) IF (KEEPEXT) THEN FILNM = FILNAM NLET = lnblnk(FILNM) ELSE CALL FILNAMANDEXT(FILNAM,DATEXC,FILNM,NLET,.TRUE.,IRTFLGT) IF (IRTFLGT .NE.0) RETURN ENDIF C SEE IF FILE EXISTS NOW IF (MYPID .LE. 0) THEN INQUIRE(FILE=FILNM(1:NLET),IOSTAT=IER,EXIST=EX) ENDIF #ifdef USE_MPI IF (USEBCAST) THEN CALL BCAST_MPI('OPENFIL','EX',EX,1,'L',ICOMM) CALL BCAST_MPI('OPENFIL','IER',IER,1,'I',ICOMM) ENDIF #endif IF (IER .NE. 0) THEN MSG = 'OPENFIL; INQUIRY ERROR: ' // FILNM(1:NLET) CALL ERRT(101,MSG,NE) RETURN ENDIF ENDIF C SET ACTUAL LUN FOR THIS FILE LUNARB(LUN) = LUN CALLERRT = (DISP(1:1) .NE. 'Z' .AND. DISP(1:1) .NE. 'E') 10 IF (DISP .EQ. 'U' .OR. DISP .EQ. 'N') THEN C USER WANTS A NEW FILE TO WRITE INTO ---------------------- NEW IF (EX) THEN C FILE IS IS OPENED WITH 'UNKNOWN' BUT ALREADY EXISTS; IT WILL C BE REPLACED. OLD FILES ARE DELETED FIRST IF (MYPID .LE. 0) THEN OPEN(UNIT=LUN,FILE=FILNM(1:NLET),STATUS='OLD') CLOSE(UNIT=LUN,STATUS='DELETE',IOSTAT=IER) ENDIF #ifdef USE_MPI IF (USEBCAST)CALL BCAST_MPI('OPENFIL','IER',IER,1,'I',ICOMM) #endif IF (IER .NE. 0) THEN MSG = 'OPENFIL; DELETING FILE: ' // FILNM(1:NLET) CALL ERRT(101,MSG,NE) RETURN ENDIF ENDIF C INITIALIZE HEADER OBJECT FOR NEW IMAGE CALL LUNSETHDR(LUNT,LUN,NSAM,NROW,NSLICE,ITYPE,NSTACK,IRTFLGT) C SET FMIN.... TO AVOID FLT. PT. ERROR ON DEC CALL LUNSETSTAT(LUN,0,0.0,0.0,0.0,0.0,IRTFLGT) IF (INLNED .EQ. 0) THEN C REGULAR FILE, NOT INLINE FILE LENREC = LENOPENFILE(NSAM*4) IF (MYPID .LE. 0) THEN OPEN(LUN,FILE=FILNM(1:NLET),STATUS='NEW', & FORM='UNFORMATTED', & ACCESS='DIRECT',IOSTAT=IER,RECL=LENREC) ENDIF #ifdef USE_MPI IF (USEBCAST) THEN CALL BCAST_MPI('OPENFIL','IER',IER,1,'I',ICOMM) ENDIF #endif IF (IER .NE. 0) THEN MSG = 'OPENFIL; OPENING FILE: ' // FILNM(1:NLET) CALL ERRT(101,MSG,NE) RETURN ENDIF C FOR USING NEW FILE ON OLDER SPIDER RELEASES CALL LUNSET25(LUN,-1,IRTFLGT) ELSE C SET UP INLINE BUFFER AND TIE IT TO LUN C SAVE ISTACK IN NON-VOLATILE PART OF HEADER OBJECT CALL LUNGETISTACK(LUN,ISTACK,IRTFLGT) CALL LUNSETSTKALL(LUN,ISTACK,IRTFLGT) CALL LUNGETLAB(LUN,LABREC,INDXREC,NRECS,LABBYT, & LENBYT,IRTFLGT) NWORDS = (NRECS + INDXREC) * LENBYT / 4 CALL OPENINLN(LUN,INLNED,.TRUE.,NSAM,NWORDS, & .TRUE.,IRTFLGT) IF (IRTFLGT .NE. 0) RETURN ENDIF C PUSH HEADER OBJECT INFO INTO NEW FILE CALL LUNWRTHED(LUN,NSAM,0,IRTFLGT) GOTO 2000 C --------------------------------------------------------- OLD ELSEIF (DISP .EQ. 'O' .OR. DISP .EQ. 'K' .OR. & DISP .EQ. 'Z' .OR. & DISP .EQ. 'E' .OR. DISP .EQ. 'M') THEN C FILE EXISTS, AND IS ACCESSED WITH 'OLD', OPEN THE FILE IF (.NOT. EX) THEN C ERROR -- FILE DOES NOT EXIST, BUT BEING OPENED WITH 'OLD IF (MYPID .LE. 0) & WRITE(NOUT,*) '*** FILE NOT FOUND: ',FILNM(1:NLET) #ifdef USE_MPI c write(6,*) ' openfil; ',mypid, ' not found: ',filnm(1:nlet) #endif C FOR DISP=Z, DO NOT STOP THE BATCH JOB BY CALLING ERRT IF (CALLERRT) THEN MSG = 'OPENFIL; FILE NOT FOUND: ' // FILNM(1:NLET) CALL ERRT(101,MSG,NE) ENDIF RETURN ENDIF IF (INLNED .NE. 0) THEN C USE EXISTING INLINE BUFFER, TIE IT TO LUN & RETRIEVE NSAM CALL OPENINLN(LUN,INLNED,.FALSE.,NSAM,0,CALLERRT,IRTFLGT) IF (IRTFLGT .NE. 0) RETURN ELSE C REGULAR FILE ACCESS LENREC = LENOPENFILE(256*4) IF (MYPID .LE. 0) THEN OPEN(LUN,FILE=FILNM(1:NLET),STATUS='OLD', & ACCESS='DIRECT', & FORM='UNFORMATTED',RECL=LENREC,IOSTAT=IER) ENDIF #ifdef USE_MPI IF (USEBCAST) THEN CALL BCAST_MPI('OPENFIL','IER',IER,1,'I',ICOMM) ENDIF #endif IF (IER .NE. 0) THEN C SEE IF FILE ALREADY OPEN ON DIFFERENT LUN IF (MYPID .LE. 0) THEN INQUIRE(FILE=FILNM(1:NLET),IOSTAT=IER,OPENED=OPENED, & NUMBER=LUNOPENED) ENDIF #ifdef USE_MPI IF (USEBCAST) THEN CALL BCAST_MPI('OPENFIL','IER',IER,1,'I',ICOMM) CALL BCAST_MPI('OPENFIL','OPENED',OPENED,1,'L',ICOMM) CALL BCAST_MPI('OPENFIL','LUNOPENED',LUNOPENED,1, & 'I',ICOMM) ENDIF #endif IF (OPENED) THEN C MUST REDIRECT OLD LUNS TO CURRENT LUN, IF (MYPID .LE. 0) CLOSE(LUNOPENED) DO I = 1,100 IF (LUNARB(I) .EQ. LUNOPENED) LUNARB(I) = LUN ENDDO C NOW WE CAN REOPEN THIS SAME FILE ON LUN IF (MYPID .LE. 0) THEN OPEN(LUN,FILE=FILNM(1:NLET),STATUS='OLD', & ACCESS='DIRECT', & FORM='UNFORMATTED',RECL=LENREC,IOSTAT=IER) ENDIF #ifdef USE_MPI IF (USEBCAST) THEN CALL BCAST_MPI('OPENFIL','IER',IER,1,'I',ICOMM) ENDIF #endif ELSE C UNKNOWN ERROR MSG = 'OPENFIL; OPENING FILE: ' // FILNM(1:NLET) CALL ERRT(101,MSG,NE) RETURN ENDIF ENDIF ENDIF C READ OVERALL HEADER FROM FILE CALL LUNREDHED(LUN,256,0,.TRUE.,IRTFLGT) IF (IRTFLGT .NE. 0 .AND. MYPID .LE. 0) THEN WRITE(NOUT,*) '*** ERROR READING HEADER OF: ',FILNM(:NLET) RETURN ENDIF C NEED ITYPE CALL LUNGETTYPE(LUN,ITYPE,IRTFLGT) IF (ITYPE .EQ. -1 .OR. ITYPE .EQ. -3 .OR. ITYPE .EQ. -7) THEN C WANT TO READ OBSOLETE FORMAT FOURIER FILE WRITE(NOUT,96) 96 FORMAT(' *** CAN NOT READ OBSOLETE FOURIER FORMAT',/, & '*** CONVERT FOURIER FILE TO REAL FORMAT USING ', & 'ORIGINAL VERSION OF SPIDER.'/) CALL ERRT(100, 'OPENFIL',NE) RETURN ENDIF C NEED NSAM VALUE CALL LUNGETSIZE(LUN,NSAM,NROW,NSLICE,IRTFLGT) IF (IRTFLGT .NE. 0) RETURN IF (ITYPE .EQ. 0 .OR. & NSAM .LE. 0 .OR. NROW .LE. 0 .OR. NSLICE .LE. 0 .OR. & NSAM .GT. 100000 .OR. NROW .GT. 100000 .OR. & NSLICE .GT. 100000) THEN C NOT A NATIVE SPIDER IMAGE C FLIP BYTES IN HEADER OBJECT CALL LUNFLIPHDR(LUN,IRTFLGT) CALL LUNSETFLIP(LUN,1,IRTFLG) C NEED ITYPE & SIZE CALL LUNGETTYPE(LUN,ITYPE,IRTFLGT) CALL LUNGETSIZE(LUN,NSAM,NROW,NSLICE,IRTFLGT) IF (IRTFLGT .NE. 0) RETURN IF (ITYPE .EQ. 0 .OR. & NSAM .LE. 0 .OR. NROW .LE. 0 .OR. NSLICE .LE. 0 .OR. & NSAM .GT. 100000 .OR. NROW .GT. 100000 .OR. & NSLICE .GT. 100000) THEN C PROBABLY NOT A SPIDER IMAGE IF (CALLERRT) THEN CALL ERRT(101,'INVALID HEADER, NOT A SPIDER IMAGE?',NE) ENDIF RETURN ENDIF WRITE(NOUT,*) ' NON-NATIVE BYTE ORDERED SPIDER FILE' ENDIF C ON UNIX, REOPEN THE FILE WITH FINAL RECORD LENGTH IF (INLNED .EQ. 0) THEN CLOSE(LUN) LENREC = LENOPENFILE(NSAM*4) IF (MYPID .LE. 0) THEN OPEN(LUN,FILE=FILNM(1:NLET),STATUS='OLD', & FORM='UNFORMATTED', & ACCESS='DIRECT',IOSTAT=IER,RECL=LENREC) ENDIF #ifdef USE_MPI IF (USEBCAST) THEN CALL BCAST_MPI('OPENFIL','IER',IER,1,'I',ICOMM) ENDIF #endif IF (IER .NE. 0) THEN MSG = 'OPENFIL; REOPENING FILE: ' // FILNM(1:NLET) CALL ERRT(101,MSG,NE) RETURN ENDIF ENDIF ELSE MSG = 'OPENFIL; PGM. ERROR, UNKNOWN DISP: ' // DISP CALL ERRT(101,MSG,NE) RETURN ENDIF 2000 CONTINUE C SAVE ISTACK IN NON-VOLATILE PART OF HEADER OBJECT CALL LUNGETISTACK(LUN,ISTACK,IRTFLGT) CALL LUNSETSTKALL(LUN,ISTACK,IRTFLGT) C SAVE MAXIM IN NON-VOLATILE PART OF HEADER OBJECT CALL LUNCOPYMAXIM(LUN,MAXIM,IRTFLGT) C SET FINAL LUNARA OFFSET VALUE FOR USE BY REDLIN/WRTLIN. C FOR INDEXED STACKS THIS INCLUDES INDEX OFFSET IF (ISTACK .NE. 0) THEN CALL LUNSETIMGOFF(LUN,0,NSAM,IRTFLGT) ELSE IVAL = 1 CALL LUNSETIMGOFF(LUN,IVAL,NSAM,IRTFLGT) ENDIF C PUT COMMON VALUES INTO COMMON AREA (NOT NEEDED IN FUTURE?) CALL LUNSETCOMMON(LUN,IRTFLGT) C WRITE OUT FILE OPENING INFO CALL LUNSAYINFO(LUN,IRTFLGT) C NEED TO RETURN NSTACK & MAXIM IF (ISTACK .NE. 0) THEN C RETURN CURRENT HIGHEST IMAGE NUMBER IN NSTACK NSTACK = MAXIM ELSE C NOT A STACK, RETURN -2 NSTACK = -2 ENDIF C SET FLAG FOR NORMAL RETURN IRTFLG = 0 RETURN END