Silverfrost Forums

Welcome to our forums

Is it possible to get data points from a graph?

31 Jul 2009 4:48 #4848

Im am plotting data using the simpleplot facilities of Clearwin+ and I want to mark two points in a curve with a mouse click on the graph, take the data points between these limits and perform the fit of the data in the range marked in the plot. I have checked some subroutines of simpleplot but I do not find how to do this. Have anyone tried to pick up data points from a graph made using clearwin?

Thanks in advance!

Agustin

1 Aug 2009 6:57 #4853

Here is a sample program that uses full_mouse_input...

      options(implicit_none)
      winapp
c-----------------------------------------------------------------
      include <clearwin.ins>
      include 'gr6.ins'
      integer i
      external gr_func

      cstat=' '
      mstat=0

      i=winio@('%ww[no_border]&')
      i=winio@('%ca[LINE SELECTION]&')
      i=winio@('%mn[E&xit]&','EXIT')
      i=winio@('%ob&')
      i=winio@('%^gr[black,line_selection,full_mouse_input]&',
     +         300,300,gr_func)
      i=winio@('%cb%ob[status]%20st%cb',cstat)
      end
c-----------------------------------------------------------
      integer function gr_func()
      include <windows.ins>
      include 'gr6.ins'
      integer x1,y1,x2,y2,nstat

      call get_mouse_info@(x1,y1,nstat)
      write(cstat(1:30),'(3I7)') x1,y1,nstat
      call window_update@(cstat)

      if(and(nstat,MK_LBUTTON).EQ.0.AND.and(mstat,MK_LBUTTON).NE.0)then
        call get_graphics_selected_area@(x1,y1,x2,y2)
        call set_graphics_selection@(0)
        call draw_line@(x1,y1,x2,y2,12)
        call set_graphics_selection@(2)
      endif
      mstat=nstat

      gr_func=1
      end

gr6.ins contains...

      integer mstat
      character*30 cstat
      common/control/ mstat,cstat
1 Aug 2009 6:06 #4855

Thank you Paul for your code, but it is not what I mean. I have no problems with mouse input, in fact with my program I can get windows coordinates with no problems. The point is how can I transform these 'pixel' or 'window' coordinates into 'data' coordinates. i.e. if I have a graph about Temperature and Presure, when I click with the mouse and get x=200 and y=300 (window pixels) I get T=315 and P = 0.5 as a result. Do you follow what I mean?

Agustin

1 Aug 2009 7:16 #4857

Sorry, I don't know how I missed your reference to SimplePlot.

Off hand I don't know how to work out the transformation but %gp may be useful; also clearwin_info@('SCREEN_WIDTH') and clearwin_info@('SCREEN_DEPTH').

There is also get_window_location@ used together with %lc.

1 Aug 2009 10:37 #4858

Paul, I don't think it registered with you that Agustin was using Simpleplot - I'm guessing that you read it that he was using “simple plot” routines! I read your first reply, and was amazed to imagine that the mouse worked the same in a Simpleplot window as a %gr window – and I guess that it doesn’t.

Agustin, In the documentation area of the Silverfrost website you will find a range of documents on Simpleplot. In some of them, mention is made of a routine GETXY for interaction using the mouse in a Simpleplot window. This is a Simpleplot (i.e. BUSS) routine not a Silverfrost one, as it doesn't end with @. One of the difficult things to discover is precisely what is present in the “bundled” version, and what extra facilities were in the full version. Whether or not GETXY is included in the bundled mini version of Simpleplot that is supplied with FTN95 I don't know. You should probably start by downloading all the Simpleplot documentation and read it all. You may find the answer there - although if the routine is available only in the full Simpleplot then you continue to have a problem.

In the Simpleplot documentation, it talks about placing Simpleplot graphics into a conventional %dw window. This is in the document 'Using Simpleplot with FTN95' in section 5.2.3. There is sample code there and a tutorial. I don't like %dw - it doesn't work properly with all the Silverfrost routines - so maybe it is worth trying with %gr instead. Then you can use the method Paul gave you for getting the mouse position.

