Bar Chart Subroutine

16K Cassette or Disk
by Thomas P. Newdome


The advent of computer processing has brought the capability to provide a quick analysis of data via a graphic display. One type of display, the bar chart, is commonly used for displaying data that has values occuring at discrete intervals. The quarterly dividend of a given stock, the annual rainfall at a specific location, and the amount of money spent per month on food by a family are a few of many possible examples.

The following program, written as a subroutine, can be used to display a bar chart of data supplied by a user's program. The data is plotted against one of three different time intervals, with the user's program determining the range of the vertical axis of the plot. Included in the listing is a short program which demonstrates the use of the subroutine.

The three different time intervals which data may be plotted against are:

The vertical axis range of the chart is determined by the user. The actual range specified will, of course, be dictated by the range of data to be plotted.

The chart is constructed in Graphics mode 0. A high-resolution display is obtained through the use of a redefined character set. For a given bar, a resolution of up to 160 points is possible.

In order to use the subroutine, the calling program must supply values for six items:

  1. The beginning year (two digits) to be used for labeling the horizontal axis.
  2. The desired type (1-3) of time interval for the horizontal axis, as described above.
  3. The minimum value to be used for labeling of the vertical axis. Typically, this value may be zero; however, a negative value (in the event a negative bar is to be plotted) or a value greater than zero is also allowed.
  4. The vertical axis is "marked" off into 20 segments. Each segment has a resolution equal to 1/8 of its range. The value supplied here will be the range between each segment (mark). For example, if a vertical axis which varies from 0 to 1000 is desired, then a zero would be specified for the minimum (item 3 abo ve) and 50 would be specified for the range of each vertical mark (50 x 20 = 1000). The value for this parameter cannot be less than .01.

    If a negative number is specified as the minimum (item 3 above), then the range of each vertical mark must be large enough to insure that zero (0.00) is included as a label on the vertical axis. The subroutine will automatically take care of this condition and include zero on the vertical axis, although the minimum may not be as desired.

    The range of the vertical axis must be an interval between -99, 999.99 and 999,999.99.

  5. The data to be plotted.
  6. A descriptive title for the bar chart. This title should be 30 characters or less and use all upper case characters.

The values for the first five items above are stored by the user's program in an array, DAT(). The beginning year, plot type, minimum vertical label and vertical mark range are stored in DAT(1), DAT(2), DAT(3) and DAT(4) respectively. The data is then stored chronologically in DAT(5) through DAT(32). The desired title is stored in TITLE$, and a call to the subroutine can then be made (GOSUB 560). The subroutine plots the data and then returns to the user's program after any key is hit.

The following listings are composed of 3 segments. The first, Lines 100 through 490, is an initialization sequence which sets up the redefined characters that are used to construct the horizontal axis, vertical axis and data bars. Since the standard alphanumeric characters are also required, the upper case letters and numbers are copied from BASIC's standard character set to be used in the new character set. This is accomplished in Lines 180 through 220.

Lines 240 through 490 provide the definition of the redefined characters. Notice that this initialization also provides storage for DAT() and TITLE$ (Line 150). This initialization needs to be executed only once. Once accomplished, a branch to the user's program (second segment) is made in Line 510.

The user's program for this example is listed in Lines 1480 through 1600. The data values in Line 1520 are the chart specifications for DAT(1) - DAT(4). It will be instructive to make changes to the data values in this line to see how the chart construction is affected. Basically, the user's program puts the appropriate values into array DAT(), sets TITLE$ equal to the desired title, and then calls the bar chart subroutine with GOSUB 560.

The third segment (Lines 520 through 1470) is the subroutine itself. Lines 610 through 830 draw the horizontal axis. The vertical axis is drawn by Lines 840 through 1040. Use is made of a short subroutine (Lines 1360 through 1470) in order to right-justify the numbers for the vertical axis labels.

The data is plotted sequentially at Lines 1050 through 1320. At Line 1070, the value of a given data point is converted to the number of blocks that will be displayed to construct the bar. Each block has a height equal to the height of a Graphics 0 character; as little as 1/8 of a block can be plotted. The number of full character blocks to be plotted is determined at Line 1110, and the fractional part of a block to be added is evaluated at Line 1130. Lines 1170 through 1230 draw a bar for positive-valued data while Lines 1240 through 1320 draw a bar for negative-valued data. A return to the user's program is accomplished at Line 1350.

Precautions

There are a couple of precautions which should be noted. If the vertical range exceeds 999,999.99 or is below -99,999.99, then the subroutine will execute a program stop at Line 1380. Should this occur, readjustment of the minimum vertical value, DAT(3), or the vertical mark range, DAT(4), will be needed.

The redefined character set used by the subroutine is stored at the highest 1K block of RAM which begins at a 1K boundary. This beginning address is calculated as the value for variable NB at Line 160. When writing your application program, care must be taken to insure that this area of RAM is not overwritten.

