ch04s02.html
54.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Graphing the number of sun spots during the 19th Century</title><link rel="stylesheet" type="text/css" href="manual.css"><meta name="generator" content="DocBook XSL Stylesheets V1.76.0"><link rel="home" href="index.html" title="JpGraph Manual"><link rel="up" href="ch04.html" title="Chapter 4. Your first graph script"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Graphing the number of sun spots during the 19th Century</th></tr><tr><td width="20%" align="left"> </td><th width="60%" align="center">Chapter 4. Your first graph script</th><td width="20%" align="right"> </td></tr></table><hr></div><div class="sect1" title="Graphing the number of sun spots during the 19th Century"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="sec1.graphing-sun-spots"></a>Graphing the number of sun spots during the 19th Century</h2></div></div></div>
<div class="sect2" title="The historic data"><div class="titlepage"><div><div><h3 class="title"><a name="id2492934"></a>The historic data</h3></div></div></div>
<p>It is a well known fact that sun spots have a certain pattern and regularity.
The cause of these regular patterns are not currently fully understood (even
though investigation into this phenomenon has been made since beginning of the
17:th century). The fact that solar storms affects the earth in terms of
interference with radio traffic and other sensitive electronic devices makes it
very interesting to keep careful records of the suns activities.</p>
<p>For this reason the data of solar storm is readily available and makes an
interesting first example. The data used here is taken from SIDC (The Solar
Influences Data Analysis Center) in Belgium (<code class="uri"><a class="uri" href="http://sidc.oma.be/sunspot-data/SIDCpub.php" target="_top">http://sidc.oma.be/sunspot-data/SIDCpub.php</a></code>).
In this example we will use the summary historical data that shows the total
number of sun spots per year since 1700.. </p>
</div>
<div class="sect2" title="Preparing the data"><div class="titlepage"><div><div><h3 class="title"><a name="sec.preparing-sunspots-data"></a>Preparing the data</h3></div></div></div>
<p>The first step is to get the data into our PHP script which makes for a first
good discussion since all graphs needs to get data from some source. The library
itself is agnostic in regards to from where the data is collected and only needs
(and requires) data stored in a PHP array of numbers (integers or floats). </p>
<p>In principle the data to be plotted in the graph can come from :</p>
<p>
</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">
<p>Hard-coded data in the script. This is the least flexible and can
only really be recommended for examples and really static
data.</p>
</li><li class="listitem">
<p>Data stored in plain text files. (This is what we will use in this
example.)</p>
</li><li class="listitem">
<p>Data stored in binary format in flat files. </p>
</li><li class="listitem">
<p>Data stored in a database</p>
</li><li class="listitem">
<p>Data sent to the script via URI parameter passing (either GET or
POST HTTP constructs can be used).</p>
</li></ol></div><p>
</p>
<p>What is common among all these methods is that the creator of the script has
to read the data into one (or several) data arrays that can be used by the
library. For our example the data of sunspots are stored in a plain text file in
two columns, one column for the year (with a ".5" added which indicates the
average of the year) and one column for the number of sunspots for the
corresponding year. As illustration the first 10 lines of data is shown in <a class="xref" href="ch04s02.html#fig.first-ten-sunspot" title="Figure 4.1. The first ten rows of data of sunspot activities from year 1700">Figure 4.1. The first ten rows of data of sunspot activities from year
1700</a>.</p>
<p>
</p><div class="figure"><a name="fig.first-ten-sunspot"></a><p class="title"><b>Figure 4.1. The first ten rows of data of sunspot activities from year
1700</b></p><div class="figure-contents">
<div class="hl-main"><table class="hl-table" width="100%"><tr><td class="hl-gutter" align="right" valign="top"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="hl-main" valign="top"><pre><span class="hl-code">1700.5 5.0
1701.5 11.0
1702.5 16.0
1703.5 23.0
1704.5 36.0
1705.5 58.0
1706.5 29.0
1707.5 20.0
1708.5 10.0
1709.5 8.0</span></pre></td></tr></table></div>
</div></div><p><br class="figure-break">
</p>
<p>From this data we need to create two arrays, one with the number of sunspots
and one with the corresponding years. If we assume that the data is stored in a
text file named "<code class="filename">yearssn.txt</code>" in the same directory as the
script file the function in <a class="xref" href="ch04s02.html#fig.getsunspots" title="Figure 4.2. Reading numeric tabulated sunspot data from a file">Figure 4.2. Reading numeric tabulated sunspot data from a file</a>will read the data into two arrays</p>
<p>
</p><div class="figure"><a name="fig.getsunspots"></a><p class="title"><b>Figure 4.2. Reading numeric tabulated sunspot data from a file</b></p><div class="figure-contents">
<a name="pl.getsunspots"></a><div class="hl-main"><table class="hl-table" width="100%"><tr><td class="hl-gutter" align="right" valign="top"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="hl-main" valign="top"><pre><span class="hl-inlinetags"><?php</span><span class="hl-code">
</span><span class="hl-reserved">function</span><span class="hl-code"> </span><span class="hl-identifier">readsunspotdata</span><span class="hl-brackets">(</span><span class="hl-var">$aFile</span><span class="hl-code">, &</span><span class="hl-var">$aYears</span><span class="hl-code">, &</span><span class="hl-var">$aSunspots</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
</span><span class="hl-var">$lines</span><span class="hl-code"> = @</span><span class="hl-identifier">file</span><span class="hl-brackets">(</span><span class="hl-var">$aFile</span><span class="hl-code">,</span><span class="hl-identifier">FILE_IGNORE_NEW_LINES</span><span class="hl-code">|</span><span class="hl-identifier">FILE_SKIP_EMPTY_LINES</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-reserved">if</span><span class="hl-brackets">(</span><span class="hl-code"> </span><span class="hl-var">$lines</span><span class="hl-code"> === </span><span class="hl-reserved">false</span><span class="hl-code"> </span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
</span><span class="hl-reserved">throw</span><span class="hl-code"> </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">JpGraphException</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">Can not read sunspot data file.</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-reserved">foreach</span><span class="hl-brackets">(</span><span class="hl-code"> </span><span class="hl-var">$lines</span><span class="hl-code"> </span><span class="hl-reserved">as</span><span class="hl-code"> </span><span class="hl-var">$line</span><span class="hl-code"> => </span><span class="hl-var">$datarow</span><span class="hl-code"> </span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
</span><span class="hl-var">$split</span><span class="hl-code"> = </span><span class="hl-identifier">preg_split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">/[\s]+/</span><span class="hl-quotes">'</span><span class="hl-code">,</span><span class="hl-var">$datarow</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-var">$aYears</span><span class="hl-brackets">[</span><span class="hl-brackets">]</span><span class="hl-code"> = </span><span class="hl-identifier">substr</span><span class="hl-brackets">(</span><span class="hl-identifier">trim</span><span class="hl-brackets">(</span><span class="hl-var">$split</span><span class="hl-brackets">[</span><span class="hl-number">0</span><span class="hl-brackets">]</span><span class="hl-brackets">)</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-var">$aSunspots</span><span class="hl-brackets">[</span><span class="hl-brackets">]</span><span class="hl-code"> = </span><span class="hl-identifier">trim</span><span class="hl-brackets">(</span><span class="hl-var">$split</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-var">$year</span><span class="hl-code"> = </span><span class="hl-reserved">array</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-var">$ydata</span><span class="hl-code"> = </span><span class="hl-reserved">array</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-identifier">readsunspotdata</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">yearssn.txt</span><span class="hl-quotes">'</span><span class="hl-code">,</span><span class="hl-var">$year</span><span class="hl-code">,</span><span class="hl-var">$ydata</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-inlinetags">?></span></pre></td></tr></table></div>
</div></div><p><br class="figure-break">
</p>
<p>In the function above we have deviated from the common practice of not
including even the most basic error handling in examples by adding an exception
in case the data file could not be read. This is to emphasize that graph scripts
which reads data from potentially disconnected sources must have real quality
error and exception handling. As this is the first example we will not discuss
the details of the error handling other than saying that the library provides
one exception class <code class="code">JpGraphException</code> that is meant to be used by
clients to signal unrecoverable errors in the code. The full details on error
handling in the library is discussed in <a class="xref" href="ch06.html" title="Chapter 6. Error handling">Chapter 6. <i>Error handling</i></a></p>
<p>
</p><div class="tip" title="Tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Tip</h3>
<p>In the library there is an auxiliary utility class
<code class="code">ReadFileData</code> to help read data from text files. In this
class there are methods to read data from a file in either of the
following formats</p>
<p>
</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
<p> CSV (Comma Separated Values) format.
<code class="code">ReadFileData::FromCSV()</code></p>
</li><li class="listitem">
<p>two column format (almost) as we did manually above with
<code class="code">ReadFileData::From2Col()</code></p>
</li><li class="listitem">
<p>one column format
<code class="code">ReadFileData::From1Col()</code></p>
</li></ul></div><p>
</p>
</div><p>
</p>
<p>Armed with the data in the two arrays <code class="code">$year</code> and
<code class="code">$ydata</code> we will now plot the data in a basic line graph with
some variations and then show the data in a bar graph.</p>
</div>
<div class="sect2" title="A basic line graph"><div class="titlepage"><div><div><h3 class="title"><a name="id2492973"></a>A basic line graph</h3></div></div></div>
<p>As the very first start we will create a line graph which shows sun spots as a
line graph. To keep the code focused on the graph we do not include the previous
function to read the data again in the code snippet shown below. Before we get
into the code we start by briefly discuss how your script can include the
necessary library files.</p>
<p>All graph scripts must include at least two files,
<code class="filename">jpgraph.php</code> and some plot module. If we want to create
a line plot we must include <code class="filename">jpgraph_line.php</code>. Slightly
depending on the server setup and what paths are defined for PHP include files
(as discussed in <a class="xref" href="ch03s03.html#sec2.adjusting-php-include-path" title="Adjusting PHP include path">Adjusting PHP include path</a>) the include paths for the
library might look a bit different. However, we recommend that you install the
library files so they can be accessed, for example using,
<code class="code">require_once('jpgraph/jpgraph.php')</code> (since this is what is
assumed by the library examples). Furthermore, we would recommend that the
<code class="code">require_once()</code> construct is used to avoid including the same
file multiple times.</p>
<p>
</p><div class="hl-main"><table class="hl-table" width="100%"><tr><td class="hl-gutter" align="right" valign="top"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="hl-main" valign="top"><pre><span class="hl-inlinetags"><?php</span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> Width and height of the graph</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$width</span><span class="hl-code"> = </span><span class="hl-number">600</span><span class="hl-code">; </span><span class="hl-var">$height</span><span class="hl-code"> = </span><span class="hl-number">200</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Create a graph instance</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code"> = </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">Graph</span><span class="hl-brackets">(</span><span class="hl-var">$width</span><span class="hl-code">,</span><span class="hl-var">$height</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Specify what scale we want to use,</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> int = integer scale for the X-axis</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> int = integer scale for the Y-axis</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">SetScale</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">intint</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Setup a title for the graph</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">title</span><span class="hl-code">-></span><span class="hl-identifier">Set</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">Sunspot example</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Setup titles and X-axis labels</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">xaxis</span><span class="hl-code">-></span><span class="hl-identifier">title</span><span class="hl-code">-></span><span class="hl-identifier">Set</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">(year from 1701)</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Setup Y-axis title</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">yaxis</span><span class="hl-code">-></span><span class="hl-identifier">title</span><span class="hl-code">-></span><span class="hl-identifier">Set</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">(# sunspots)</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Create the linear plot</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$lineplot</span><span class="hl-code">=</span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">LinePlot</span><span class="hl-brackets">(</span><span class="hl-var">$ydata</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Add the plot to the graph</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">Add</span><span class="hl-brackets">(</span><span class="hl-var">$lineplot</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Display the graph</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">Stroke</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-inlinetags">?></span></pre></td></tr></table></div><p>
</p>
<p>Before we explain this code in some more detail it is a good idea to visualize
what we get when we execute this as script. The result of running this script is
shown in <a class="xref" href="ch04s02.html#fig.sunspotsex1" title="Figure 4.3. Line plot showing the number of sun spots since 1700 (sunspotsex1.php)">Figure 4.3. Line plot showing the number of sun spots since 1700 <code class="uri"><a class="uri" href="example_src/sunspotsex1.html" target="_top">(<code class="filename">sunspotsex1.php</code>)</a></code> </a></p>
<p>
</p><div class="figure"><a name="fig.sunspotsex1"></a><p class="title"><b>Figure 4.3. Line plot showing the number of sun spots since 1700 <code class="uri"><a class="uri" href="example_src/sunspotsex1.html" target="_top">(<code class="filename">sunspotsex1.php</code>)</a></code> </b></p><div class="figure-contents"> <span class="inlinemediaobject"><img src="images/sunspotsex1.png" alt="Line plot showing the number of sun spots since 1700 (sunspotsex1.php)"></span> </div></div><p><br class="figure-break">
</p>
<p>
</p><div class="tip" title="Tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Tip</h3>
<p>You can always click on the filename in the title of a figure to view
the complete source code.</p>
</div><p>
</p>
<p>Let us now walk through this code in some details.</p>
<p>
</p><div class="variablelist"><dl><dt><span class="term">Line 1-12</span></dt><dd>
<p>The size of the graph must always be specified so the first
thing to do is to create a new graph object and set the width
and height of the overall graph. All graph scripts will need to
create at least one instance of the <code class="code">Graph()</code> class.
By convention in all our scripts we will name the created
instance of the Graph class "<code class="code">$graph</code>"..</p>
<p>The second thing that all graph scripts must specify is what
kind of scales should be used. The library supports linear,
integer, logarithmic, text and date scales. Since we know that
our data consist of only integers we keep things simple and set
both the X and the Y axis scale to be integers. The scale is
specified as a string where the first half of the string
denominates the X-axis scale and the second half denominates the
Y-axis scale. So in our example we specify
'<code class="code">intint'</code>. With this explanation you can probably
guess what '<code class="code">intlog</code>' or '<code class="code">linlog</code>' would
do. Why not try it ?</p>
</dd><dt><span class="term">Line 13-21</span></dt><dd>
<p>These lines sets some different text labels. By the naming
convention used in the library you can probably guess what all
those lines are doing. They set the overall graph title as well
as the X- and Y-axis titles. To keep the example as lean as
possible we use the default font and default size and color of
the text strings.</p>
</dd><dt><span class="term">Line 22-27</span></dt><dd>
<p>Each graph must have at least one plot (data series) that is
added to the graph. In our case we wanted to create a line graph
so we must create an instance of the class
'<code class="code">LinePlot</code>'. We create a new instance of this
class and as a parameter use the data for the data series we
want to create the line plot from, in our case the data array
with the sun spot numbers.</p>
</dd><dt><span class="term">Line 29</span></dt><dd>
<p>Understanding this single line is key to understanding dynamic
graph generation with PHP. This line instructs the library to
actually create the graph as an image, encode it in the chosen
image format (e.g. png, jpg, gif, etc) and stream it back to the
browser with the correct header identifying the data stream that
the client receives as a valid image stream. When the client
(most often a browser) calls the PHP script it will return data
that will make the browser think it is receiving an image and
not, as you might have done up to now from PHP scripts, text. </p>
<p>This is something that can be conceptually difficult to fully
understand at first and that is why we are spending the entire
next chapter <a class="xref" href="ch05.html" title="Chapter 5. Fundamentals of dynamic graph generation">Chapter 5. <i>Fundamentals of dynamic graph generation</i></a> on further exploring
this. But for now please accept that this works and by calling
the script above in your browser (it is available in the
"<code class="filename">Examples/</code>" directory in the
distribution as '<code class="filename">sunspotsex1.php</code>') you
should get the exact same image as shown above in <a class="xref" href="ch04s02.html#fig.sunspotsex1" title="Figure 4.3. Line plot showing the number of sun spots since 1700 (sunspotsex1.php)">Figure 4.3. Line plot showing the number of sun spots since 1700 <code class="uri"><a class="uri" href="example_src/sunspotsex1.html" target="_top">(<code class="filename">sunspotsex1.php</code>)</a></code> </a></p>
</dd></dl></div><p>
</p>
<p>Let's now make a small variation of the above line graph. Let's make it a
filled line graph. instead. In order to do this we only have to add one single
line</p>
<p>
</p><div class="hl-main"><table class="hl-table" width="100%"><tr><td class="hl-gutter" align="right" valign="top"><pre>1
2
3
</pre></td><td class="hl-main" valign="top"><pre><span class="hl-inlinetags"><?php</span><span class="hl-code">
</span><span class="hl-var">$lineplot</span><span class="hl-code">-></span><span class="hl-identifier">SetFillColor</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">orange@0.5</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-inlinetags">?></span></pre></td></tr></table></div><p>
</p>
<p>The line above actually does two things. First it sets the basic color to
'orange' and then it modifies this color to be 50% opaque (0.5) which makes the
grid line shine through the fill color to some extent. The whole color handling
in the library is further describe both in <a class="xref" href="apd.html" title="Appendix D. Named color list">Appendix D. <i>Named color list</i></a> as well as in <a class="xref" href="ch07.html" title="Chapter 7. Color handling">Chapter 7. <i>Color handling</i></a>. The result of adding the line above is
shown in <a class="xref" href="ch04s02.html#fig.sunspotsex2" title="Figure 4.4. Displaying sun spots with a semi filled line graph (sunspotsex2.php)">Figure 4.4. Displaying sun spots with a semi filled line graph <code class="uri"><a class="uri" href="example_src/sunspotsex2.html" target="_top">(<code class="filename">sunspotsex2.php</code>)</a></code> </a></p>
<p>
</p><div class="figure"><a name="fig.sunspotsex2"></a><p class="title"><b>Figure 4.4. Displaying sun spots with a semi filled line graph <code class="uri"><a class="uri" href="example_src/sunspotsex2.html" target="_top">(<code class="filename">sunspotsex2.php</code>)</a></code> </b></p><div class="figure-contents"> <span class="inlinemediaobject"><img src="images/sunspotsex2.png" alt="Displaying sun spots with a semi filled line graph (sunspotsex2.php)"></span> </div></div><p><br class="figure-break">
</p>
<div class="sect3" title="Adding tick labels to the X-axis"><div class="titlepage"><div><div><h4 class="title"><a name="id2493501"></a>Adding tick labels to the X-axis</h4></div></div></div>
<p>
</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3>
<p>This section can be skipped at first reading since it contains
some slightly more advanced material. The reason why we have
included this section already now is that some of the issues
discussed here is an often repeated question among newcomers to the
library.</p>
</div><p>
</p>
<p>There is one bit of the available data that we haven't used yet and that
is the actual years. In the example above we can only see the count from
1700. (If we just want to look at the cyclic behaviour of the number of
sunspots this is fine since what year a specific number of sunspots appeared
is not relevant.) To make it easier to see what year corresponds to the
different sunspot numbers we must change the label on the X-axis scale to
show the years instead.</p>
<p>There is actually a couple of ways to do this. The easiest way is to just
add the labels we have (<code class="code">$years</code>) on the X-axis and instruct the
library to use them instead. This is done with a call to the method
<code class="code">SetTickLabels()</code> on the X-axis. This method call takes an
array as argument and uses the values in that array to populate all labels
on major tick marks. In order to make adequate room for the scale the
library automatically selects a suitable distance between each major tick
mark.</p>
<p>
</p><div class="hl-main"><table class="hl-table" width="100%"><tr><td class="hl-gutter" align="right" valign="top"><pre>1
2
3
</pre></td><td class="hl-main" valign="top"><pre><span class="hl-inlinetags"><?php</span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">xaxis</span><span class="hl-code">-></span><span class="hl-identifier">SetTickLabels</span><span class="hl-brackets">(</span><span class="hl-var">$year</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-inlinetags">?></span></pre></td></tr></table></div><p>
</p>
<p>Adding this line to our previous graph will generate the graph shown in <a class="xref" href="ch04s02.html#fig.sunspotsex3" title="Figure 4.5. Adding tick labels to the graph (sunspotsex3.php)">Figure 4.5. Adding tick labels to the graph <code class="uri"><a class="uri" href="example_src/sunspotsex3.html" target="_top">(<code class="filename">sunspotsex3.php</code>)</a></code> </a></p>
<p>
</p><div class="figure"><a name="fig.sunspotsex3"></a><p class="title"><b>Figure 4.5. Adding tick labels to the graph <code class="uri"><a class="uri" href="example_src/sunspotsex3.html" target="_top">(<code class="filename">sunspotsex3.php</code>)</a></code> </b></p><div class="figure-contents"> <span class="inlinemediaobject"><img src="images/sunspotsex3.png" alt="Adding tick labels to the graph (sunspotsex3.php)"></span> </div></div><p><br class="figure-break">
</p>
<p>However, there is a problem in the graph above. There are valid years on
the X-axis up to "2000" but then there is a single label "320". </p>
<p><span class="bold"><strong>What is going on here?</strong></span> Have we already discovered
a bug in the library? </p>
<p>No, not really. In the way we have setup the graph we have not provided
the library with enough labels. What has happened is that the integer scale
has chosen a suitable interval between each tick label to have enough space
to be able to show the labels. As can be seen from the figure the distance
chosen with this particular graph seems to be 20 years between each tick.
The way the default labeling works is that the end tick should be labelled
and hence be an even multiple of 20 years (in this case).</p>
<p>Since the library needs to have tick labels for all ticks it uses the
labels we supplied as far as they go (up to 2008) but since we didn't supply
data more than up to "2008" (in the <code class="code">$year</code> array) the library
does what it can do and continues with the ordinal numbers where we failed
to provide enough labels.</p>
<p>Now, there are a some standard ways of correcting this abomination.</p>
<p>
</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">
<p>We can set a manual scale to make sure the scale ends exactly
at 2008, i.e. the scale is exactly as long as our data. This is
done by submitting the wanted scale min/max as additional
argument in the <code class="code">SetScale()</code> method. First the
min/max for the Y-axis and then the min/max for the X-scale.
Since we still want the Y-scale to be fully automatically
determined we just put a "0" for both min and max on the Y-scale
and specify 0 for the min x-value and then the exact number of
sunspots we have measured as the maximum x-value.</p>
<p>
</p><div class="hl-main"><table class="hl-table" width="100%"><tr><td class="hl-gutter" align="right" valign="top"><pre>1
2
3
</pre></td><td class="hl-main" valign="top"><pre><span class="hl-inlinetags"><?php</span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">SetScale</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">intint</span><span class="hl-quotes">'</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-identifier">max</span><span class="hl-brackets">(</span><span class="hl-var">$year</span><span class="hl-brackets">)</span><span class="hl-code">-</span><span class="hl-identifier">min</span><span class="hl-brackets">(</span><span class="hl-var">$year</span><span class="hl-brackets">)</span><span class="hl-code">+</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-inlinetags">?></span></pre></td></tr></table></div><p>
</p>
<p>The result of this is shown in <a class="xref" href="ch04s02.html#fig.sunspotsex4" title="Figure 4.6. Manually specifying the X scale to use just the supplied X values (sunspotsex4.php)">Figure 4.6. Manually specifying the X scale to use just the supplied X values <code class="uri"><a class="uri" href="example_src/sunspotsex4.html" target="_top">(<code class="filename">sunspotsex4.php</code>)</a></code> </a></p>
<p>
</p><div class="figure"><a name="fig.sunspotsex4"></a><p class="title"><b>Figure 4.6. Manually specifying the X scale to use just the supplied X values <code class="uri"><a class="uri" href="example_src/sunspotsex4.html" target="_top">(<code class="filename">sunspotsex4.php</code>)</a></code> </b></p><div class="figure-contents"> <span class="inlinemediaobject"><img src="images/sunspotsex4.png" alt="Manually specifying the X scale to use just the supplied X values (sunspotsex4.php)"></span> </div></div><p><br class="figure-break">
</p>
</li><li class="listitem">
<p>An alternative way to get labels is to use a callback function
to specify the labels. This works so that the library calls the
user specified function and as argument passes the label (or the
value of the label) that the library intends to put on a tick.
The library will then use as the actual label whatever string
value we return from our function. Since we know that the
integer label 0 (the first tick) corresponds to the first value,
i.e. "1700" we can simply take whatever label we get as
argument, add "1700" and return that value. This way all labels
will be properly named and even if the scale extends far beyond
where we have data a sensible tick label will be shown.</p>
<p>A suitable callback function together with the method to
instruct the library to use this callback would be</p>
<p>
</p><div class="hl-main"><table class="hl-table" width="100%"><tr><td class="hl-gutter" align="right" valign="top"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="hl-main" valign="top"><pre><span class="hl-inlinetags"><?php</span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> ...</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> Label callback</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-reserved">function</span><span class="hl-code"> </span><span class="hl-identifier">year_callback</span><span class="hl-brackets">(</span><span class="hl-var">$aLabel</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code">
</span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">1700</span><span class="hl-code">+</span><span class="hl-brackets">(</span><span class="hl-identifier">int</span><span class="hl-brackets">)</span><span class="hl-var">$aLabel</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> ...</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">xaxis</span><span class="hl-code">-></span><span class="hl-identifier">SetLabelFormatCallback</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">year_callback</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> ...</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-inlinetags">?></span></pre></td></tr></table></div><p>
</p>
<p>and the result can be seen in <a class="xref" href="ch04s02.html#fig.sunspotsex5" title="Figure 4.7. Using a callback to get correct values on the x axis (sunspotsex5.php)">Figure 4.7. Using a callback to get correct values on the x axis <code class="uri"><a class="uri" href="example_src/sunspotsex5.html" target="_top">(<code class="filename">sunspotsex5.php</code>)</a></code> </a></p>
<p>
</p><div class="figure"><a name="fig.sunspotsex5"></a><p class="title"><b>Figure 4.7. Using a callback to get correct values on the x axis <code class="uri"><a class="uri" href="example_src/sunspotsex5.html" target="_top">(<code class="filename">sunspotsex5.php</code>)</a></code> </b></p><div class="figure-contents"> <span class="inlinemediaobject"><img src="images/sunspotsex5.png" alt="Using a callback to get correct values on the x axis (sunspotsex5.php)"></span> </div></div><p><br class="figure-break">
</p>
</li><li class="listitem">
<p>There is one more way to handle this issue which we will not
cover in detail yet. This is to use a "text" scale. The
"text"scale can be used when there is no need to show numeric
values on the axis. A typical use for text scale would be to add
labels to mark bar graphs. Of course a text can contain numeric
strings that would make it visually indistinguishable from a
"real" numeric value.</p>
<p>For text scales every label counts. So by default the library
will assign a tick mark for each ordinal so that every label is
used. In some cases this will just be two dense and then the
tick and the labelling can be adjusted by calling the two
methods <code class="code">Axis::SetTextTickInterval()</code> and
<code class="code">Axis::SetTextLabelInterval()</code> to get to a wanted
result. But for now we do not discuss this technique further
here since it would bring too far.</p>
</li></ol></div><p>
</p>
</div>
</div>
<div class="sect2" title="A basic bar graph"><div class="titlepage"><div><div><h3 class="title"><a name="id2493198"></a>A basic bar graph</h3></div></div></div>
<p>As a final illustration we will show how easy it is to change the plot type.
We will make a small modification of the previous script and display the sun
spots as a bar graph instead. In order to do this we take the code from <a class="xref" href="ch04s02.html#fig.sunspotsex2" title="Figure 4.4. Displaying sun spots with a semi filled line graph (sunspotsex2.php)">Figure 4.4. Displaying sun spots with a semi filled line graph <code class="uri"><a class="uri" href="example_src/sunspotsex2.html" target="_top">(<code class="filename">sunspotsex2.php</code>)</a></code> </a> and just change the creation of an instance
of the <code class="code">LinePlot()</code> class to instead be an instance of the
<code class="code">BarPlot()</code> class (to make the code more readable we also change
the name of the variable where we store the instance so it makes more sense). In
order to use this class we must also change the include statement so that the
bar module is included by adding the statement
<code class="code">require_once('jpgraph/jpgraph_barplot.php')</code>. The changed code
would now look like this</p>
<p>
</p><div class="hl-main"><table class="hl-table" width="100%"><tr><td class="hl-gutter" align="right" valign="top"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="hl-main" valign="top"><pre><span class="hl-inlinetags"><?php</span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> ...</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> Create the bar plot</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$barplot</span><span class="hl-code">=</span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">BarPlot</span><span class="hl-brackets">(</span><span class="hl-var">$ydata</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Add the plot to the graph</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">Add</span><span class="hl-brackets">(</span><span class="hl-var">$barplot</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> Display the graph</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">Stroke</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-inlinetags">?></span></pre></td></tr></table></div><p>
</p>
<p>and would result in the graph displayed in <a class="xref" href="ch04s02.html#fig.sunspotsex6" title="Figure 4.8. Changing the plot type to a bar plot instead (sunspotsex6.php)">Figure 4.8. Changing the plot type to a bar plot instead <code class="uri"><a class="uri" href="example_src/sunspotsex6.html" target="_top">(<code class="filename">sunspotsex6.php</code>)</a></code> </a></p>
<p>
</p><div class="figure"><a name="fig.sunspotsex6"></a><p class="title"><b>Figure 4.8. Changing the plot type to a bar plot instead <code class="uri"><a class="uri" href="example_src/sunspotsex6.html" target="_top">(<code class="filename">sunspotsex6.php</code>)</a></code> </b></p><div class="figure-contents"> <span class="inlinemediaobject"><img src="images/sunspotsex6.png" alt="Changing the plot type to a bar plot instead (sunspotsex6.php)"></span> </div></div><p><br class="figure-break">
</p>
<p>Since there are so many bars in small space we cannot see the individual bars
in the example in <a class="xref" href="ch04s02.html#fig.sunspotsex6" title="Figure 4.8. Changing the plot type to a bar plot instead (sunspotsex6.php)">Figure 4.8. Changing the plot type to a bar plot instead <code class="uri"><a class="uri" href="example_src/sunspotsex6.html" target="_top">(<code class="filename">sunspotsex6.php</code>)</a></code> </a>. So lets modify the script so that it only
shows the last 20 years of measurements so that we can see the individual bars.
To set this up there are two things we must do</p>
<p>
</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">
<p>Change the scale ot a text scale since we want to make sure each
value is displayed. In addition the text scale actually changes one
more thing that we haven't mentioned. Using a text scale also
changes the alignment of the labels. For linear, integer,
logarithmic scales the labels are placed cantered below the tick
marks. For text labels they are instead place in between the tick
marks. This is the most common way of displaying bar graphs. This is
one more reason to think of text scales as a special scale mostly
suitable for bar graphs.</p>
</li><li class="listitem">
<p>Add two lines of code to "chop off" the extra not wanted data in
the input data arrays.</p>
</li></ol></div><p>
</p>
<p>The following code snippet shows the necessary modifications to the previous
script</p>
<p>
</p><div class="hl-main"><table class="hl-table" width="100%"><tr><td class="hl-gutter" align="right" valign="top"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="hl-main" valign="top"><pre><span class="hl-inlinetags"><?php</span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> Just keep the last 20 values in the arrays</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$year</span><span class="hl-code"> = </span><span class="hl-identifier">array_slice</span><span class="hl-brackets">(</span><span class="hl-var">$year</span><span class="hl-code">, -</span><span class="hl-number">20</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-var">$ydata</span><span class="hl-code"> = </span><span class="hl-identifier">array_slice</span><span class="hl-brackets">(</span><span class="hl-var">$ydata</span><span class="hl-code">, -</span><span class="hl-number">20</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> ...</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> Specify what scale we want to use,</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> text = txt scale for the X-axis</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment"> int = integer scale for the Y-axis</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-></span><span class="hl-identifier">SetScale</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">textint</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-comment">//</span><span class="hl-comment"> ...</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-inlinetags">?></span></pre></td></tr></table></div><p>
</p>
<p>The final graph with the "zoomed" last 20 years can now be seen in</p>
<p>
</p><div class="figure"><a name="fig.sunspotsex7"></a><p class="title"><b>Figure 4.9. Sunspots zoomed to only show the last 20 years <code class="uri"><a class="uri" href="example_src/sunspotsex7.html" target="_top">(<code class="filename">sunspotsex7.php</code>)</a></code> </b></p><div class="figure-contents"> <span class="inlinemediaobject"><img src="images/sunspotsex7.png" alt="Sunspots zoomed to only show the last 20 years (sunspotsex7.php)"></span> </div></div><p><br class="figure-break">
</p>
<p>Since the scale is larger we can now actually see the individual bars. By
default the library choses a light blue color to fill the interior. (Try to see
what happens if you add the method call
"<code class="code">$barplot->SetFillColor('orange@0.5');</code>" just after the
"<code class="code">$barplot</code>" variable has been assigned the new BarPlot
object.)</p>
</div>
</div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"> </td><td width="20%" align="center"><a accesskey="u" href="ch04.html">Up</a></td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top"> </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> </td></tr></table></div></body></html>