#! /usr/bin/gawk -f # Last edited on 2021-08-27 23:01:38 by stolfi BEGIN { # Reads an isolated run, prints the range and avg of each electrode within the fixation and stimulus phases. abort = -1; # Temporary: ne = -1; # Number of electrodes. nc = -1; # Number of channels. nt = -1; # Total number of frames in dataset. split("", chan); # {chan[ic]} is the name of channel {ic} (from 1). */ # The phase index {ip} ranges in {1..np} split("", icmk); # {icmk[ip]} is the marker channel's index (from 1) for phase {ip}. split("", phname); # {phname[ip]} is the name of phase {ip}. # Specific for Gislain's 128 electrode dataset: np = 2; # Number of phases. phname[1] = "FX"; # Fixation. phname[2] = "ST"; # Stimulus. split("", ns_p); # {ns_p[ip]} is number of times phase {ip} was seen. split("", nt_p); # {nt_p[ip]} is number of frames in phase {ip}. split("", it_ini_p); # {it_ini_p[ip]} is the index (from 0) of the first frame of phase {ip}. split("", it_fin_p); # {it_fin_p[ip]} is the index (from 0) of the last frame of phase {ip}. split("", vmin_pe); # {vmin_pe[ip,ie]} is min value of electrode {ie} (from 1) during phase {ip} (1 or 2). split("", vmax_pe); # {vmax_pe[ip,ie]} is max value of electrode {ie} (from 1) during phase {ip} (1 or 2). split("", vsum_pe); # {vsum_pe[ip,ie]} is total value of electrode {ie} (from 1) during phase {ip} (1 or 2) split("", up); # {up[ip]} tells whether the marker for phase {ip} was positive (1) or zero (0) in last frame. for (ip = 1; ip <= np; ip++) { ns_p[ip] = 0; nt_p[ip] = 0; it_ini_p[ip] = +9999999; it_fin_p[ip] = +9999999; up[ip] = 0; for (ie = 1; ie <= ne; ie++) { vmin_pe[ip,ie] = +9999999; vmax_pe[ip,ie] = -9999999; vsum_pe[ip,ie] = 0; } } nframes = 0; # Number of data frames seen. } (abort >= 0) { exit(abort); } # Ignore comments and blank lines: // { gsub(/[#].*$/, "", $0); } /^ *$/ { next; } # Parse {nc,nt,} from header: /^ *nt *[=] */ { nt = $3 + 0; next; } /^ *nc *[=] */ { nc = $3 + 0; next; } # Parse {chan} from header: /^ *channels *[=] */ { if (nc < 0) { prog_error("did not find {nc} in header"); } if (NF != nc + 2) { prog_error("wrong num of channel names in header"); } for (ic = 1; ic <= nc; ic++) { chan[ic] = $(ic + 2); } next } # Parse {ne} from header, define {icmk[1..np],phname[1..np]}: /^ *ne *[=] */ { if (nc < 0) { prog_error("did not find {nc} in header"); } ne = $3 + 0; if ((ne < 1) || (ne+np > nc)) { prog_error("invalid {ne} in header"); } printf "nc = %d ne = %d nt = %d", nc, ne, nt > "/dev/stderr"; # Specific for Gislain's 128 electrode dataset: icmk[1] = nc-1; # Fixation. icmk[2] = nc; # Stimulus. for (ip = 1; ip <= np; ip++) { if (chan[icmk[ip]] != phname[ip]) { prog_error("marker channel name mismatch in header"); } } next; } # Ignore other header lines: /^ *[a-zA-Z#]/ { next; } # Process data lines: /^ *[-+0-9]/ { if (NF != nc) { data_error(("invalid line format")); } it = nframes; # Index of current frame (from 0). prev_ip = -1; # Last phase active in this frame, or -1 if none. for (ip = 1; ip <= np; ip++) { vmk = 0 + $(icmk[ip]); # Value of marker channel for phase {ip}. if (vmk > 0) { # Frame belongs to phase {ip}: nt_p[ip]++; # One more frame in phase. if (up[ip] == 0) { # Start of phase {ip}. if (ns_p[ip] > 0) { data_error(("phase " ip " occurs more than once in run")); } it_ini_p[ip] = it; ns_p[ip]++; } it_fin_p[ip] = it; for (ie = 1; ie <= ne; ie++) { ve = 0 + $(ie); # Value of electrode {ie}. if (ve < vmin_pe[ip,ie]) { vmin_pe[ip,ie] = ve; } if (ve > vmax_pe[ip,ie]) { vmax_pe[ip,ie] = ve; } vsum_pe[ip,ie] += ve; } up[ip] = 1; if (prev_ip > 0) { data_error(("phases " prev_ip " and " ip " both on")); } prev_ip = ip; } } nframes ++; next; } // { data_error(("invalid line format")); } END { if (abort >= 0) { exit(abort); } printf "%d frames read\n", nframes > "/dev/stderr"; for (ip = 1; ip <= np; ip++) { printf "phase %s :", phname[ip]; if (ns_p[ip] == 0) { data_error(("phase " ip " does not occur in run")); } printf " spans %d frames %6d .. %6d", nt_p[ip], it_ini_p[ip], it_fin_p[ip]; printf "\n"; } for (ie = 1; ie <= ne; ie++) { printf "electrode %3d :", ie; for (ip = 1; ip <= np; ip++) { printf " %s ", phname[ip]; printf " range %+9.2f _ %+9.2f ", vmin_pe[ip,ie], vmax_pe[ip,ie] printf " del %9.2f ", vmax_pe[ip,ie] - vmin_pe[ip,ie] ;; printf " avg %+9.2f", vsum_pe[ip,ie]/nt_p[ip]; } printf "\n"; } } function arg_error(msg) { printf "** %s\n", msg > "/dev/stderr"; abort = 1; exit(1); } function prog_error(msg) { printf "%s:%d: ** prog error: %s\n", FILENAME, FNR, msg > "/dev/stderr"; abort = 1; exit(1); } function data_error(msg) { printf " «%s»\n", $0 > "/dev/stderr"; printf "%s:%d: ** %s\n", FILENAME, FNR, msg > "/dev/stderr"; abort = 1; exit(1); }