After the initialization sequence and subroutines have been typed in, the following command, entered in the direct mode while in Graphics 0, will indicate the actual amount of RAM available for your program.

? FRE(0)-PEEK(741)-1024

As your program is added, the value shown will decrease, but as long as it is greater than zero, memory will be available. With a 16K RAM machine, at least 8K bytes should be available for your program.

Additionally, your program must not use any graphics mode which requires more RAM than Graphics 0 (see Table 9.1 in the Atari BASIC Reference Manual). This means your programs will be limited to graphics 4 or below. Otherwise, RAM required by the screen display will modify memory where the redefined character set is stored.

BASIC Listing

BARCHART.LST is available in ATASCII format.

100 REM SAMPLE PROGRAM AND SUBROU-
110 REM TINE FOR PRODUCING A BAR
120 REM CHART.    WRITTEN BY
130 REM THOMAS P. NEWDOME
140 REM INITIALIZE CHARACTER SET
150 DIM DAT(32),TITLE$(30)
160 GRAPHICS 0:CB=57344:NB=(PEEK(742)-
4)*256
170 GRAPHICS 17:POSITION 4,10:? #6;"IN
ITIALIZING"
180 FOR II=0 TO 58:XX=II*8
190 A1=CB+XX:A2=NB+XX
200 FOR JJ=0 TO 7
210 POKE A2+JJ,PEEK(A1+JJ)
220 NEXT JJ:NEXT II
230 GRAPHICS 17:POSITION 6,10:? #6;"ST
ANDBY"
240 ME=NB+512
250 RESTORE 290
260 FOR II=0 TO 20:A2=ME+II*8
270 FOR JJ=0 TO 7:READ CH:POKE A2+JJ,C
H
280 NEXT JJ:NEXT II
290 DATA 255,255,24,24,24,24,24,24
300 DATA 255,255,24,24,0,0,0,0
310 DATA 255,255,0,0,0,0,0,0
320 DATA 3,3,3,3,3,3,3,31
330 DATA 3,3,3,3,3,3,3,127
340 DATA 0,0,0,0,0,0,0,0
350 DATA 0,0,0,0,0,0,0,126
360 DATA 0,0,0,0,0,0,126,126
370 DATA 0,0,0,0,0,126,126,126
380 DATA 0,0,0,0,126,126,126,126
390 DATA 0,0,0,126,126,126,126,126
400 DATA 0,0,126,126,126,126,126,126
410 DATA 0,126,126,126,126,126,126,126
420 DATA 126,126,126,126,126,126,126,1
26
430 DATA 126,126,126,126,126,126,126,0
440 DATA 126,126,126,126,126,126,0,0
450 DATA 126,126,126,126,126,0,0,0
460 DATA 126,126,126,126,0,0,0,0
470 DATA 126,126,126,0,0,0,0,0
480 DATA 126,126,0,0,0,0,0,0
490 DATA 126,0,0,0,0,0,0,0
500 REM BRANCH TO USERS PROGRAM
510 GOTO 1480
520 REM BAR CHART SUBROUTINE
530 REM ARRAY DAT() AND TITLE$
540 REM SHOULD BE PREPARED BY THE
550 REM USERS PROGRAM
560 PT=INT(DAT(2)):YR=DAT(1):LO=DAT(3)
565 IF PT<1 OR PT>3 THEN ? "PLOT TYPE 
MUST BE 1,2, OR 3":STOP 
570 VI=DAT(4):HF=36:LI=PT+1
575 IF VI<0.01 THEN ? "THE RANGE FOR E
ACH VERTICAL MARK MUST BE > .01":STOP 
580 IF PT=2 THEN HF=38
590 IF PT=1 THEN HF=34:LI=11
600 GRAPHICS 0:POKE 756,NB/256:POKE 75
5,0
610 REM HORIZONTAL AXIS
620 POSITION 10,20:? CHR$(2)
630 POSITION 11,20
640 ? CHR$(0);
650 IF PEEK(91)>=HF THEN 710
660 FOR XX=1 TO LI
670 ? CHR$(1);
680 NEXT XX
690 GOTO 640
700 REM HORIZONTAL LABELS
710 HZ=11
720 IF PT>1 THEN 780
730 POSITION HZ,21
740 ? "JFMAMJJASONDJFMAMJJASOND"
750 POSITION HZ,22:? YR
760 POSITION 23,22:? YR+1
770 GOTO 830
780 POSITION HZ,21:? YR
790 IF PT=2 THEN YR=YR+1:HZ=HZ+4
800 IF PT=3 THEN YR=YR+5:HZ=HZ+5
810 IF YR>=100 THEN YR=YR-100
820 IF PEEK(91)<35 THEN 780
830 POSITION 24-(LEN(TITLE$))/2,23:? T
ITLE$;
840 REM VERTICAL AXIS
850 FOR XX=0 TO 19
860 POSITION 9,XX:? CHR$(3)
870 NEXT XX
880 VA=0:MB=0:V2=VI*2
890 ZE=19+INT(LO/VI)
900 IF LO>=VI THEN ZE=19:VA=LO:MB=LO/V
I
910 IF ZE<0 THEN ZE=0
920 VT=ZE:GOSUB 1380
930 VT=VT+2
940 IF VT>19 THEN 980
950 VA=VA-V2
960 GOSUB 1380
970 GOTO 930
980 VA=0:VT=ZE
990 IF LO>=VI THEN VA=LO
1000 VT=VT-2
1010 IF VT<0 THEN 1060
1020 VA=VA+V2
1030 GOSUB 1380
1040 GOTO 1000
1050 REM PLOT DATA
1060 FOR II=11 TO HF
1070 BK=DAT(II-6)/VI-MB
1080 SN=SGN(BK):BK=ABS(BK)
1090 IF SN=-1 AND ZE+BK>19 THEN BK=19-
ZE
1100 IF SN=1 AND ZE-BK<-1 THEN BK=ZE+1
1110 FB=INT(BK)
1120 XX=(BK-FB)*8
1130 PB=INT(XX)
1140 IF (XX-PB)>=0.5 THEN PB=PB+1
1150 IF PB=8 THEN FB=FB+1:PB=0
1160 IF SN=-1 THEN 1240
1170 IF FB=0 THEN 1220
1180 FOR JJ=0 TO FB-1
1190 POSITION II,ZE-JJ
1200 ? CHR$(13):NEXT JJ
1210 IF ZE-BK<=-1 THEN 1320
1220 POSITION II,ZE-FB:? CHR$(6+PB)
1230 GOTO 1320
1240 POSITION II,ZE:? CHR$(6)
1250 IF FB=0 THEN 1290
1260 FOR JJ=1 TO FB
1270 POSITION II,ZE+JJ
1280 ? CHR$(13):NEXT JJ
1290 IF PB=0 THEN 1320
1300 POSITION II,ZE+FB+1
1310 ? CHR$(21-PB)
1320 NEXT II
1330 POKE 764,255
1340 IF PEEK(764)=255 THEN 1340
1350 RETURN 
1360 REM SUBROUTINE FOR RIGHT
1370 REM JUSTIFICATION
1380 IF VA>999999.99 OR VA<-99999.99 T
HEN STOP 
1390 V3=ABS(VA):HZ=5
1400 IN=INT(V3):FA=INT((V3-IN)*100)
1410 IF IN=0 THEN 1430
1420 HZ=5-INT(CLOG(IN))
1430 IF VA<0 THEN 1450
1440 POSITION HZ,VT:? IN;".";FA;"0";:G
OTO 1460
1450 POSITION HZ-1,VT:? "-";IN;".";FA;
"0"
1460 POSITION 9,VT:? CHR$(4)
1470 RETURN 
1480 REM BEGINNING OF USER PROGRAM
1490 RESTORE 1520
1500 FOR X=1 TO 32:READ DATA
1510 DAT(X)=DATA:NEXT X
1520 DATA 80,1,-5,2
1530 DATA 0,.25,.5,.75,1,1.25,1.5,1.75
,2
1540 DATA 0,-1,-2,-3,-4,-5
1550 DATA 0,4,6,8,10,12,24,32,12,10,9,
8,6
1560 TITLE$="PLOT TYPE 1 - HIT ANY KEY
"
1570 GOSUB 560
1580 DAT(2)=2:TITLE$="PLOT TYPE 2":GOS
UB 560
1590 DAT(2)=3:TITLE$="PLOT TYPE 3":GOS
UB 560
1600 GRAPHICS 0
Checksum Data
100 DATA 7,285,886,714,486,174,311,663
,340,983,137,302,952,653,949,7842
250 DATA 215,598,8,970,937,345,303,16,
874,724,835,304,363,474,943,7909
400 DATA 974,85,554,86,986,933,465,365
,312,844,739,965,311,51,727,8397
550 DATA 42,901,878,570,852,95,813,117
,312,722,478,683,713,497,693,8366
680 DATA 746,742,817,303,523,591,464,2
04,553,739,212,193,178,674,495,7434
830 DATA 587,12,400,711,747,809,616,35
2,835,747,576,837,861,840,745,9675
980 DATA 68,331,668,923,879,953,700,52
6,643,9,361,163,531,100,162,7017
1130 DATA 195,160,847,638,885,656,173,
896,251,297,712,621,893,630,168,8022
1280 DATA 904,903,167,205,723,15,859,7
93,163,423,800,623,375,922,923,8798
1430 DATA 910,905,907,825,798,50,192,8
80,114,431,441,814,318,105,755,8445
1580 DATA 536,540,60,1136

Previous | Contents | Next

Original text copyright 1984 by ANALOG Computing. Reprinted with permission by the Digital ANALOG Archive.