Close This Window

Please download official ILL logos here


For using on the web or on a screen

For printing in high resolution

White version, for dark backgrounds



Download PNG

Download TIF

Download white PNG

Download JPG

Download EPS

Download white EPS logo

Institut Laue-Langevin

The Computing for Science (CS) group supports ILL scientists, students and visitors in a number of activities including data analysis, instrument simulation and sample simulation.

Back to ILL Homepage
English French Deutsch 

Data treatment

A short guide to using MinGW for Fortran programming on PCs

Ron Ghosh, ILL, October 2004

Programming in Fortran is not hard, and the very simple examples given here are easily adaptable to be really useful programs. They introduce the reader to a few libraries which are available at the ILL which offer useful graphics on PC-Windows. The MinGW program suite includes g77 (aka f77) C, C++, objective C, from the GNU package. The self extracting file MinGW-3.1.0-1.exe contains the compilers and tools (about 45MB).

Equivalent libraries exist also for CYGWIN and for Macintosh OS-X all using the same basic GNU tools.

First steps...

A very simple Fortran program to read and write out a data file

Program progrw.f - written with Notepad

      program progrw
c***** a simple program to read and write data
c     R. Ghosh, ILL, version 1 October 2004
c     g77 -o progrw progrw.f
      parameter (inmax=100)
c***** maximum number of lines to be read from file
      real x(inmax),y(inmax),yer(inmax)
c***** define arrays of variables x,y,yer
      open(unit=2,file='mydata.dat')
c***** open data file 'mydat.dat' in the current directory
      do i=1,inmax
        read(2,*,end=20) x(i),y(i),yer(i)
c*****  read one line at a time, going to 20 on reaching the end of file
        j=i
c*****  keep a note of lines read in
      end do
20    continue
      close(unit=2)
c***** finished with file input unit
      write(6,*) j, ' lines have been read'
c***** the unit number 6 is usually associated with screen output
      do i=1,j
c***** now write out the variables which have been stored
        write(6,*)' line ',i,' has ',x(i),y(i),yer(i)
      end do
      end

to run this program, compile progrw.f and link to make progrw.exe


g77 -o progrw progrw.f

and run

progrw
           10 lines have been read
  line            1 has   1.6860990E-03   464.5000       10.77613   
  line            2 has   4.1995151E-03   493.0833       6.410170   
  line            3 has   6.5153618E-03   476.0625       5.454714   
  line            4 has   9.1368612E-03   444.2500       3.983224   
  line            5 has   1.1507930E-02   496.5000       4.210955   
  line            6 has   1.3852740E-02   512.4167       3.772770   
  line            7 has   1.6353959E-02   510.4375       3.260999   
  line            8 has   1.8697230E-02   503.2954       3.382090   
  line            9 has   2.1087030E-02   493.0333       2.866570   
  line           10 has   2.3404090E-02   507.0179       3.008968   




Clearly one wants more flexibility than just reading the file
"mydata.dat".  In the next example the reading and writing
activities are localised in subroutines.  Because there might be
errors in the data it is useful to have a way of showing this.

To top

Second example using reading and writing subroutines

Program progrwm.f - written with Notepad

program progrwm
c***** a simple program to read and write data using subroutines
c R. Ghosh, ILL, version 1 October 2004
c g77 -o progrwm progrwm.f daread.f dawrit.f
parameter (inmax=100)
c***** maximum number of lines to be read from file
real x(inmax),y(inmax),yer(inmax)
c***** define arrays of variables x,y,yer
call daread(x,y,yer,in,inmax)
c***** routine reads in from file
iout=6
call dawrit(x,y,yer,in,iout)
c***** writes out to unit 6 (terminal)
end

and a read routine daread.f

subroutine daread(xx,yy,yr,in,inmax)
c****** routine to read from a 3 column data file
c xx out first column value
c yy out second column value
c yr out third column value
c in out number of lines read
c inmax in maximum lines expected
c R. Ghosh, Ill, October 2004
real xx(inmax),yy(inmax),yr(inmax)
common/infile/fname
character*100 fname
c***** the filename to be read has a maximum length of 100 characters
write(6,1)
1 format(' Give input filename : ',$)
read(5,2) fname
2 format(a)
open(unit=2,file=fname)
do i=1,inmax
read(2,*,err=25,end=20) xx(i),yy(i),yr(i)
j=i
end do
20 continue
close(unit=2)
c***** not required further - close input
write(6,3) j
3 format(i3,' lines have been read in')
in=j
return
25 write(6,26)j
26 format(' daread - error after line ',i4)
c***** when reading data it is useful to offer guidance on
c potential errors therein
stop
end

