
forums.silverfrost.com Welcome to the Silverfrost forums

View previous topic :: View next topic 
Author 
Message 
DanRRight
Joined: 10 Mar 2008 Posts: 1547 Location: South Pole, Antarctica

Posted: Fri Oct 06, 2017 4:05 pm Post subject: 


Based on how much source text takes to plot similar graphs in Matlab or even older Simpleplot PL, i'd say that the glorious times of hacking returned back to this forum . Before this was with broken Simpleplot PL, now it's native PL.
After trying everything we still could not fix the LOG_LOG with older Simpleplot PL, it worked only if X values do not exceed 1. And it had no X_min, Y_min, or framed plotting, and was buggy, crashing at Y values > 1e22, crashing debugger, not working with 64bit etc.
But like Matlab, older Simpleplot PL had no big problems with the correct LOG tics or labels. And, like in Matlab, the whole source code for the similar plots like above take only one single source text line. If it would take more no one would use them. With Matlab even 3D plot is done with one line, clearly people at Matlab know human psychology very well.
Here is what older Simpleplot PL produced (though crashing inside with LOG_LOG and turning to LINEAR_LOG plotting instead) with just onetwo lines of Fortran code if plotting data already exist and all the fonts were preliminary set up. No minimum/maximum beautifications were necessary, let alone using Y_min for the native PL fixing. This is one single 132 character Fortran line!
Code:  i=winio@('%pl[title="STANDARD CHARACTERISTICS",colour=red,colour=green,X_ARRAY,N_GRAPHS=3,SCALE=LOG_LOG]%es',640,480,5,X,Y1,Y2,Y3) 
The whole source code with setting data and fonts is here, SLINK its obj file with SIMPLE.DLL
Code:  real*8, dimension (5) :: X = (/1., 20., 60., 200., 600./)
real*8, dimension (5) :: Y1 = (/2.9e4, 300., 3., 0.2, 0.0022/)
real*8, dimension (5) :: Y2 = (/2.5e4, 500., 2., 0.4, 0.042/)
real*8, dimension (5) :: Y3 = (/2.2e4, 722., 2., 0.5, 0.072/)
CALL DIAGLV (0)
CALL TEXTMN(0.4) ! setting font size
CALL AXLBJS('*C','C') ! centering tic labels
call thckmg('LINE',4.) ! setting line width
call chset(11) ! setting fonts
!... Case of two lines of Fortran source code
i=winio@('%ww%pv%pl[title="STANDARD IEC IDMT CHARACTERISTICS", x_axis="Multiple of setting current",y_axis="Relay operating time&
& [s]", colour=red, colour=blue, colour=green, X_ARRAY, N_GRAPHS=3, SCALE=LOG_LOG]%es', 640, 480, 5, X, Y1, Y2, Y3)
End 
Times actually are coming that even one single line will be way too much. People take their data to cell phone graphics plotting utility which costs $1 or is even free, set there all the MINs and MAXs if needed, and all analysis is done without programming at all. Look at BridPlot for example, the grandgrandson of Simpleplot. 

Back to top 


Kenneth_Smith
Joined: 18 May 2012 Posts: 126 Location: Glasgow, Scotland.

Posted: Sat Oct 07, 2017 10:51 am Post subject: 


Dan's data combined with Friday's "hack" and I can replicate the performance of the old simple plot with the native %pl.
And it works for log_log scales.


Back to top 


Kenneth_Smith
Joined: 18 May 2012 Posts: 126 Location: Glasgow, Scotland.

Posted: Sat Oct 07, 2017 2:46 pm Post subject: 


I was going to add grid lines to my log_log plots but unfortunately get_plot_point@ does not work with log scales as this example demonstrates.
Code:  module test
implicit none
integer, parameter, private :: dp = SELECTED_REAL_KIND(15,307)
real(kind=dp) :: x(1:5) = (/0.1d0,1.d0,10.d0,100.d0,1000.d0/)
real(kind=dp) :: y(1:5) = (/0.1d0,1.d0,10.d0,100.d0,1000.d0/)
contains
integer function plot()
include<windows.ins>
integer i
i = winio@('%mn[Exit]&','exit')
i = winio@('%fn[Tahoma]&')
i = winio@('%ts&', 1.5d0)
call winop@('%pl[native,x_array,N_GRAPHS=1]')
call winop@('%pl[scale=log_log]')
call winop@('%pl[y_min=0.1,y_max=1000,x_min=0.1,x_max=1000]')
call winop@('%pl[link=curves, colour=blue, symbol=11, pen_style=0]')
i = winio@('%`bg[white]&')
i = winio@('%^pl',800,600,5,x,y,call_back)
plot=1
end function plot
integer function call_back()
include<windows.ins>
real(kind=dp) xx, yy
integer i
do i = 1, 5
call get_plot_point@(x(i), y(i), xx, yy)
call draw_ellipse@(nint(xx),nint(yy),6,6,rgb@(0,0,0))
write(6,*) x(i), y(i), nint(xx), nint(yy)
end do
call_back = 1
end function call_back
end module test
program main
use test
integer i
i = plot()
end program main 


Back to top 


DanRRight
Joined: 10 Mar 2008 Posts: 1547 Location: South Pole, Antarctica

Posted: Sat Oct 07, 2017 5:19 pm Post subject: 


As everyone can see from comparison, even after the tricks and beautifications, even though the curves in native PL look better then in older PL, the unreasonable frame numbering, wrongly placed tic marks and other errors making the whole plot far from production quality.
Without the tricks (of setting X and Y axis min and max at exact orders of magnitude as Ken have done above) and beautifications (bullets, frames, font and lines sizes), here is what novice user will see for the first time in native PL as a default image when he will visualize with LOG_LINEAR and LOG_LOG the data above (even using more lines of Fortran code). For everyone raised on shiny covers of journals and flashy websites the cultural shock is guaranteed:
Code:  use clrwin
real*8 :: X (5) = (/1., 20., 60., 200., 600./)
real*8 :: Y1(5) = (/2.9e4, 300., 3., 0.2, 0.0022/)
real*8 :: Y2(5) = (/2.5e4, 500., 2., 0.4, 0.042/)
real*8 :: Y3(5) = (/2.2e4, 722., 2., 0.5, 0.072/)
i=winio@('%pl[title="STANDARD IEC IDMT CHARACTERISTICS", x_axis="Multiple of setting current",y_axis="Relay operating time&
& [s]", colour=red, colour=blue, colour=green, X_ARRAY, N_GRAPHS=3, SCALE=LOG_LOG]%es', 720, 480, 5, X, Y1, Y2, Y3)
End 
Just in case, the compilation: ftn95 NativePL.f95 /link /64 

Back to top 


Kenneth_Smith
Joined: 18 May 2012 Posts: 126 Location: Glasgow, Scotland.

Posted: Sun Oct 08, 2017 11:46 am Post subject: 


I do agree with you Dan, my perseverance and enthusiasm with native the %pl is beginning to falter somewhat. I have hoped to be able to generate a plot similar to the one below with grid lines, but it's not that straightforward. Even if I can decode the coordinates returned by get_plot_point@ with log graphs, there is an added complication of user selected margins to consider, which takes me back to the struggles I have with my own %gr based plotting routines.
Guess we all just have to wait on Paul and his colleagues having the time to look at these issues. A quick fix for get_plot_point@ with log scales would be a step in the right direction as I can live with having to select appropriate ranges for scales. 

Back to top 


JohnSilver
Joined: 30 Jul 2013 Posts: 558

Posted: Wed Oct 11, 2017 11:31 pm Post subject: 


See my post on p.7 ... Wed 27 sept 2017  in particular my 'ex 3f' plots.
I saw the same 'effect' as in Dan's plot above of where the xaxis disappears after a certain value !!!! (just tick marks plotted !!!
In addition as you'll see ์t became more gobbledygook after resizing.
I'd put it down to being when loglog scales are set which are bigger than the range of data to plot but since Ken's latest plots seem not to to exhibit this effect maybe it's more complicated than that.
Ken, your comment about get_plot_point@ not working properly has thrown me as I definitely need to use that !
I hadn't made the time to follow up on the์at yet but I will now.
I'll look at your code. 

Back to top 


JohnSilver
Joined: 30 Jul 2013 Posts: 558

Posted: Thu Oct 12, 2017 2:13 am Post subject: 


again this is good detective work on your part Ken (Holmes )
Ah I see, only the first 2 'ellipses' (circles) appear on the plot and the first one is not in the correct position either.
After a quick look, the problem must be related to the original 'concept' for input data.
You remember originally the user had to input the LOG of the input data !?
So, in the case of your plot here , if the range has values <1 (10^0), which is in fact the reference point for loglog plots, then those values will have NEGATIVE values for the log.
I'm not sure where the 'origin' for the plot area is  bottom left of plot frame ? or the global %pl window (top left of plot frame)? I think it's actually towards bottom left, whether it's exactly at intersection of axes there I don't know  only Paul knows for sure.
Whatever ... it seems only the Y point coords are incorrect in SIGN If you like becasue the first segment of the scales goes <1 then the 'sign' of the spacing is negative and when it's added to the lowest value it goes even more negative !
Then there's the question of why xscale pixel spacing appears to be 135*10between successive pixel values output.
I think this shuld be a simple one to fix.
I suspect it's also the cause of other problems seen with log scales too
Having said all that (albeit not very clearly) it's a mystery how the plot itself comes out as it should ! I'd have thought that the get_plot_point should use the same algorithm as ffor the curve plotting ! Maybe it's just something that was corrected previously for the curve plotting which wasn't for the get_plot_point algorithm ?
In any case this must be classed as a bug . 

Back to top 


PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 4919 Location: Salford, UK

Posted: Thu Oct 12, 2017 7:03 am Post subject: 


I don't know if it is a bug or if, like a number of these plots, it is a matter of choosing nice values for y_min, y_max, dx and dy. If and when I am able to do more work on this we will need to start off with some simple plots that illustrate the problems. But please don't post them now.
In the mean time one or two fixes have been made and...
a) the limit on number of plots (previously 10) has been removed. At the same time, an option [stacked] has been added which means that the y (and x) data for different plots is concatenated in order to avoid multiple winio@ arguments. The concatenation is equivalent to using a two dimensional array for the data but this 2D array can be "ragged".
b) an option [gridlines] has been added with the expected result. 

