Python vs Modula-2

(1A) Reading data file

To (1)     Workbench Python に戻る

<Task>

The task is to read and display the data in file. This program is more complex but more useful than (1).

It reads text files of csv format, the first line of which is the header and has the information of the following data.

Suppose that the header has N items, and I-th item bagins with "i". Then the I-th item in any row below is integer, and otherwise real. The number of items of that row is the same as the number of items in the header.

For example datasheet1.csv (contents) has three real data, (time, conc, err) in each line. datasheet2.csv (contents) has integer i_number and real weight in each line.

<Python (Object Oriented Programming)>

[Module] fileRead.py

import numpy as np 

class readtest:
    
    def __init__(self,fname): 
        xa = []
        ya = []
        za = []
        maxitem = 3
        isf = np.arange(maxitem)
		
        def findTypes(res, n):
            for i in range(n):
                s = res[i].upper()
                isf[i] = (s[0] != 'I')
                if isf[i]==True:
                    print('float, ', end="")
                else:
                    print('integer, ', end="")
            print()
            return isf  # maybe redundant
  		
        file = open(fname, 'r') 
        line = file.readline()
        self.header = line

        l = len(line)
        line = line[:l-1]
        result = line.split(',')

        for x in reversed(result):  # remove ""
            if len(x)>0:
                break
            else:
                result.remove(x)
            
        n_item = len(result)
        isf = findTypes(result, n_item) 

        i = 0
        while (True):
            line = file.readline()
            l = len(line)
            line = line[:l-1]
            if len(line)==0: 
                print('Null line: end of file')
                break
            print(line)
            if ('END' in line.upper()):
                print('END found')
                break 

            result = line.split(',')
            if isf[0]:
                xa.append(float(result[0]))
            else:
                xa.append(int(result[0]))
            if n_item > 1:
                if isf[1]:
                    ya.append(float(result[1]))
                else:
                    ya.append(int(result[1]))
            if n_item > 2:
                if isf[2]:
                    za.append(float(result[2]))
                else:
                    za.append(int(result[2]))
               
            i += 1               
        file.close()

        self.fname = fname
        self.ndata = i
        self.nitem = n_item
		self.isfloat = isf
        self.xa = xa
        self.ya = ya
        self.za = za

    def datatypes(self):
        print('Data types: ', end="")
        for i in range(self.nitem):
            if self.isfloat[i]:
                print('float ',end="")
            else:
                print('integer ',end="")
        print()      
[Main] mytest.py
#f = readtest('datasheet1.csv')
f = readtest('datasheet2.csv')
nitem = f.nitem
print('x:',f.xa)
if nitem>1:
    print('y:',f.ya)
    if nitem>2:
        print('z:',f.za)
print('ndata:', f.ndata)
<Modula-2 (Structured Programming)>

IMPLEMENTATION MODULE fileRead.MOD

IMPORT FIO, Str;
FROM IO IMPORT WrStr, WrLn;

PROCEDURE readtest(fname: ARRAY OF CHAR;
	VAR ndata, nitem: INTEGER;
		 VAR isf: ARRAY OF BOOLEAN;
	       VAR x,y,z: ARRAY OF LONGREAL;
	    VAR ix,iy,iz: ARRAY OF INTEGER);

  PROCEDURE findTypes(s: ARRAY OF CHAR);
    VAR
      a: ARRAY[0..15] OF CHAR;
      i: INTEGER;
    BEGIN
      WrStr('findTypes'); WrLn;
      i:= 0;
      LOOP
        Str.Item(a, s, Str.CHARSET{','}, i);
	    IF Str.Length(a)=0 THEN EXIT END;
	    Str.Caps(a);
	    isf[i]:= (a[0]<>'I');
	    INC(i);
      END;	
      nitem:= i;
    END findTypes;

  VAR
    f : FIO.File;
    line, s: ARRAY[0..79] OF CHAR;
    nline,i: INTEGER;
    OK : BOOLEAN;
  BEGIN
    IF NOT FIO.Exists(fname) THEN 
	  WrStr('File not exist'); WrLn; RETURN END;
    f := FIO.Open(fname);
    nline := 0; ndata := 0;
    LOOP
      FIO.RdStr(f,line);
      WrStr(line); WrLn;
      IF Str.Length(line)=0 THEN 
	    WrStr('Null line found'); WrLn; EXIT END;
      INC(nline);
      IF nline=1 THEN
        Str.Copy(header,line);
        findTypes(header);
      ELSE
        Str.Caps(line);
        IF Str.Pos(line,'END')<Str.Length(line) THEN
          WrStr("'END' reached"); WrLn; EXIT;
     	END;
        FOR i:= 0 TO nitem-1 DO
          Str.Item(s, line, Str.CHARSET{','}, i);
          CASE i OF
       |0: IF isf[i] THEN x[ndata]:= Str.StrToReal(s,OK);
	       ELSE ix[ndata]:= Str.StrToInt(s,10,OK);
	       END;
       |1: IF isf[i] THEN y[ndata]:= Str.StrToReal(s,OK);
	       ELSE iy[ndata]:= Str.StrToInt(s,10,OK);
	       END;
       |2: IF isf[i] THEN z[ndata]:= Str.StrToReal(s,OK);
	       ELSE iz[ndata]:= Str.StrToInt(s,10,OK);
	       END;
          END;
        END;	
        INC(ndata);
      END;
    END;
    FIO.Close(f);
  END readtest;
  
PROCEDURE datatypes(isf: ARRAY OF BOOLEAN; n: INTEGER);
  VAR
    i: INTEGER;
  BEGIN
    WrStr('Data types: ');
	FOR i:= 0 TO n-1 DO
	  IF isf[i] THEN WrStr('float '); 
	  ELSE WrStr('integer '); END;
	END;
    WrLn;
  END datatypes;	

[Main] mytest.MOD

IMPORT fileRead;
FROM IO IMPORT WrStr, WrLn, WrLngReal, WrInt;
  
CONST
  N_item = 3;
  N_data = 1000;

VAR
  header: ARRAY [0..79] OF CHAR;
  isf: ARRAY [0..N_item-1] OF BOOLEAN;
  ndata, nitem: INTEGER;
  x,y,z: ARRAY[0..N_data-1] OF LONGREAL;
  ix,iy,iz: ARRAY[0..N_data-1] OF INTEGER;

BEGIN  
  fileRead.readtest('datasheet1.csv',
    ndata, nitem, isf, x,y,z, ix,iy,iz);
  WrStr('nitem='); WrInt(nitem,1); WrLn;
  WrStr('ndata='); WrInt(ndata,1); WrLn;
  FOR i:=0 TO ndata-1 DO
    j:=0;
    IF isf[j] THEN WrLngReal(x[i],5,10);
    ELSE WrInt(ix[i],2);
    END;
    WrStr(', ');
    IF nitem>1 THEN
      j:=1;
      IF isf[j] THEN WrLngReal(y[i],5,10);
      ELSE WrInt(iy[i],2);
      END;
      WrStr(', ');
      IF nitem>2 THEN
        j:=2;
        IF isf[j] THEN WrLngReal(z[i],5,10);
        ELSE WrInt(iz[i],2);
        END;
      END;
    END;
    WrLn;
  END;

9-19-2023, 11-11-2022, S. Hayashi