When drawing any graphics, you always have to do a conversion from real world coordinates to pixels, both for scaling and for shifting the origin. To get back, reverse the process. Remember that the mouse position is given to 1 pixel accuracy, and this isn't very good (usually) in real world coordinates, so you may have to make an intelligent decision about what the real world equivalent should be and round (up or down) your mouse position accordingly. I keep the conversions in “statement functions”, so, for example,

       IPOSX(XX) = (XX - X_CENTRE)/SCREEN_SCALE_X + IXRES/2
       IPOSY(YY) = IYRES/2 - (YY-Y_CENTRE)/SCREEN_SCALE_Y

give me the pixel coordinates of a point with real life coordinates (XX,YY) in a window of size (IXRES , IYRES). The scales for X and Y are possibly different (hence SCREEN_SCALE_X and _Y) and these have to be worked out from the range of X and Y coordinates, and whether the aspect ratio is fixed or not. My statement functions centre my plottable object in the window, and take account of the fact that my Y coordinates increase upwards, although the screen y-coordinates increase downwards. (I forget about whether or not the coordinates start at 1 or 0 !)

Reversing things is a matter of getting the pixel coordinates, and then getting the real life coordinates. In one of my programs this is done with

       IXP = CLEARWIN_INFO@ ('GRAPHICS_MOUSE_X')
       IYP = CLEARWIN_INFO@ ('GRAPHICS_MOUSE_Y')
       RX = (IXP-ixres/2)*SCREEN_SCALE + X_CENTRE
       RY = Y_CENTRE - (IYP-iyres/2)*SCREEN_SCALE

As I understand Simpleplot, the actual graph is plotted in (say) 60% of the available window pixels, so you need to take that into account as well when back-calculating the real world coordinates.

You may find this rather easier if you program the graphing yourself (in a %gr region) rather than using Simpleplot! (or try using SIMDEM).

Regards Eddie

PS. It is always useful to download the FTN77 documentation as well. There are facilities still in FTN95 that come from the past, and which aren't always documented in FTN95.CHM.

E

4 Aug 2009 1:34 #4862

Thank you Ed for your comments. I will probably try your suggestion after finishing my tries with Simpleplot. I know the getxy subrooutine that should be used along with kxyxy to obtain the mouse position coordinates (getxy) and convert to user defined coordinates (kxyxy) but...it seems that, at least with clearwin windows such as %gr and %pl, does not work. I will give a look to %dw although you think it is not the best way to work with graphics windows. For your information, the Simpleplot library that comes with FTN95 is, as far as I know, complete, i.e. it is the same that BUSS used to provide to their users. I bougth Simpleplot long time ago (1993?) and the last version I got was 2.15, which is not very different from the last version BUSS produced after they closed. Although I have the full documentation of Simpleplot, the manuals were not the best ones for understanding how every subroutine worked. However, I think that graphics are done easier with Simpleplot than with FTN95 facilities. Am I wrong?

Agustin

4 Aug 2009 5:39 #4864

Agustin,

If you are just drawing a graph, then Simpleplot has to be easier than doing it yourself. However, if you want to interact with the graph, then in my view doing it yourself is best.

A quick fix might be to ask the user to input the values for redrawing the graph rather than picking them up with the mouse. Best of luck.

Eddie

4 Aug 2009 8:00 #4866

well, in fact I was thinking precisely about that, i.e. see the graph and input the upper and lower values that one like to fit (for instance). Thanks for your comments.

Agustin

5 Sep 2009 4:26 #4925

Quoted from PaulLaidler

  include <clearwin.ins>
  include 'gr6.ins'

Where is gr6.ins - compilation failed ?

5 Sep 2009 5:57 #4928

The include file is also listed in my post.

2 Oct 2009 10:32 #5111