Back to top 


Kenneth_Smith
Joined: 18 May 2012 Posts: 126 Location: Glasgow, Scotland.

Posted: Thu Oct 12, 2017 12:40 pm Post subject: 


Paul,
The option external_ticks works well, but unfortunately it does not address the issue of cases where the data to be plotted obscures the scale numbers on the axis as shown bottom right below, perhaps you might consider an 'external_scales' option at some time in the future.
Apologies for raising this again, my intention is to provide positive suggestions which all users will benefit from rather than negative feedback.
The news that you have implemented grid lines is a big step forward. I look forward to being able to use that option. 

Back to top 


Kenneth_Smith
Joined: 18 May 2012 Posts: 126 Location: Glasgow, Scotland.

Posted: Thu Oct 12, 2017 1:05 pm Post subject: 


As for the issue with get_plot_point@ with loglog scales, I don't think this is related to the selection of y_min, y_max etc. I have experimented with lots of variations on this. My impression is that somewhere within %pl there is a coordinate transformation that is the root cause of all the problems we are collectively complaining about. 

Back to top 


PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 4919 Location: Salford, UK

Posted: Thu Oct 12, 2017 2:04 pm Post subject: 


Thanks Ken. I hope to come back to this thread when things are a little quieter. 

Back to top 


Kenneth_Smith
Joined: 18 May 2012 Posts: 126 Location: Glasgow, Scotland.

