Announcement

Collapse
No announcement yet.

simple scatterplot

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Manuel Valdes
    replied
    Hi Mike,

    Good!. I'm also learning a lot from Dave's code. The number 38 doesn't have special meaning, except that it's 15000/400 rounded to the closest integer. The idea was to get the RND ranges closer and closer to 0, so as to concentrate the points around that value.

    Best regards,

    Leave a comment:


  • Mike Hounsome
    replied
    Dave: GW Plot is just about exactly what I was trying to achieve - thanks, I've learned a lot. I'll be able to incorporate those ideas into my main program.

    Manuel: Your program was too sophisticated for my simple needs for this particular job, but the ideas in it will be of great help to me when writing future programs. And I like your random data generator - most useful for testing. Is there any significance in the number 38?

    Thanks again, guys.

    Leave a comment:


  • Manuel Valdes
    replied
    Hi Dave

    Many thanks, now I have something good to study a fresh view of the subject. For starter I like the idea of the 0-0 axes, and I'm thinking whether to superimpose them using a different colour, or to start the grid lines from them going up and down, left and right.

    As I am a lousy typist, I use this small code to produce my testing data files, playing with the random algorithm to get some effects:

    Code:
     
    #COMPILE EXE
    '#DIM ALL
     
    FUNCTION PBMAIN () AS LONG
     OPEN "POINTS.CSV" FOR OUTPUT AS #1
     PRINT #1, "X-Value,Y-Value"
     IV1&=15000
     IV2&=38
     FOR I%=1 TO 400
      PRINT #1,RND(-IV1&,IV1&)/100;CHR$(44);RND(-IV2&,IV2&)/100
      IV1&=IV1&-38
      IV2&=IV2&+38
     NEXT
     CLOSE 1
    END FUNCTION
    Best regards,
    Last edited by Manuel Valdes; 20 Feb 2012, 05:31 PM.

    Leave a comment:


  • Dave Biggs
    replied
    Hi Manuel,

    Thanks for the 'bare-bones' version I shall be picking over it for more goodies!

    I've done a bit more with the CalculateStepSize function and incorporated it in this (final?) example.
    It seems to work quite well with the data files in the zip below.
    The sample data includes a modified version of your latest POINTS.CSV data. I removed the three special points and the function comes up with the same axes automagically!
    Attached Files

    Leave a comment:


  • Manuel Valdes
    replied
    Hi Dave, Hi Mike,

    Attached a simpler, bare-bones version, which I hope will respond in a better way to Mike's purposes.

    The "POINTS.CSV" file was created with 100 pairs of values, using the RND function, except that I included three special point to control the accuracy of the deployment (-100,-100; 0,0 and 100,100).

    I know this subject is in a way tricky, since I have been programming this type of stuff for the last 37 years.

    Best regards,
    Attached Files
    Last edited by Manuel Valdes; 20 Feb 2012, 05:29 AM.

    Leave a comment:


  • Dave Biggs
    replied
    Hi Mike,
    Hope your wife is coping OK?

    I haven't made as much progress on the scaling / axes algo stuff as I would have liked yet. (I'm afraid I really don't deserve Manuel's high esteem ).

    I did google my way to a site that discussed some possible solutions though and cobled together this test code. It shows some promise..
    Code:
    #COMPILE EXE
    #DIM ALL
     
    FUNCTION PBMAIN () AS LONG
     LOCAL xmin, xmax, xRange AS SINGLE
     LOCAL Steps AS LONG, StepSize AS SINGLE
      xmin = 1.4                  ' change to test
      xmax = 2.0                  '
      Steps = 10                 '
     
      xRange = xmax - xmin
      ? "xmin" xmin "xmax" xmax "xRange" xRange "Steps" Steps
      ' "Pretty step" algo
      CalculateStepSize(xRange, Steps) TO StepSize
      ?
      ? "StepSize" StepSize
      ' Adjust _min and _max
      xmin = StepSize * Int(xmin/StepSize)         ' -0.5 ?
      xmax = StepSize * ceil(xmax/StepSize)
      ? "Adjusted xmin" xmin "xmax" xmax
      ? "Actual steps " (xmax - xmin)/StepSize
     WAITKEY$
    END FUNCTION
    '------------------/PBMain
     
    FUNCTION CalculateStepSize(Range AS SINGLE, Steps AS LONG) AS SINGLE
     LOCAL tempstep AS SINGLE
     LOCAL mag, magPow AS SINGLE, magMsd AS LONG
     
    ReStart:
      ' calculate an initial guess at step size
      tempStep = range/Steps    : ? "tempstep" tempStep
      ' get the magnitude of the step size
      mag = FIX(LOG10(tempStep))  : ? "mag" mag
      magPow = 10^mag              : ? "magPow" magPow
      ' calculate most significant digit OF the NEW STEP SIZE
      magMsd = int((tempStep/magPow) + 0.5)  : ? "magMsd" magMsd
      ' promote the MSD TO either 1, 2, OR 5
        IF (magMsd > 5.0) THEN
          magMsd = 10.0
        ELSEIF (magMsd > 2.0) THEN
          magMsd = 5.0
        ELSEIF (magMsd > 1.0) THEN
          magMsd = 2.0
        END IF
      ? "magMsd*magPow" magMsd*magPow
       IF magMsd*magPow < 1 THEN Decr Steps : GOTO ReStart
     FUNCTION = magMsd*magPow
    END FUNCTION
    '------------------/CalculateStepSize
    Perhaps a version of this method of might suffice to configure the two axes?

    Give it a spin and see what you think.

    Leave a comment:


  • Manuel Valdes
    replied
    Hi Mike,

    I hope that my eagerness to help wasn't in a way impolite. I am very grateful of all that I can learn every day from this forum, and this is one of the very rare cases where I thought I had some experiences to share. Specially, since like you, I used to program in TB. Anyway to trump Dave is absolutely out of my capabilities, and he is very, very hi in my regards.

    The codes I posted can't deal with negative numbers, but that can be quite easily corrected. Please let me know if you have any other comment or question about it.

    Best regards,
    Last edited by Manuel Valdes; 17 Feb 2012, 08:35 PM.

    Leave a comment:


  • Mike Hounsome
    replied
    Dave, we've been somewhat trumped by Manuel's tour de force! As you say, there's lots there to learn from but for my initial purposes the simple plot that we (well, you) were working on was adequate. All that had to be done was to solve the scaling of the axes and making sure that it coped with whatever numbers (including negative ones) that were thrown at it. I guess that some of the methods used by Manuel could be transferred to the simple plot but I admit that I'm lost in his code - trying run before I can walk in PBCC. I'll persevere and keep looking at his code to see how he scales the axes. Thanks, both of you, for taking up the challenge.

    Leave a comment:


  • Manuel Valdes
    replied
    Scalable Single Channel Plotter

    This is an scalable parametric version of the code. Using the function keys F2 to F5, it's possible to change the width and height of the GW, along with the graphic itself.

    The testing file is now the US Consumer Price Index from Jan 1913 to Dec 2011 (the later is a forecast, since the official one will be available in a couple days)

    Regards,
    Attached Files

    Leave a comment:


  • Manuel Valdes
    replied
    Final Version

    Hi,

    Final version of Dual Channel Plotter. I hope it can contain some useful ideas for Mike's purposes. I'll appreciate any suggestion, criticism or comment.

    Regards,
    Attached Files
    Last edited by Manuel Valdes; 9 Feb 2012, 05:36 AM.

    Leave a comment:


  • Manuel Valdes
    replied
    Dual Channel

    Hi,

    This is a dual channel version. It works OK provided both channels display variables with the same name, and having values in the same order of magnitud. Next step is to add an option for independent names and scaling.

    Regards
    Attached Files

    Leave a comment:


  • Mike Hounsome
    replied
    Manuel, I've tried double-left click but it just downloads a PHP file. I use Firefox so I tried IE9 but with the same result. I'm also using a download accelerator, so I disabled it and it worked! Thanks.

    Leave a comment:


  • Manuel Valdes
    replied
    Hi Dave,

    It's good to learn that the program looks interesting to you. I never miss a post of yours, as I always have learned a lot from them. Sorry for my short nondescriptive variable names, a custom which came from my old TB and PBDOS days.

    Since I have a few days left from my vacations, I am right now adding to the program the capability to handle two variables simultaneously, which doesn't look so difficult.

    Best regards,
    Last edited by Manuel Valdes; 7 Feb 2012, 02:53 PM.

    Leave a comment:


  • Dave Biggs
    replied
    Downloaded OK for me using IE8 (have to be logged in to the site, not just visiting)

    Another fine example Manuel, you do good work!

    It'll take me a while to work through the source though - I'm renaming the variables as I go to help me to figure out what's being done where!

    I can see though that you are scaling the data values before plotting which defintely helps in drawing the axes and positioning other elements on the window, independent of the data values.

    I've been making life more difficult by the use of custom coordinates via GRAPHIC SCALE to enable direct plotting of the data without needing to scale the values.

    Something I want to investigate is the use of SET CLIP to protect the other information, labels titles etc from the effects of using GRAPHIC SCALE to set up the plotting area... First, though I must finish mining your work to see what I can pinch

    Thanks for sharing!

    Leave a comment:


  • Manuel Valdes
    replied
    Hi Mike,

    Just double Left (not right) click on the ZIP and select the 'Save' Option in the Pop Up Menu.

    Regards


    Later: In order to be able to download an attachment you must be logged in
    Last edited by Manuel Valdes; 7 Feb 2012, 08:19 AM.

    Leave a comment:


  • Mike Hounsome
    replied
    That's brilliant, Dave. I will take a day or two to go through your program learning, as I go, because my wife fell and broke her leg the other day and I'm needed to help her get around.

    Manuel: thanks for the link but when I try to download plotter.zip all I get is a PHP page. What am I doing wrong?

    Leave a comment:


  • Manuel Valdes
    replied
    Hi,

    In the attached ZIP file please find the source code of a simple, auto-scaling, static plotter, the compiled EXE, and a 540 points testing CSV file.
    Even though the testing file was made of sequential points, the program accepts scattered points, provided the highest 'y' value is in the last record of the file. Since the code includes just Basic commands, it compiles both in PBCC GW and PBWin.

    I think it can be easily modified to fit the intended use.

    Regards,
    Attached Files
    Last edited by Manuel Valdes; 7 Feb 2012, 06:24 AM. Reason: Fix some glitches in the program

    Leave a comment:


  • Dave Biggs
    replied
    Took that forward a little in the code below but it's not such a 'simple scatterplot' anymore

    Seems that the trick will be finding a method of analysing the data to deciding what start / stop / interval markers to use.

    I've tried to make a generic solution below and it kind of works with the three data sets listed at the end of the source. (Well ok that's not 'all conceivable data sets' but it's heading in that direction )

    PB's GRAPHIC SCALE statement makes plotting the data a breeze but actually drawing the axes, marks and labels consistently is a bit trickier.
    Use of the new GRAPHIC Functions like GRAPHIC(CANVAS.X) and GRAPHIC(CELL.SIZE.X) helps a lot there as they are scaled along with the window when a different data set is loaded.

    Code:
    'PBCC6 program
    #DIM ALL
     
    FUNCTION PBMAIN () AS LONG
     LOCAL hBmp, n, hFont1, hFont2, Clk AS LONG
     LOCAL r, x, y, xmax, ymax, xmin, ymin, xmark, ymark AS SINGLE
     LOCAL lm, tm, rm, bm AS SINGLE                           ' margins
     LOCAL slm, stm, srm, sbm AS SINGLE                       ' scaled margins
     LOCAL file, b, xaxis, yaxis, sKey AS STRING
     
      FONT NEW "Lucida Console", 10, 0, 0, 0, 0 TO hFont1     ' set up fonts to be used later
      FONT NEW "Lucida Console", 10, 0, 0, 0, 900 TO hFont2   ' rotated font (needs to be true type)
      CONSOLE SET LOC 1, 1
      CONSOLE SET SCREEN 20, 30
     
      file  = "ltest.dat"                                     ' see example data at end of source
      b     = "Title that is quite long in the scheme of things"
      xaxis = "X-Axis"
      yaxis = "Y-Axis"
     
      lm = 70 : rm = 70 : tm = 40 : bm = 70                   ' Margins (pixels). Space for labels etc
     
      OPEN file$ FOR INPUT AS #1
        INPUT#1, n
        DIM a(1 TO n, 1 TO 2) AS DOUBLE                       ' Note most Graphic sizes etc are single.
     
        GRAPHIC WINDOW "test", 300, 300, 800, 500 TO hBmp&
        GRAPHIC ATTACH hBmp&, 0
        GRAPHIC CLEAR %WHITE
        GRAPHIC COLOR %BLACK, %WHITE
     
        FOR r = 1 TO n                                        ' read data -> array (check data range)
          INPUT#1, a(r, 1), a(r, 2)
          xmax = MAX(a(r, 1), xmax)                           ' take note of max & min values
          ymax = MAX(a(r, 2), ymax)
          xmin = IIF(xmin > 0, MIN(a(r, 1), xmin), a(1,1))    ' initially set min to first value
          ymin = IIF(ymin > 0, MIN(a(r, 2), ymin), a(1,2))    ' update in subsequent loops
        NEXT
     
        PRINT "x" xmin "-" xmax, "y" ymin "-" ymax
        xmin = IIF(xmin > 10, FIX (xmin/10)*10,  FIX(xmin))   ' round down minimum values &
        xmax = IIF(xmax > 10, CEIL(xmax/10)*10, CEIL(xmax))   ' round up maximums for scale ranges
        ymin = IIF(ymin > 10, FIX (ymin/10)*10,  FIX(ymin))
        ymax = IIF(ymax > 10, CEIL(ymax/10)*10, CEIL(ymax))
        PRINT "x scale" xmin "-" xmax
        PRINT "y scale" ymin "-" ymax
     
        ' Calc scaled margins
        slm = lm * (xmax-xmin)/(GRAPHIC(CANVAS.X) - lm - rm) : srm = rm * (xmax-xmin)/(GRAPHIC(CANVAS.X) - lm - rm)
        stm = tm * (ymax-ymin)/(GRAPHIC(CANVAS.Y) - tm - bm) : sbm = bm * (ymax-ymin)/(GRAPHIC(CANVAS.Y) - tm - bm)
        ' PRINT "Margins l,r,t,b" Ceil(slm) Ceil(srm) Ceil(stm) Ceil(sbm)
     
        ' calculate mark spacing based on data range / values
        xmark = SWITCH(xmax-xmin =< 10, 0.5, xmax-xmin =< 100, 5, xmax-xmin =< 500, 50, xmax-xmin =< 1000, 100)  'eg
        ymark = SWITCH(ymax-ymin =< 10, 0.5, ymax-ymin =< 100, 5, ymax-ymin =< 500, 50, ymax-ymin =< 1000, 100)
        PRINT "xmark" xmark "ymark" ymark
        ' ToDo? ..align scale with nearest .5, 5, 50 w/ bigger marks at MOD 1, 10, 100 etc??
     
        ' set custom coordinates for direct plotting of points
        GRAPHIC SCALE (xmin-slm, ymax+stm) - (xmax+srm, ymin-sbm)  ' set custom coordinates for direct plotting of points
     
        ' draw axes marks, labels
        GRAPHIC SET FONT hFont1                                 ' set font
        GRAPHIC SET POS (xmax-(xmax-xmin)/2 - GRAPHIC(TEXT.SIZE.X, b$)/2, ymax + stm/2)
        GRAPHIC PRINT b$
        GRAPHIC SET POS (xmax-(xmax-xmin)/2 - GRAPHIC(TEXT.SIZE.X, xaxis$)/2, ymin - sbm/2)
        GRAPHIC PRINT xaxis$                                    ' xaxis label
     
        GRAPHIC LINE (xmin, ymin) - (xmax, ymin)                ' x axis line
     
        FOR r = xmin TO xmax STEP xmark                         ' marks
          GRAPHIC LINE (r, ymin) - (r, ymin-GRAPHIC(CELL.SIZE.Y)/2)
          GRAPHIC SET POS STEP (-GRAPHIC(CELL.SIZE.X)*1.5, -GRAPHIC(CELL.SIZE.X)*5)
        IF xmax < 10 THEN
          GRAPHIC PRINT FORMAT$(r, "0.0")                       ' print scale values
        ELSE
          GRAPHIC PRINT r
        END IF
        NEXT
     
        GRAPHIC SET FONT hFont2                                 ' font2 (rotated font)
        GRAPHIC SET POS (xmin-slm*.9, ymax / 2)
        GRAPHIC PRINT yaxis$                                    ' yaxis label
        GRAPHIC SET FONT hFont1                                 ' back to font1
     
        GRAPHIC LINE (xmin, ymin) - (xmin, ymax)                ' y axis line
     
        FOR r = ymin TO ymax STEP ymark                         ' marks
          GRAPHIC LINE (xmin, r) - (xmin-GRAPHIC(CELL.SIZE.X)/2, r)
          GRAPHIC SET POS STEP (-GRAPHIC(CELL.SIZE.X)*5, GRAPHIC(CELL.SIZE.Y)/2)
          IF ymax =< 10 THEN
            GRAPHIC PRINT FORMAT$(r, "0.0")                     ' print scale values
          ELSE
          GRAPHIC PRINT r
        END IF
        NEXT
     
        ' GRAPHIC PRINT points..
        FOR r = 1 TO n
          x = a(r, 1) - GRAPHIC(CELL.SIZE.X) / 2            ' adjust point positions to suit "X" center
          y = a(r, 2) + GRAPHIC(CELL.SIZE.Y) / 2
          PRINT a(r, 1), a(r, 2)
          GRAPHIC SET POS (x, y)
          GRAPHIC PRINT "X"
     '      GRAPHIC SET PIXEL (a(r, 1),a(r, 2)), %RED         ' check alignment of point mark
          GRAPHIC SET CAPTION "Click screen for values"
        NEXT r
     
      ' Interaction..
        DO WHILE GRAPHIC(DC) <> 0                           ' loop while Graphic Window exists
          GRAPHIC INKEY$ TO sKey                          ' check keyboard input to graphic window
          SLEEP 1
          IF sKey <> "" THEN EXIT LOOP                    ' any key to quit loop (focus goes to console)
     
          GRAPHIC WINDOW CLICK hBmp TO Clk, x, y          ' check if graphic window clicked
     
          IF Clk = 2 THEN                                               ' Double Click
            GRAPHIC SET CAPTION "test"                                  ' clear old pos info
          ELSEIF Clk = 1 THEN                                           ' Single click
            IF xmax < 10 OR ymax < 10 THEN
              GRAPHIC SET CAPTION USING$("x: #.# y: #.#", x, y)         ' show x, y 'click' position
            ELSE
              GRAPHIC SET CAPTION USING$("x: # y: #", x, y)             ' decimal places not needed
            END IF
          END IF
        LOOP
     
        PRINT "Press any key to end."
        CONSOLE SET FOCUS
        WAITKEY$
      CLOSE
     
    END FUNCTION
    '------------------/
     
    #IF 0                       ' * metastatement defines (e.g. comment) section for compiler to ignore
     
    ' sample data sets for ltest.dat
        11              11          11
        1.4, 6.1        14, 61      140, 610
        1.7, 2.4        17, 24      170, 240
        2.4, 6.5        24, 65      240, 650
        2.5, 6.9        25, 69      250, 690
        2.7, 5.4        27, 54      270, 540
        3.3, 9.3        33, 93      330, 930
        3.4, 1.7        34, 17      340, 170
        3.7, 8.9        37, 89      370, 890
        4.0, 10.0       40, 100     400, 999
        4.1, 9.0        41, 90      410, 900
        4.2, 9.7        42, 97      420, 970
     
    #ENDIF

    Leave a comment:


  • Dave Biggs
    replied
    Not bored yet

    What's needed are general algorithms to work out the range of data and appropriate marks and labels on the axes. Somewhat dependant on the actual data to be plotted of course.

    This is what I have so far..
    Code:
    ' Determine range of values to be plotted and axes required
     FOR r = 1 TO n                                    ' read data -> array (check data range)
      INPUT#1, a(r, 1), a(r, 2)
      xmax = Max(a(r, 1), xmax)                           ' note max & min values
        ymax = Max(a(r, 2), ymax)
        xmin = IIF(xmin > 0, Min(a(r, 1), xmin), a(1,1))    ' initially set min to first value
        ymin = IIF(ymin > 0, Min(a(r, 2), ymin), a(1,2))    ' update in subsequent loops
     NEXT
      PRINT "x" xmin "-" xmax, "y" ymin "-" ymax
     
      xmin = IIF(xmin > 10, Fix (xmin/10)*10,  Fix(xmin))   ' round down minimum values &
      xmax = IIF(xmax > 10, Ceil(xmax/10)*10, Ceil(xmax))   ' round up maximums for scale ranges
      ymin = IIF(ymin > 10, Fix (ymin/10)*10,  Fix(ymin))
      ymax = IIF(ymax > 10, Ceil(ymax/10)*10, Ceil(ymax))
      PRINT "x scale" xmin "-" xmax
      PRINT "y scale" ymin "-" ymax
     
      ' To Do: 
      ' calculate mark spacing based on data range / values
      ' ..divide scale by .5, 5, 50 bigger marks at MOD 1, 10, 100 ?
     
      ' draw axes marks, labels
     
      ' GRAPHIC SET CLIP (margins to set aside area for plotting)
      ' .. ~ 70 pixels on left and bottom, 30 at top for Title, 60 on the right for balance?
     
      ' GRAPHIC SCALE (xmin, ymin) - (xmax, ymax)  ' set custom coordinates for direct plotting of points
     
      ' GRAPHIC PRINT points..
    '------------------/
     
    'Sample data, results:
    x 1.4 - 4.2   y 1.7 - 10         x 14 - 42     y 17 - 100
     
    x scale 1 - 5                    x scale 10 - 50
    y scale 1 - 10                   y scale 10 - 100
     1.4           6.1                14            61
     1.7           2.4                17            24
     2.4           6.5                24            65
     2.5           6.9                25            69
     2.7           5.4                27            54
     3.3           9.3                33            93
     3.4           1.7                34            17
     3.7           8.9                37            89
     4             10                 40            100
     4.1           9                  41            90
     4.2           9.7                42            97

    Leave a comment:


  • Mike Hounsome
    replied
    Thanks for the latest lesson, Dave! I like the rotated font and the correct position of the Xs and the click on the screen is a nice demonstration which I may well use in other programs but it is not necessary in this one. I've changed the 'LOCAL' statements to split the integers from the reals, so that x,y,xmax and ymax are double precision as they are rarely integers in real life - OK, in the test data set they are integers but usually they would not be. The main problem now is to make the program work for all conceivable data sets. I tried it with the same data except that I moved the decimal point one place to the left in all the X values and the axis scaling and point setting went haywire. As I said in my last message it's the scaling to accommodate all conceivable data that's the problem. I solved it in my TurboBasic programs but I'm having difficulty in seeing how to do it in PBCC. In any case, in my TurboBasic programs it always resulted in messy axis divisions and I'm hopeful that in PBCC I can tidy that up. I hope that you don't mind spending time helping me on this - just let me know when you get bored with it. You've already given me some excellent pointers and I'm very grateful.

    Mike

    Leave a comment:

Working...
X