! based on ! small module to do text mode graphics using ANSI terminal escape sequences ! Copyright (c) 2013 Axel Kohlmeyer <akohlmey@gmail.com> ! v0.1 2013-06-22, initial public version ! v0.2 2013-06-24, better autoscale and overflow protection module M_matrix__text_viz implicit none private public :: viz_init, viz_pos, viz_plot, viz_done character, parameter :: esc = achar(27) character(len=*), parameter :: cli = esc//'[' integer, parameter :: maxplot = 10 character, parameter :: plot(0:maxplot) = [' ', '.', ',', ':', '=', '+', 'o', 'x', 'X', '#', '@'] integer :: rows, cols character(len=*), parameter :: gen = '(*(g0))' contains subroutine viz_put(string) character(len=*),intent(in) :: string write(*,fmt=gen,advance='no')string end subroutine viz_put subroutine viz_init(x,y) ! initialize package and set size of plot area integer, intent(in):: x,y cols = x rows = y call viz_put(cli//'?25l') ! hide the cursor to reduce flicker !call viz_put(cli//'2J') ! clear the screen end subroutine viz_init subroutine viz_done ! restore settings to something sane. ! place cursor in last line CALL viz_pos(1,rows) ! set forground color to principal color ! re-enable the cursor ! and call for a reset call viz_put(cli//'30m'//cli//'?25h'//cli//'0m') write(*,*) end subroutine viz_done subroutine add_code(code,c,n) character(len=1),intent(inout) :: code(*) character(len=1),intent(in) :: c integer,intent(inout) :: n n = n+1 code(n) = c end subroutine add_code subroutine viz_pos(x,y) ! position cursor at a given location within screen. ! top left corner is (1,1) integer, intent(in) :: x,y integer :: i,n character(len=1) :: code(7) n = 0 i = y if (i < 1) i = 1 if (i > rows) i = rows call add_code(code,'[',n) if (i > 9) call add_code(code,achar(48+i/10),n) call add_code(code,achar(48+mod(i,10)),n) call add_code(code,';',n) i = x if (i < 1) i = 1 if (i > cols) i = cols if (i > 9) call add_code(code,achar(48+i/10),n) call add_code(code,achar(48+mod(i,10)),n) call add_code(code,'H',n) write(*,fmt=gen,advance='no')esc,code(1:n) end subroutine viz_pos subroutine viz_plot(val,nx,ny,max) real, intent(in) :: val(:,:) integer, intent(in) :: nx,ny real, intent(in),optional :: max integer :: i, j, k, l, m, n, dx, dy real :: vmax, scalef, tmp ! set blocksize for averaging dx = nx / cols if (dx < 1) dx = 1 dy = ny / rows if (dy < 1) dy = 1 ! set or determine scaling factor for data points vmax=1.0e-30 if (present(max)) then vmax = abs(max) else ! find absolute maximum value for scaling do j=1,rows do i=1,cols ! average over cells tmp = 0.0 n = 0 do k=(j-1)*dy+1,j*dy do l=(i-1)*dx+1,i*dx tmp = tmp + val(l,k) n = n + 1 enddo enddo tmp = ABS(tmp)/REAL(n) if (vmax < tmp) vmax = tmp enddo enddo endif scalef = real(maxplot)/vmax ! now plot do j=1,rows call viz_pos(1,j) do i=1,cols ! average over cells tmp = 0.0 n = 0 do k=(j-1)*dy+1,j*dy do l=(i-1)*dx+1,i*dx tmp = tmp + val(l,k) n = n + 1 enddo enddo ! convert absolute value into character m = int(scalef*abs(tmp)/real(n)+0.5) if (m > maxplot) m = 10 if (tmp < 0.0) then if (m > 5) then call viz_put(cli//'36m'//plot(m)) else call viz_put(cli//'34m'//plot(m)) endif else if (m > 5) then call viz_put(cli//'31m'//plot(m)) else call viz_put(cli//'30m'//plot(m)) endif endif enddo call viz_put(cli//'30m|') enddo call viz_pos(1,rows) call viz_put(cli//'30m') DO i=1,cols+1 call viz_put('-') enddo end subroutine viz_plot end module M_matrix__text_viz program demo_user use M_matrix use M_matrix__text_viz implicit none integer, parameter :: nx = 200, ny = 200 real :: val(nx,ny) integer :: i,j,k integer :: ierr character(len=1) :: paws call set_usersub(lala_text_viz) ! set user routine ! create a dataset in the program to pass to LALA() do k=1,2000 do j=1,ny ! fill array with data do i=1,nx val(i,j) = sin(real(i)*real(k)*0.0001)*sin(real(j)*0.033) enddo enddo call put_into_lala('val',val,ierr) call lala("user(val,24,80);") ! display using user routine !read(*,'(a)')paws enddo write(*,*)'user added routine does normalized pixelized text plot' write(*,*)'optional parameters give character cell dimensiones' write(*,*)'the default is the size of the array' call lala() ! enter interactive mode contains subroutine lala_text_viz(a,m,n,s,t) ! sample usersub_placeholder routine implicit none integer :: m,n doubleprecision :: a(:) doubleprecision :: s,t integer :: display_cols,display_rows display_rows=nint(s) display_cols=nint(t) if(display_cols.eq.0)display_cols=m if(display_rows.eq.0)display_rows=n call viz_init(display_cols,display_rows) ! initialize package and set size of plot area call viz_plot(reshape(real(a),[m,n]),m,n) call viz_done end subroutine lala_text_viz end program demo_user