Posted: Thu Oct 12, 2017 3:51 pm Post subject: 


John,
My quick and dirty fix for get_plot_point@ for log_log scales with logs using base 10.
Code:  module test
implicit none
integer, parameter, private :: dp = SELECTED_REAL_KIND(15,307)
integer, parameter, private :: npts = 5
real(kind=dp) :: x(1:npts) = (/0.1d0,1.d0,10.d0,100.d0,1000.d0/)
real(kind=dp) :: y(1:npts) = (/0.1d0,1.d0,10.d0,100.d0,1000.d0/)
integer margin, gw, gh !############
real(kind=dp) x_min, y_min, x_max, y_max !############
contains
integer function plot()
include<windows.ins>
integer i
i = winio@('%mn[Exit]&','exit')
i = winio@('%fn[Tahoma]&')
i = winio@('%ts&', 1.5d0)
call winop@('%pl[framed,etched]')
call winop@('%pl[x_array,N_GRAPHS=1]')
call winop@('%pl[margin=80]') !#########
margin = 80 !#########
call winop@('%pl[scale=log_log]')
call winop@('%pl[y_min=0.1,y_max=1000,x_min=0.1,x_max=1000]')
y_min = 0.1d0 !##########
y_max = 1000.d0 !##########
x_min = 0.1d0 !##########
x_max = 1000.d0 !##########
call winop@('%pl[link=lines, colour=blue, symbol=11, pen_style=0]')
i = winio@('%`bg[white]&')
gw = 800 !##########
gh = 600 !##########
i = winio@('%^pl',gw,gh,npts,x,y,call_back) !##########
plot=1
end function plot
integer function call_back()
include<windows.ins>
real(kind=dp) xx, yy
integer i
do i = 1, npts
call get_plot_point_k(x(i), y(i), xx, yy)
call draw_ellipse@(nint(xx),nint(yy),6,6,rgb@(0,0,0))
end do
call_back = 1
end function call_back
subroutine get_plot_point_k(x,y,xx,yy)
real(kind=dp), intent(in) :: x, y
real(kind=dp), intent(out) :: xx, yy
xx = log10(x) ; yy = log10(y)
xx = map_range(log10(x_min),log10(x_max),real(margin,kind=dp),real(gwmargin,kind=dp),xx)
yy = map_range(log10(y_min),log10(y_max),real(ghmargin,kind=dp),real(margin,kind=dp),yy)
end subroutine get_plot_point_k
real(kind=dp) function map_range(a1, a2, b1, b2, s)
real(kind=dp), intent(in) :: a1, a2, b1, b2, s
map_range = (s  a1) * (b2  b1) / (a2  a1) + b1
end function map_range
end module test
program main
use test
implicit none
integer i
i = plot()
end program main 