and a write routine dawrit.f

subroutine dawrit(xx,yy,yr,nin,nunit)
c****** routine to write out a 3 column data file
c if nunit is 6 then output is to terminal
c otherwise output is to a named file
c
c xx in first column value
c yy in second column value
c yr in third column value
c nin in number of lines <=100
c nunit in output unit
c R. Ghosh, ILL, October 2004
real xx(nin),yy(nin),yr(nin)
common/oufile/fname
character*120 fname
c***** the filename to be read has a maximum length of 120 characters
if(nin.gt.100) stop ' dawrit- cannot write more than 100 data'
c***** all files treated by these routines should have less than 101 lines
if(nunit.ne.6) then
write(6,1)
1 format(' Give output filename : ',$)
read(5,2) fname
2 format(a)
end if
c***** open a new file
if(nunit.ne.6) open(unit=nunit,file=fname,status='new')
c***** could use 'unknown' rather than 'new' if allow overwriting
do i=1,nin
write(nunit,*) xx(i),yy(i),yr(i)
j=i
end do
if(nunit.ne.6) close(unit=nunit)
c***** finished writing file output - close file
write(6,3) j
3 format(i3,' lines have been written')
return
end

putting it all together

g77 -o progrwm progrwm.f daread.f dawrit.f
progrwm
Give input filename : mydata.dat
10 lines have been read in
1.6860990E-03 464.5000 10.77613
4.1995151E-03 493.0833 6.410170
6.5153618E-03 476.0625 5.454714
9.1368612E-03 444.2500 3.983224
1.1507930E-02 496.5000 4.210955
1.3852740E-02 512.4167 3.772770
1.6353959E-02 510.4375 3.260999
1.8697230E-02 503.2954 3.382090
2.1087030E-02 493.0333 2.866570
2.3404090E-02 507.0179 3.008968
10 lines have been written

To top

Subtracting two sets of data is the next example

program progsub

c***** a simple program to read two data files and subtract
c the second from the first, using subroutines
c R. Ghosh, ILL, version 1 October 2004
c g77 -o progsub progsub.f daread.o dawrit.o
parameter (inmax=100)
c***** maximum number of lines to be read from file
real x1(inmax),y1(inmax),yer1(inmax)
real x2(inmax),y2(inmax),yer2(inmax)
real x3(inmax),y3(inmax),yer3(inmax)
c***** define arrays of variables x,y,yer
call daread(x1,y1,yer1,in1,inmax)
c***** routine reads in from file
call daread(x2,y2,yer2,in2,inmax)
c***** trivial check for compatibility
if(in2.ne.in1) stop ' input files have differing lengths!'
write(6,5)
5 format(' Give multiplier for second set of data [1.0] :',$)
read(5,6) fmul
6 format(g12.6)
if(fmul.eq.0) fmul=1.0
c
c***** calculate difference and new error values
c
do i=1,in1
x3(i)=x1(i)
c***** take first data as reference
y3(i)=y1(i)-fmul*y2(i)
yysq=yer1(i)**2+(fmul*yer2(i))**2
yer3(i)=sqrt(yysq)
end do
c
c***** output results
c
iout=6
call dawrit(x3,y3,yer3,in1,iout)
c***** writes out to unit 6 (terminal)
iout=2
c***** output into a new file
call dawrit(x3,y3,yer3,in1,iout)
end

Reusing the routine from above:

g77 -o progsub progsub.f daread.f dawrit.f

or, because the compiled subroutines remain there:

g77 -o prgsub progsub.f daread.o dawrit.o

and test it..

progsub
Give input filename : mydata.dat
10 lines have been read in
Give input filename : mydata.dat
10 lines have been read in
Give multiplier for second set of data [1.0] :-1.0
1.6860990E-03 929.0000 15.23975
4.1995151E-03 986.1666 9.065350
6.5153618E-03 952.1250 7.714130
9.1368612E-03 888.5000 5.633129
1.1507930E-02 993.0000 5.955190
1.3852740E-02 1024.833 5.335503
1.6353959E-02 1020.875 4.611749
1.8697230E-02 1006.591 4.782998
2.1087030E-02 986.0666 4.053942
2.3404090E-02 1014.036 4.255323
10 lines have been written
Give output filename : newdata.dat
10 lines have been written


as a simple check the y data have doubled, and the error
increased by a factor of 1.414 which is correct if the data
are from two uncorrelated sets of counting events(SQRT(2.0))

To top

Plotting data

