I am receiving a formatting error from an input file, and I would like to determine where the formatting error is occurring in the input file.
My question is: Is there a way to print the line number of the input file where the error is occurring in my fortran code?
This is the error I get:
fmt: read unexpected character
apparent state: unit 4 named input_file
last format: (6(I3,X,F7.2,X,I2,X))
lately reading sequential formatted external IO
Which means that the code is getting hung up on some line in my input file that doesn't correspond with the above format.
Here is the part of my code where Fortran is reading in the input file:
DO 20 K = 1,NUMB
READ(4,200) (NSTN(J),TT(J),IKPS(J),J=1,6)
DO 30 J = 1,6
L = L+1
ISTO(L,N) = NSTN(J)
SECT(L,N) = TT(J)
KWV(L,N) = IKPS(J)
30 CONTINUE
20 CONTINUE
KOBS(N) = NSTM
10 CONTINUE
100 FORMAT(5(I2,X),F6.2,X,F5.2,X,F7.3,X,F6.3,X,F8.3,X,F6.3,
& X,F6.2,X,F5.2,X,I3,X,F4.1,X,F5.2,X,F7.3)
200 FORMAT(6(I3,X,F7.2,X,I2,X))
RETURN
END
I'd like to add a line in the above piece of code to identify the current line the code is reading, so that when it gets hung up, I'll know which line contains the error. Thank you for your help.
Here's what I tried and it's giving me another error:
c READ(4,200) (NSTN(J),TT(J),IKPS(J),J=1,6)
READ(4,200)line
READ(line,*,iostat=ios) (NSTN(J),TT(J),IKPS(J),J=1,6)
IF(ios>0)THEN
WRITE(*,*)'Error Reading Line',line
STOP
ENDIF
INTEGER ios
CHARACTER*(200)line
With a read statement like
READ(4,200) (NSTN(J),TT(J),IKPS(J),J=1,6)
an error in the input results in (error) termination of the program. One has no control over this termination, and in particular one can't do further processing.
There are two ways to avoid this termination, and both involve using an additional specifier in the read statement. One is iostat= and the other err=. If either of these is present then an error doesn't result in termination.
With iostat (for integer istat):
READ(4,200,iostat=istat) (NSTN(J),TT(J),IKPS(J),J=1,6)
then on an error condition, istat will have a (processor-dependent) positive value. It will be zero when (and only when) there is no error.
With err (for some label, say, 991):
READ(4,200,err=991) (NSTN(J),TT(J),IKPS(J),J=1,6)
Putting all that together, let's imagine an outer loop
DO 100 LINE=1,91959
READ(4,200,IOSTAT=ISTAT) (NSTN(J),TT(J),IKPS(J),J=1,6)
IF (ISTAT.NE.0) THEN
PRINT *, 'It went wrong on line', LINE
STOP
END IF
...
100 CONTINUE
or
DO 100 LINE=1,91959
READ(4,200,ERR=991) (NSTN(J),TT(J),IKPS(J),J=1,6)
...
100 CONTINUE
...
991 PRINT *, 'It went wrong on line', LINE
STOP
[I couldn't bring myself to write that code like it really was 1980.]
Add an explicit loop to read your data like:
DO 20 J = 1,6
write (*,*) 'Reading line = ', J
READ(4,100) NSTN(J),TT(J),IKPS(J)
20 CONTINUE
100 FORMAT(I3,X,F7.2,X,I2,X)
This way, you will know exactly where it stopped thank to the write statement in the reading loop. Note that I added two new labels, 20 to control the new loop and 100 for the new format statement. Adapt accordingly.
==============
DO 20 K = 1,NUMB
WRITE (*,*) 'Reading line = ', K
READ(4,200) (NSTN(J),TT(J),IKPS(J),J=1,6)
DO 30 J = 1,6
L = L+1
ISTO(L,N) = NSTN(J)
SECT(L,N) = TT(J)
KWV(L,N) = IKPS(J)
30 CONTINUE
20 CONTINUE
KOBS(N) = NSTM
200 FORMAT(6(I3,X,F7.2,X,I2,X))
RETURN
END
Related
I would like to read the same line of a file many time in Fortran. The concerned data are real values. I tried to build this code as test but I am always getting it wrong.
program advance
implicit none
integer , parameter :: ut = 20
character(len=7) :: fname = 'dat.dat'
integer :: n, idx
character(len=100) :: lnumber
open(unit = ut, file =fname, status='old', action='read')
n = 10
do idx = 1, n
read(ut, '(a)', advance = 'no') lnumber
print *, lnumber
end do
end program advance
The dat.dat file contains one line with 25.325654515464564564
The code return the following error.
At line 13 of file advance.f90 (unit = 20, file = 'dat.dat')
Fortran runtime error: End of record
How do I fix this bug?
Such non-advancing input (using advance='no') doesn't mean that the file position is not advanced at all. It means that the file position isn't advanced beyond what is needed to satisfy the requirements of the input list.
So, in this case, the file position is advanced by reading the single "real number" into the character variable lnumber. The next read will continue from this later point. This later point happens to be the end of the file.
With advancing input more generally, the file position is advanced to the start of the next record even if the record is not required in entirety.
As High Performance Mark comments, reading the same line over and over again likely isn't what you should be doing. You could read the line into a character variable (such as is done here) and repeatedly use that variable as an internal file. However, if you really want to read a line again, consider backspace.
I am trying to read a file called "syerasg.txt" in Fortran90. This text file includes panel data on 91 variables (columns) for 8984 individuals for 16 years (143 744 rows). This variables are divided in 7 groups and this groups are divided in 13 subgroups. I am trying to read this file with the following code:
PROGRAM main
IMPLICIT NONE
INTEGER, PARAMETER :: p=8984, tf=16, sem=53, emp=7, gap=13
INTEGER :: r, t, j, m, g, x, i, IOstatus
INTEGER, DIMENSION (p,tf,emp) :: yemp
INTEGER, DIMENSION (p,tf,emp,gap) :: gaps
OPEN(UNIT=4, FILE='syearsg.txt',STATUS='old') !start gap years
DO i=1,p
DO t=1,tf
DO j=1,emp
IF (j==1) THEN
READ(4,*)(gaps(i,t,j,g),g=1,13)
ELSE IF (j==2) THEN
READ(4,*)(gaps(i,t,j,g-13),g=14,26)
ELSE IF (j==3) THEN
READ(4,*)(gaps(i,t,j,g-26),g=27,39)
ELSE IF (j==4) THEN
READ(4,*)(gaps(i,t,j,g-39),g=40,52)
ELSE IF (j==5) THEN
READ(4,*)(gaps(i,t,j,g-52),g=53,65)
ELSE IF (j==6) THEN
READ(4,*)(gaps(i,t,j,g-65),g=66,78)
ELSE IF (j==7) THEN
READ(4,*)(gaps(i,t,j,g-78),g=79,91)
END IF
END DO
END DO
END DO
CLOSE(4)
END PROGRAM main
When, running the code I get the following message:
Fortran runtime error: End of file
Any ideas on how to solve this?
Your loop nest issues 1,006,208 (that is p*tf*emp) read statements. It's no surprise that the program runs past the end of a file with only 143,744 lines. read reads the values it is asked to read, then skips to the start of the next line ready for the next read.
You might be able to fix your program by fiddling around with non-advancing input, ie telling the read statements not to skip to the start of the next line. But it would be easier not to.
From what you write you should only be issuing p*tf read statements, then reading a single line containing 91 elements, then distributing those elements into gaps as your logic demands.
You might revise your code to something like this (untested and not very carefully checked)
INTEGER, DIMENSION(91) :: workvec
...
DO i=1,p
DO t=1,tf
READ(4,*) workvec
gaps(i,t,1,1:13) = workvec( 1:13)
gaps(i,t,2,1:13) = workvec(14:26)
...
END DO
END DO
I have just started doing my first research project, and I have just begun programming (approximately 2 weeks ago). Excuse me if my questions are naive. I might be using python very inefficiently. I am eager to improve here.
I have experimental data that I want to analyse. My goal is to create a python script that takes the data as input, and that for output gives me graphs, where certain parameters contained in text files (within the experimental data folders) are plotted and fitted to certain equations. This script should be as generalizable as possible so that I can use it for other experiments.
I'm using the Anaconda, Python 2.7, package, which means I have access to various libraries/modules related to science and mathematics.
I am stuck at trying to use For and While loops (for the first time).
The data files are structured like this (I am using regex brackets here):
.../data/B_foo[1-7]/[1-6]/D_foo/E_foo/text.txt
What I want to do is to cycle through all the 7 top directories and each of their 6 subdirectories (named 1,2,3...6). Furthermore, within these 6 subdirectories, a text file can be found (always with the same filename, text.txt), which contain the data I want to access.
The 'text.txt' files is structured something like this:
1 91.146 4.571 0.064 1.393 939.134 14.765
2 88.171 5.760 0.454 0.029 25227.999 137.883
3 88.231 4.919 0.232 0.026 34994.013 247.058
4 ... ... ... ... ... ...
The table continues down. Every other row is empty. I want to extract information from 13 rows starting from the 8th line, and I'm only interested in the 2nd, 3rd and 5th columns. I want to put them into lists 'parameter_a' and 'parameter_b' and 'parameter_c', respectively. I want to do this from each of these 'text.txt' files (of which there is a total of 7*6 = 42), and append them to three large lists (each with a total of 7*6*13 = 546 items when everything is done).
This is my attempt:
First, I made a list, 'list_B_foo', containing the seven different 'B_foo' directories (this part of the script is not shown). Then I made this:
parameter_a = []
parameter_b = []
parameter_c = []
j = 7 # The script starts reading 'text.txt' after the j:th line.
k = 35 # The script stops reading 'text.txt' after the k:th line.
x = 0
while x < 7:
for i in range(1, 7):
path = str(list_B_foo[x]) + '/%s/D_foo/E_foo/text.txt' % i
m = open(path, 'r')
line = m.readlines()
while j < k:
line = line[j]
info = line.split()
print 'info:', info
parameter_a.append(float(info[1]))
parameter_b.append(float(info[2]))
parameter_c.append(float(info[5]))
j = j + 2
x = x + 1
parameter_a_vect = np.array(parameter_a)
parameter_b_vect = np.array(parameter_b)
parameter_c_vect = np.array(parameter_c)
print 'a_vect:', parameter_a_vect
print 'b_vect:', parameter_b_vect
print 'c_vect:', parameter_c_vect
I have tried to fiddle around with indentation without getting it to work (receiving either syntax error or indentation errors). Currently, I get this output:
info: ['1', '90.647', '4.349', '0.252', '0.033', '93067.188', '196.142']
info: ['.']
Traceback (most recent call last):
File "script.py", line 104, in <module>
parameter_a.append(float(info[1]))
IndexError: list index out of range
I don't understand why I get the "list index out of range" message. If anyone knows why this is the case, I would be happy to hear you out.
How do I solve this problem? Is my approach completely wrong?
EDIT: I went for a pure while-loop solution, taking RebelWithoutAPulse and CamJohnson26's suggestions into account. This is how I solved it:
parameter_a=[]
parameter_b=[]
parameter_c=[]
k=35 # The script stops reading 'text.txt' after the k:th line.
x=0
while x < 7:
y=1
while y < 7:
j=7
path1 = str(list_B_foo[x]) + '/%s/pdata/999/dcon2dpeaks.txt' % (y)
m = open(path, 'r')
lines = m.readlines()
while j < k:
line = lines[j]
info = line.split()
parameter_a.append(float(info[1]))
parameter_b.append(float(info[2]))
parameter_c.append(float(info[5]))
j = j+2
y = y+1
x = x+1
Meta: I am not sure If I should give the answer to the person who answered the quickest and who helped me finish my task. Or the person with the answer which I learned most from. I am sure this is a common issue that I can find an answer to by reading the rules or going to Stackexchange Meta. Until I've read up on the recomendations, I will hold off on marking the question as answered by any of you two.
Welcome to stack overflow!
The error is due to name collision that you inadvertenly have created. Note the output before the exception occurs:
info: ['1', '90.647', '4.349', '0.252', '0.033', '93067.188', '196.142']
info: ['.']
Traceback (most recent call last):
...
The line[1] cannot compute - there is no "1"-st element in the list, containing only '.' - in python the lists start with 0 position.
This happens in your nested loop,
while j < k
where you redefine the very line you read previously created:
line = m.readlines()
while j < k:
line = line[j]
info = line.split()
...
So what happens is on first run of the loop, your read the lines of the files into line list, then you take one line from the list, assign it to line again, and continue with the loop. At this point line contains a string.
On the next run reading from line via specified index reads the character from the string on the j-th position and the code malfunctions.
You could fix this with different naming.
P.S. I would suggest using with ... as ... syntax while working with files, it is briefly described here - this is called a context manager and it takes care of opening and closing the files for you.
P.P.S. I would also suggest reading the naming conventions
Looks like you are overwriting the line array with the first line of the file. You call line = m.readlines(), which sets line equal to an array of lines. You then set line = line[j], so now the line variable is no longer an array, it's a string equal to
1 91.146 4.571 0.064 1.393 939.134 14.765
This loop works fine, but the next loop will treat line as an array of chars and take the 4th element, which is just a period, and set it equal to itself. That explains why the info variable only has one element on the second pass through the loop.
To solve this, just use 2 line variables instead of one. Call one lines and the other line.
lines = m.readlines()
while j < k:
line = lines[j]
info = line.split()
May be other errors too but that should get you started.
I have been trying to write a program in Fortran77 and am not able to finish it up, so I need a bit help to make it work.
At first I am just trying to open a .txt file read the file and write the file.
the .txt file is of the format shown below.
001,0.02014,3.1217
002,0.09611,3.1203
003,0.23753,3.1128
004,0.45527,3.0884
005,0.75772,3.0285
where the first column is integer and the second column coma separated contains a real number with 5 digits after the decimal point and third column again a real number with four digits after the decimal point.
My program looks as follows:
PROGRAM FIRST
IMPLICIT NONE
REAL,DIMENSION(304,3)::A
OPEN(UNIT =7 , FILE = "Pressure_values.txt",
1 FORM = "FORMATTED", STATUS = "OLD", ACTION = "READ")
READ(*,100) ((A(I,J),J=1,3), I=1,304)
WRITE(*,100) ((A(I,J),J=1,3), I=1,304)
100 FORMAT(I3,F10.5,F10.4)
STOP
END
Where am I going wrong?
You are not reading from the file. You need to read from unit 7.
read(7,100)
your code:
READ(*,100) ((A(I,J),J=1,3), I=1,304)
means "read from STDIN with format No.100", not the file you just opened. STDIN normally means the keyboard input stream. use:
READ(7,100) ((A(I,J),J=1,3), I=1,304)
instead.
I have some issues about opening and reading multiple files. I have to write a code which reads two columns in n files formatted in the same way (they are different only for the values...). Before this, I open another input file and an output file in which I will write my results. I read other questions in this forum (such as this one) and tried to do the same thing, but I receive these errors:
read(fileinp,'(I5)') i-49
1
devstan.f90:20.24:
fileLoop : do i = 50,52
2
Error: Variable 'i' at (1) cannot be redefined inside loop beginning at (2)
and
read(fileinp,'(I5)') i-49
1
Error: Invalid character in name at (1)
My files are numbered from 1 to n and are named 'lin*27-n.dat' (where n is the index starts from 1) and the code is:
program deviation
implicit none
character(len=15) :: filein,fileout,fileinp
integer :: row,i,h
real :: usv,usf,tsv,tsf,diff
write(*,'(2x,''Input file .......''/)')
read(*,'(a12)') filein
write(*,'(2x,''Output file........''/)')
read(*,'(a12)') fileout
open(unit = 30,File=filein)
open(unit = 20,File=fileout)
fileLoop : do i = 50,52
fileinp = 'lin*27-'
read(fileinp,'(I5)') i-49
open(unit = i,File=fileinp)
do row = 1,24
read(30,*) h,usv,tsv
read(i,*) h,usf,tsf
diff = usf - usv
write(20,*) diff
enddo
close(i)
enddo fileLoop
end program deviation
How can I solve it? I am not pro in Fortran, so please don't use difficult language, thanks.
The troublesome line is
read(fileinp,'(I5)') i-49
You surely mean to do a write (as in the example linked): this read statement attempts to read from the variable fileinp rather than writing to it.
That said, simply replacing with write is probably not what you need either. This will ignore the previous line
fileinp = 'lin*27-'
merely setting to, in turn, "1", "2", "3" (with leading blanks). Something like (assuming you intend that * to be there)
write(fileinp, '("lin*27-",I1)') i-49
Note also the use of I1 in the format, rather than I5: one may want to avoid blanks in the filename. [This is suitable when there is exactly one digit; look up Iw.m and I0 when generalizing.]