Back to top 


Kenneth_Smith
Joined: 18 May 2012 Posts: 126 Location: Glasgow, Scotland.

Posted: Thu Oct 12, 2017 3:55 pm Post subject: 


and the corresponding plot


Back to top 


JohnSilver
Joined: 30 Jul 2013 Posts: 558

Posted: Sat Oct 14, 2017 1:54 pm Post subject: 


Nice work again Ken.
I notice that apparently the margin can't be defined on the %pl statement parametrically, which is a shame.
Another (assuming I've not missed something) for Paul to add to his 'simple fix/mod' list maybe.
I've also taken the liberty to mod your code slightly to whow how it can work with multiple varying margins as introcuced with dlls6 onwards .....
[code:1:28c78c325d]! v1c  algorithm modified to cater for all margins defined
module test
implicit none
integer, parameter, private :: dp = SELECTED_REAL_KIND(15,307)
integer, parameter, private :: npts = 5
real(kind=dp) :: x(1:npts) = (/0.1d0,1.d0,10.d0,100.d0,1000.d0/)
real(kind=dp) :: y(1:npts) = (/0.1d0,1.d0,10.d0,100.d0,1000.d0/)
integer margin, gw, gh !############
integer mleft, mtop, mright, mbottom
integer margin_all(4)
real(kind=dp) x_min, y_min, x_max, y_max !############
contains
integer function plot()
include<windows.ins>
integer i
i = winio@('%mn[Exit]&','exit')
i = winio@('%fn[Tahoma]&')
i = winio@('%ts&', 1.5d0)
call winop@('%pl[framed,etched]')
call winop@('%pl[x_array,N_GRAPHS=1]')
! call winop@('%pl[margin=80]') !#########
! margin = 80 !#########
mleft=30 ; margin_all(1)=mleft
mtop =120 ; margin_all(2)=mtop
mright=60 ; margin_all(3)=mright
mbottom=90 ; margin_all(4)=mbottom
! call winop@('%pl[margin=(mleft,mtop,mright,mbottom)]') !#########
call winop@('%pl[margin=(30,120,60,90)]') !#########
margin = 80 !#########
call winop@('%pl[scale=log_log]')
call winop@('%pl[y_min=0.1,y_max=1000,x_min=0.1,x_max=1000]')
y_min = 0.1d0 !##########
y_max = 1000.d0 !##########
x_min = 0.1d0 !##########
x_max = 1000.d0 !##########
call winop@('%pl[link=lines, colour=blue, symbol=11, pen_style=0]')
i = winio@('%`bg[white]&')
gw = 800 !##########
gh = 600 !##########
i = winio@('%^pl',gw,gh,npts,x,y,call_back) !##########
plot=1
end function plot
integer function call_back()
include<windows.ins>
real(kind=dp) xx, yy
integer i
do i = 1, npts
call get_plot_point_k(x(i), y(i), xx, yy)
call draw_ellipse@(nint(xx),nint(yy),6,6,rgb@(0,0,0))
end do
call_back = 1
end function call_back
subroutine get_plot_point_k(x,y,xx,yy)
real(kind=dp), intent(in) :: x, y
real(kind=dp), intent(out) :: xx, yy
xx = log10(x) ; yy = log10(y)
! xx = map_range(log10(x_min),log10(x_max),real(margin,kind=dp),real(gwmargin,kind=dp),xx)
! yy = map_range(log10(y_min),log10(y_max),real(ghmargin,kind=dp),real(margin,kind=dp),yy)
xx = map_range(log10(x_min),log10(x_max),real(margin_all(1),kind=dp),real(gwmargin_all(3),kind=dp),xx)
yy = map_range(log10(y_min),log10(y_max),real(ghmargin_all(4),kind=dp),real(margin_all(2),kind=dp),yy)
end subroutine get_plot_point_k
real(kind=dp) function map_range(a1, a2, b1, b2, s)
real(kind=dp), inte 

Back to top 


JohnSilver
Joined: 30 Jul 2013 Posts: 558

Posted: Sat Oct 14, 2017 1:57 pm Post subject: 


damn that post limitation !!!
replace last 2 lines in my previous comment above with ....
Code: 
real(kind=dp) function map_range(a1, a2, b1, b2, s)
real(kind=dp), intent(in) :: a1, a2, b1, b2, s
map_range = (s  a1) * (b2  b1) / (a2  a1) + b1
end function map_range
end module test
program main
use test
implicit none
integer i
i = plot()
end program main 
Last edited by JohnSilver on Sat Oct 14, 2017 2:06 pm; edited 1 time in total 

Back to top 




You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum

Powered by phpBB © 2001, 2005 phpBB Group
