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">&lt;?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">, &amp;</span><span class="hl-var">$aYears</span><span class="hl-code">, &amp;</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"> =&gt; </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">?&gt;</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">&lt;?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">-&gt;</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">-&gt;</span><span class="hl-identifier">title</span><span class="hl-code">-&gt;</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">-&gt;</span><span class="hl-identifier">xaxis</span><span class="hl-code">-&gt;</span><span class="hl-identifier">title</span><span class="hl-code">-&gt;</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">-&gt;</span><span class="hl-identifier">yaxis</span><span class="hl-code">-&gt;</span><span class="hl-identifier">title</span><span class="hl-code">-&gt;</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">-&gt;</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">-&gt;</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">?&gt;</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">&lt;?php</span><span class="hl-code">
</span><span class="hl-var">$lineplot</span><span class="hl-code">-&gt;</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">?&gt;</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">&lt;?php</span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-&gt;</span><span class="hl-identifier">xaxis</span><span class="hl-code">-&gt;</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">?&gt;</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">&lt;?php</span><span class="hl-code">
</span><span class="hl-var">$graph</span><span class="hl-code">-&gt;</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">?&gt;</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">&lt;?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">-&gt;</span><span class="hl-identifier">xaxis</span><span class="hl-code">-&gt;</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">?&gt;</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">&lt;?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">-&gt;</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">-&gt;</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">?&gt;</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">&lt;?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">-&gt;</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">?&gt;</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-&gt;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>