Plotting data using library routine RSPLT from
library librlib.a
which, in turn, calls Prof. Tim Pearson's
PGPLOT library

        program daplo
c example of command line driven plotting program
c R. Ghosh ILL, October 2004, version 1
c SGI f77 -o daplo daplo.f daread1.f librlib.a libpgplot.a -lX11
cMinGW g77 -o daplo daplo.f daread1.f librlib.a libpggw520.a -wl,subsystem,console -mwindows
c
c*****
parameter (inmax=100)
real x(inmax),y(inmax),yer(inmax)
common/infile/filnam
character*100 filnam,str
character*50 title
noargs=iargc()
c***** gives number of fields in command line
if(noargs.lt.1.or.noargs.gt.6) then
write(*,*)
1' plot data : usage daplo filename ymin ymax xmin xmax'
call exit
end if

filnam=' '
str=' '
c***** set the whole string str to blanks
call getargp(1,str)
c***** this is first character string in command line - file name
filnam=str
call daread1(x,y,yer,nin,inmax)
c***** daread1 will get filename from filnam
iidev=1
call pgnopn(iidev,' ',ier)
c***** open graphics
if (ier.ne.0) stop 'no screen device PGPLOT_ILL_DEV_1'
c***** put filename into title for plot
title=str
call rsplt(x,y,yer,nin,2,1,'X','Y',title)
call pgnend(iidev)
end


subroutine daread1(xx,yy,yr,in,inmax)
c****** routine to read from a 3 column data file
c xx out first column value
c yy out second column value
c yr out third column value
c in out number of lines read
c inmax in maximum lines expected
c Input filename set in common/infile/fname
c R. Ghosh, Ill, October 2004
real xx(inmax),yy(inmax),yr(inmax)
common/infile/fname
character*100 fname
c***** the filename to be read has a maximum length of 100 characters
open(unit=2,file=fname)
do i=1,inmax
read(2,*,end=20) xx(i),yy(i),yr(i)
j=i
end do
20 continue
close(unit=2)
c***** not required further - close input
write(6,3) j
3 format(i3,' lines have been read in')
in=j
return
end



build it
g77 -o daplo daplo.f daread1.f librlib.a libpggw520.a -wl,subsystem,console -mwindows

now we can run this directly from the command line..

daplo sasteflon.dat




The batch file mingwvars.bat may be used as a shortcut to setting up
a CMD program window used for development, modifying this shortcut
to start in an appropriate test directory. Part of the g77 command
line is setup as an environment variable %PGFLAG% simplifying the
above command to:
g77 -o daplo daplo.f daread1.f librlib.a %PGFLAG% 

To top

Using GNU-make

The command for building the program is getting rather complicated
and a useful tool is gmake (GNU make) which uses a text "makefile"
to build only those components which have been changed. The
"target" (result) is denoted by the name+colon followed by the
files used to create it. The following line has the
appropriate command, starting with a colon. In the MinGW distribution
the make program is initially named mingw32-make.exe


notepad makefile

all: daplo progsub progrwm
daplo.exe: daplo.f daread1.o
g77 -o daplo daplo.f daread1.o librlib.a libpggw520.a -wl,subsystem,console -mwindows
daread1.o: daread1.f
g77 -c daread1.f
progsub.exe: progsub.f daread.o dawrit.o
g77 -o progsub progsub.f daread.o dawrit.o
progrw.exe: progrw.f daread.o dawrit.o
g77 -o progrw progrw.f daread.o dawrit.o
daread.o: daread.f
g77 -c daread.f
dawrit.o: dawrit.f
f77 -c dawrit.f
clean:
del *.o

The command make daplo makes daplo.exe
The command make all makes daplo.exe progsub.exe and progrw.exe
The command make clean removes all the .o intermediate object files

To top

Fitting data

Introducing a fitting library - we can try fitting a gaussian curve


Again we have the idea of a standard (or set of standard routines)
to read in various types of data, and sets of calculation
rouines to fit to the data using the library.


The MAIN program serves primarily to label the fitting parameters
and select the reading and calculating routines.

      PROGRAM FTEST