Well, well, I eventually found how to get the x,y values of a point in a plot using Clearwin and Simpleplot! Just in case someone find it useful....

Agustin

module clearwin_sp !Contains definition of values to pass to DDDATA INTEGER SIMPLE_WINDOWS_SET_WINDOWNAME PARAMETER(SIMPLE_WINDOWS_SET_WINDOWNAME = 6) INTEGER SIMPLE_WINDOWS_SET_HDC_DIM PARAMETER(SIMPLE_WINDOWS_SET_HDC_DIM = 7) INTEGER SIMPLE_WINDOWS_END_LIST PARAMETER(SIMPLE_WINDOWS_END_LIST = 0) ! Useful definition of data structure to hold BitmapDC to pass to SIMPLEPLOT INTEGER*4 iBitmapDC, iWidth, iHeight contains subroutine ini_bitmap use mswin iWidth=GetSystemMetrics(SM_CXSCREEN)*0.75 iHeight=GetSystemMetrics(SM_CYSCREEN)0.75 ibitmapdc=GET_BITMAP_DC@(INTS(iWidth),INTS(iHeight)) end subroutine ini_bitmap ! ******************* SP_SupplyBitmap *********************** ! Set up a Static (SAVEd) parameter block consisting of an array of pairs of ! integers. Each pair of integers consists of a function number followed by an ! optional address of a data structure. ! The parameter block address is passed to SIMPLEPLOT by SUBROUTINE DDDATA. ! ! In this example: ! SIMPLE_WINDOWS_SET_HDC_DIM specifies that the next integer is the address ! of a data structure consisting of a Bitmap DC followed by its dimensions ! SIMPLE_WINDOWS_END_LIST is the mandatory end of list item which does not ! require the address of a structure SUBROUTINE SP_SupplyBitmap ! Pass Bitmap to SIMPLEPLOT INTEGER4 iParams(4) SAVE iParams iParams(1) = SIMPLE_WINDOWS_SET_HDC_DIM ! hDC + dimensions iParams(2) = LOC(iBitmapDC) ! Address of PARAMETER block iParams(3) = SIMPLE_WINDOWS_END_LIST! End of list CALL DDDATA(LOC(iParams(1)))! Notify SIMPLEPLOT CALL DEVNAM('WINDOW') ! Select Window CALL OWNNEW(.TRUE.) ! Inhibit 'Continue' button END subroutine sp_supplybitmap ! ********************* Update Window ********************** ! This subroutine is called whenever the bitmap is to be copied to the screen. ! Until this is called, none of the graphics produced by SIMPLEPLOT is visible SUBROUTINE UpdateWin CALL OUTBUF ! Flush buffers CALL WINDOW_UPDATE@(iBitmapDC) ! Copy Bitmap to window END subroutine updatewin end module clearwin_sp

program getxy use clearwin_sp LIBRARY 'C:\simple.dll' integer ans external get_xy call ini_bitmap call sp_supplybitmap ans=winio@('%ww%ca[My program GetXY]&') ans=winio@('%^dw&',ibitmapdc,get_xy) ans=winio@('%ff%cn%bt[OK]') end program getxy