C***** BASIC EXAMPLE ROUTINE FOR FITFUN
C***** Link FTEST,MYREAD,GAUSS,FITFUN/LIB,LIBPG/LIB
C HP setenv LPATH /lib:/usr/lib:/usr/local/lib:/usr/lib/X11R5
C HP f77 -o ftst ftst.o myread.o gauss.o libfitfun.a -lpgplot -lX11 -lU77
C IRIX f77 -o ftst ftst.o myread.o gauss.o libfitfun.a libpgplot.a -lX11
C MinGW f77 -o ftst ftst.o myread.o gauss.o libffn66m.a libpggw520.a \
C -wl,--subsystem,console -mwindows
EXTERNAL MYREAD,GAUSS
C
C***** MYREAD IS A USER SUPPLIED ROUTINE TO READ IN ONE SPECTRUM EACH CALL
C
C***** GAUSS IS A USER'S ROUTINE TO CALCULATE THE REQUIRED FUNCTION
C
COMMON/TITLES/NAMES(40),TX,TY
COMMON/TITLEP/NPARAS
COMMON/WORK/W(30660)
C***** THIS IS SUFFICIENT FOR 1600 DATA AND 10 PARAMETERS !
COMMON/VERSION/VERP
C***** VERP IS TYPED BY THE PROGRAM INDICATING THE CURRENTLY RUNNING VERSION
C
CHARACTER*8 NAMES
CHARACTER*4 PNAM
CHARACTER*20 TX,TY
C
DATA NAMES/'CENTRE ','SIGMA','FLAT BAK','SLOPE',
1'HEIGHT',35*' '/
DATA PNAM/'ftst'/
DATA TX/'CHANNEL'/
DATA TY/'COUNTS'/
DATA NPARAS/5/
C
VERP=2.0
CALL FITFUN(PNAM,MYREAD,GAUSS)
C
END

The calculation of a simple gaussian:

SUBROUTINE GAUSS(NPAR,PARM,NFIT,XUSE,YUSE,YRUSE,YCALC,F)
C
C CALC OF F AND YCALC FOR GAUSSIAN
C
DIMENSION PARM(NPAR)
DIMENSION YCALC(NFIT),XUSE(NFIT),YUSE(NFIT)
1,YRUSE(NFIT),F(NFIT)
C
C The first parameter PARM(1) is the peak centre
C PARM(2) is the peak deviation
C PARM(3) is the flat background
C PARM(4) is the sloping background
C PARM(5) is the peak height
C There are NFIT data values of Xuse Yuse and Yerror
DO 10 I=1,NFIT
C***** YCALC WILL CONTAIN CALCULATED FUNCTION FOR PLOTTING/LISTING
YCALC(I)= PARM(5) *
1 EXP(-0.5*((XUSE(I)-PARM(1))/PARM(2))**2)
1 +PARM(3) + PARM(4)*XUSE(I)
F(I)=YCALC(I)-YUSE(I)
C***** F WILL BE MINIMISED BY the FITFUN LIBRARY by varying PARM(1-5)
10 CONTINUE
C
C
RETURN
END

subroutine myread(in,xx,yy,yr,ntext)
c****** routine to read from a simple GSAS data file
c xx out first column value
c yy out second column value
c yr out third column value
c in out number of lines read
c inmax in maximum lines expected
c R. Ghosh, Ill, October 2004
parameter (inmax=1600)
real xx(inmax),yy(inmax),yr(inmax)
common/infile/fname
character*100 fname
c***** the filename to be read has a maximum length of 100 characters
character ntext*(*)
write(6,1)
1 format(' Give input filename : ',$)
read(5,2) fname
2 format(a)
open(unit=2,file=fname)
c***** read title
read(2,5) ntext
5 format(a)
read(2,6)
read(2,6)
c***** skip 2 lines
6 format(1x)
do i=1,inmax,5
read(2,*,end=20) (yy(n),yr(n),n=i,i+4)
j=i
end do
20 continue
close(unit=2)
do i=1,j
xx(i)=i*0.1-2.
end do
c***** not required further - close input
write(6,3) j
3 format(i3,' lines have been read in')
in=j
return
end


We can add another few lines to the makefile
ftest.exe:  ftest.f myread.o gauss.o
g77 -o ftest ftest.f myread.o gauss.o libffn66m.a libpggw520.a \
-wl,subsystem,console -mwindows
myread.o: myread.f
g77 -c myread.f
gauss.0: gauss.f
g77 -c gauss.f

and then use the command gmake ftest.exe
then test it after reading in the data file S100.gsa

To top

Really fitting data

A more complicated case allows one to fit up to four
peaks using different model functions but sharing the read-in routine

ff4.exe:  ff4.f calskp.f calskpx.f
g77 -o ff4 ff4.f myread.o calskp.f calskpx.f libffn66m.a libpggw520.a \
-wl,subsystem,console -mwindows

To top

Download examples

These programs test data and libraries have been collated in a 
zip file together
with a C version of the PGPLOT library and its header file cpgplot.h.

To top