integer function get_xy() use mswin use clearwin_sp real4,dimension(50) ::dat_x,dat_y real ::minx,maxx,miny,maxy character6 ::xt,yt integer f do i=1,50 dat_x(i)=i+20 dat_y(i)=i3+52 end do f=50 minx=MINVAL(dat_x) maxx=MAXVAL(dat_x) miny=MINVAL(dat_y) maxy=MAXVAL(dat_y) CALL INITSP call axsbtk('XC','I') call axsbtk('YC','I') call axlbjs('X','C') call textmg(1.5) CALL CHSET(0) call textmg(2.0) CALL SCALES(minx,maxx,1,miny,maxy,1) CALL NEWPIC CALL AXIS7('XC','x') CALL AXIS7('YC','y') call pen(2) CALL MARKCV(real(dat_x,1),real(dat_y,1),f,5,1) CALL TITLE7('O','C','Test of Get_XY') call updatewin ibutton=and(clearwin_info@('graphics_mouse_flags'),31) !click on the mouse right button to show the picture on screen
if(ibutton.ne.1) return !click on the left button to pick the points on the plot
ix=clearwin_info@('graphics_mouse_x') iy=iheight-clearwin_info@('graphics_mouse_y') call kxyxy(1,real(ix),real(iy),5,rx,ry) print
,rx,ry call markpt(rx,ry,5) CALL KREAL(RX,XT) CALL KREAL(RY,YT) xl=len(xt) yl=len(yt) total=xl+yl+1 call caplbm(rx,ry-4,15,xt//','//yt,total) call updatewin get_xy=1 end function get_xy

4 Oct 2009 9:35 #5117

Quoted from PaulLaidler The include file is also listed in my post.

Oops...

But why the code does not work if substutute 'include <clearwin.ins>' to 'use clrwin' (undefined variables)?

4 Oct 2009 11:50 #5119

You should set 'use mswin' and not 'use clrwin' as the module with the clearwin+ code is called mswin. Clearwin.ins was part of FTN77 (when modules did not exist) not FTN95 (or FTN90 in the very early days....).

Agustin

9 Oct 2009 3:05 #5152

Quoted from PaulLaidler Here is a sample program that uses full_mouse_input...

      options(implicit_none)
      winapp
c-----------------------------------------------------------------
      include <clearwin.ins>
      include 'gr6.ins'
      integer i
      external gr_func

      cstat=' '
      mstat=0

      i=winio@('%ww[no_border]&')
      i=winio@('%ca[LINE SELECTION]&')
      i=winio@('%mn[E&xit]&','EXIT')
      i=winio@('%ob&')
      i=winio@('%^gr[black,line_selection,full_mouse_input]&',
     +         300,300,gr_func)
.........................
.........................

How best way to get program react also on keyboard input when full_mouse_input is used?

9 Oct 2009 3:31 #5153

In the same window use %mg with WM_KEYDOWN and/or WM_SYSKEYDOWN.

Look these up in MSDN and find out what the wparam and lparam in the message are. Then in your callback for %mg, get the wparam and lparam from clearwin_info@('MESSAGE_WPARAM') etc.

9 Oct 2009 5:02 #5154

Well...that was not easy...it's like going to Microsoft Windows programmers dirty internal kitchen 😃))

I've tried to extend your example above but still failed, clearly i do not understand something. Is there any example of using %mg? Without code sample the %mg description in the help file looks unfortunately like highly encrypted message. Reading its description below i felt completely lost at the WM_NOTIFY and already at the next sentence got very bad feeling reading about set_mg_return_value@ 😦

Ideally would be to see simplest working code snippet of using keyboard with %gr[full_mouse_input] which, say, is reacting on key for letter A or number 5 or left arrow from Windows messages


winio@(‘%mg’, msg_no, cb_func) integer msg_no (input) external cb_func

This format provides direct access to specified Windows messages. It should be used with care since it is possible to interfere with other ClearWin+ processing.

msg_no is the message number of the message to be processed. User numbers should begin at WM_USER +1000. cb_func is the call-back function that is to be called when the message is received. The call-back function can use clearwin_info@ with the strings 'MESSAGE_HWND', 'MESSAGE_WPARAM', and 'MESSAGE_LPARAM' in order to get the standard arguments for a Windows call-back function.

When writing the %mg call-back function, use a return value of 3 if you want ClearWin+ to apply the default processing of the message msg_no. Other values have the usual effect (zero closes the window etc.) but cause the default processing to be bypassed. Occasionally the internal Windows dialog procedure that processes messages requires a particular return other than the default value which is zero (e.g. under certain conditions when using WM_NOTIFY). In this case you should make a call to the subroutine set_mg_return_value@ before returning. This subroutine takes one integer argument which is the value to be returned by the internal Windows dialog procedure.

9 Oct 2009 5:52 #5157

OK I will aim to put together some sample code when I get a minute.

10 Oct 2009 7:58 #5161

Here is a program that uses a %gr area and allows you to type into the status bar.

      winapp
c---------------------------------------------------------------
      include <windows.ins>
      integer i,gr_func,mg_func
      external gr_func,mg_func
      character*40 cstat
      common cstat
      cstat=' '
      i=winio@('%ww[no_border]&')
      i=winio@('%ca[Sample]&')
      i=winio@('%mn[E&xit]&','EXIT')
      i=winio@('%ob&')
      i=winio@('%mg&', WM_KEYDOWN, mg_func)
      i=winio@('%^gr[black,full_mouse_input]&',300,300,gr_func)
      i=winio@('%cb%ob[status]%20st%cb',cstat)
      end
c-----------------------------------------------------------
      integer function mg_func()
      include <windows.ins>
      integer wparam,i
      save i
      character*40 cstat
      common cstat
      wparam=clearwin_info@('MESSAGE_WPARAM')
      if(wparam==8 .and. i>0)then
        cstat(i:i)=' '
        i=i-1
        call window_update@(cstat)
      else if(wparam > 31 .and. wparam < 127)then
        if(and(GetKeyState(VK_SHIFT),Z'80') == 0)then
          wparam=wparam+ichar('a')-ichar('A')
        endif
        i=i+1
        cstat(i:i)=char(wparam)
        call window_update@(cstat)
      endif  
      mg_func=1
      end
c-----------------------------------------------------------
      integer function gr_func()
c     Process mouse keys here      
      gr_func=1
      end
c-----------------------------------------------------------
10 Oct 2009 8:06 #5163

Holly shmolly...thanks for the example, i'd crash before finding this solution. But we have to admit, the solution is kind of antiintuitive. I still do not understand how this line works

  i=winio@('%mg&amp;', WM_KEYDOWN, mg_func) 

And since all the warnings about %mg is also such specific callback content important? This is because as to the keys generated, the get_wkey@ or get_wkey1@ look more familiar for Salford/Silverfrost compiler users then wparam which not everywhere coincides with key and seems misses arrow keys. All in all is the code below without clearwin_info@ etc calls legitimate? Seems it works fine...

      winapp 
c--------------------------------------------------------------- 
      include <windows.ins> 
      integer  gr_func,mg_func 
      external gr_func,mg_func 
      character*40 cstat 
      common cstat 
      cstat=' ' 
      i=winio@('%ww[no_border]&') 
      i=winio@('%ca[Sample]&') 
      i=winio@('%mn[E&xit]&','EXIT') 
      i=winio@('%ob&') 
      i=winio@('%mg&', WM_KEYDOWN, mg_func) 
      i=winio@('%^gr[black,full_mouse_input]&',300,300,gr_func) 
      i=winio@('%cb%ob[status]%20st%cb',cstat) 
      end 
c----------------------------------------------------------- 
      integer function mg_func() 
      include <windows.ins> 
      integer wparam,i 
      character*40 cstat 
      common cstat 
      integer key, get_wkey@
      save i 
      data i/0/
      i=i+1

      key=get_wkey@()

      cstat(i:i)= char(key)
      call window_update@(cstat) 
      if(i > 39) i=0
      mg_func=1 
      end 
c----------------------------------------------------------- 
      integer function gr_func() 
c     Process mouse keys here      
      gr_func=1 
      end 
c-----------------------------------------------------------

Please don't forget to include your sample in the Examples and in the Help - allowing keyboard and full mouse simultaneously is important design feature.

11 Oct 2009 8:44 #5165

I am not sure that your code will always work but it is an interesting approach.

The difference is that get_wkey@ takes the value from a buffer whilst WM_KEYDOWN responds the the current key stroke. Maybe if you included a way to clear the buffer then the two would be equivalent and yours would be the simpler approach.

Please login to reply.