Load lesson dependencies..
library(swirl)
#install_from_swirl("Exploratory Data Analysis")
library(ggplot2)
library(jpeg)
package 㤼㸱jpeg㤼㸲 was built under R version 3.5.2
Slides for this and other Data Science courses may be found at github https://github.com/DataScienceSpecialization/courses/. If you care to use them, they must be downloaded as a zip file and viewed locally. This lesson corresponds to 04_ExploratoryAnalysis/Graphics_Devices_in_R.
As the title suggests, this will be a short lesson introducing you to graphics devices in R. So, what IS a graphics device?
Would you believe that it is something where you can make a plot appear, either a screen device, such as a window on your computer, OR a file device?
There are several different kinds of file devices with particular characteristics and hence uses. These include PDF, PNG, JPEG, SVG, and TIFF. We’ll talk more about these later.
To be clear, when you make a plot in R, it has to be “sent” to a specific graphics device. Usually this is the screen (the default device), especially when you’re doing exploratory work. You’ll send your plots to files when you’re ready to publish a report, make a presentation, or send info to colleagues.
How you access your screen device depends on what computer system you’re using. On a Mac the screen device is launched with the call quartz(), on Windows you use the call windows(), and on Unix/Linux x11(). On a given platform (Mac, Windows, Unix/Linux) there is only one screen device, and obviously not all graphics devices are available on all platforms (i.e. you cannot launch windows() on a Mac).
Run the R command ?Devices to see what graphics devices are available on your system.
?Devices
R Documentation shows you what’s available.
There are two basic approaches to plotting. The first, plotting to the screen, is the most common. It’s simple - you call a plotting function like plot, xyplot, or qplot (which you call depends on the plotting system you favor, but that’s another lesson), so that the plot appears on the screen. Then you annotate (add to) the plot if necessary.
As an example, run the R command with with 2 arguments. The first is a dataset, faithful, which comes with R, and the second is a call to the base plotting function plot. Your call to plot should have two arguments, eruptions and waiting. Try this now to see what happens.
with(faithful, plot(eruptions, waiting))

See how R created a scatterplot on the screen for you? This shows that relationship between eruptions of the geyser Old Faithful and waiting time. Now use the R function title with the argument main set equal to the string "Old Faithful Geyser data". This is an annotation to the plot.
with(faithful, plot(eruptions, waiting))
title(main = "Old Faithful Geyser data")

Simple, right? Now run the command dev.cur(). This will show you the current plotting device, the screen.
dev.cur()
null device
1
The second way to create a plot is to send it to a file device. Depending on the type of plot you’re making, you explicitly launch a graphics device, e.g., a pdf file. Type the command pdf(file="myplot.pdf") to launch the file device. This will create the pdf file myplot.pdf in your working directory.
pdf(file="myplot.pdf")
You then call the plotting function (if you are using a file device, no plot will appear on the screen). Run the with command again to plot the Old Faithful data. Use the up arrow key to recover the command and save yourself some typing.
with(faithful, plot(eruptions, waiting))

Now rerun the title command and annotate the plot. (Up arrow keys are great!)
with(faithful, plot(eruptions, waiting))
title(main = "Old Faithful Geyser data")

Finally, when plotting to a file device, you have to close the device with the command dev.off(). This is very important! Don’t do it yet, though. After closing, you’ll be able to view the pdf file on your computer.
There are two basic types of file devices, vector and bitmap devices. These use different formats and have different characteristics. Vector formats are good for line drawings and plots with solid colors using a modest number of points, while bitmap formats are good for plots with a large number of points, natural scenes or web-based plots.
We’ll mention 4 specific vector formats. The first is pdf, which we’ve just used in our example. This is useful for line-type graphics and papers. It resizes well, is usually portable, but it is not efficient if a plot has many objects/points.
The second is svg which is XML-based, scalable vector graphics. This supports animation and interactivity and is potentially useful for web-based plots.
The last two vector formats are win.metafile, a Windows-only metafile format, and postscript (ps), an older format which also resizes well, is usually portable, and can be used to create encapsulated postscript files. Unfortunately, Windows systems often don’t have a postscript viewer.
We’ll also mention 4 different bitmap formats. The first is png (Portable Network Graphics) which is good for line drawings or images with solid colors. It uses lossless compression (like the old GIF format), and most web browsers can read this format natively. In addition, png is good for plots with many points, but it does not resize well.
In contrast, jpeg files are good for photographs or natural scenes. They use lossy compression, so they’re good for plots with many points. Files in jpeg format don’t resize well, but they can be read by almost any computer and any web browser. They’re not great for line drawings.
The last two bitmap formats are tiff, an older lossless compression meta-format and bmp which is a native Windows bitmapped format.
Although it is possible to open multiple graphics devices (screen, file, or both), when viewing multiple plots at once, plotting can only occur on one graphics device at a time.
The currently active graphics device can be found by calling dev.cur(). Try it now to see what number is assigned to your pdf device.
with(faithful, plot(eruptions, waiting))
dev.cur()
png
2
#Now use `dev.off()` to close the device.
dev.off()
null device
1
#Now rerun `dev.cur()` to see what integer your plotting window is assigned.
dev.cur()
null device
1
The device is back to what it was when you started. As you might have guessed, every open graphics device is assigned an integer greater than or equal to 2. You can change the active graphics device with dev.set(<integer>) where is the number associated with the graphics device you want to switch to.
You can also copy a plot from one device to another. This can save you some time but beware! Copying a plot is not an exact operation, so the result may not be identical to the original. R provides some functions to help you do this. The function dev.copy copies a plot from one device to another, and dev.copy2pdf specifically copies a plot to a PDF file.
Just for fun, rerun the with command again, with(faithful, plot(eruptions, waiting)), to plot the Old Faithful data. Use the up arrow key to recover the command if you don’t feel like typing.
with(faithful, plot(eruptions, waiting))

Now rerun the title command, title(main = "Old Faithful Geyser data"), to annotate the plot. (Up arrow keys are great!)
with(faithful, plot(eruptions, waiting))

title(main = "Old Faithful Geyser data")
#Now run `dev.copy` with the 2 arguments. The first is `png`, and the second is file set equal to `"geyserplot.png"`. This will copy your screen plot to a png file in your working directory which you can view AFTER you close the device.
dev.copy(png, file = "geyserplot.png")
png
3
#Don't forget to close the PNG device! Do it NOW!!! Then you'll be able to view the file.
dev.off()
png
2

Congrats! We hope you found this lesson deviced well!
END
LS0tDQp0aXRsZTogIkdyYXBoaWNzIERldmljZXMgaW4gUiINCnN1YnRpdGxlOiAiU3dpcmwgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcyBMZXNzb24gMyINCmF1dGhvcjogIlJvZ2VyIEQuIFBlbmcgKGNvbXBpbGVkIGFuZCBlZGl0ZWQgYnk6IE51bm5vIE51Z3JvaG8pIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KPC9icj4NCg0KTG9hZCBsZXNzb24gZGVwZW5kZW5jaWVzLi4NCmBgYHtyfQ0KbGlicmFyeShzd2lybCkNCiNpbnN0YWxsX2Zyb21fc3dpcmwoIkV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMiKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShqcGVnKQ0KYGBgDQoNCjwvYnI+DQoNCipTbGlkZXMgZm9yIHRoaXMgYW5kIG90aGVyIERhdGEgU2NpZW5jZSBjb3Vyc2VzIG1heSBiZSBmb3VuZCBhdCBnaXRodWIgaHR0cHM6Ly9naXRodWIuY29tL0RhdGFTY2llbmNlU3BlY2lhbGl6YXRpb24vY291cnNlcy8uIElmIHlvdSBjYXJlIHRvIHVzZSB0aGVtLCB0aGV5IG11c3QgYmUgZG93bmxvYWRlZCBhcyBhIHppcCBmaWxlIGFuZCB2aWV3ZWQgbG9jYWxseS4gVGhpcyBsZXNzb24gY29ycmVzcG9uZHMgdG8gMDRfRXhwbG9yYXRvcnlBbmFseXNpcy9HcmFwaGljc19EZXZpY2VzX2luX1IuKg0KDQo8L2JyPg0KDQpBcyB0aGUgdGl0bGUgc3VnZ2VzdHMsIHRoaXMgd2lsbCBiZSBhIHNob3J0IGxlc3NvbiBpbnRyb2R1Y2luZyB5b3UgdG8gZ3JhcGhpY3MgZGV2aWNlcyBpbiBSLiBTbywgd2hhdCBJUyBhIGdyYXBoaWNzIGRldmljZT8NCg0KV291bGQgeW91IGJlbGlldmUgdGhhdCBpdCBpcyBzb21ldGhpbmcgd2hlcmUgeW91IGNhbiBtYWtlIGEgcGxvdCBhcHBlYXIsIGVpdGhlciBhIHNjcmVlbiBkZXZpY2UsIHN1Y2ggYXMgYSB3aW5kb3cgb24geW91ciBjb21wdXRlciwgT1IgYSBmaWxlIGRldmljZT8NCg0KVGhlcmUgYXJlIHNldmVyYWwgZGlmZmVyZW50IGtpbmRzIG9mIGZpbGUgZGV2aWNlcyB3aXRoIHBhcnRpY3VsYXIgY2hhcmFjdGVyaXN0aWNzIGFuZCBoZW5jZSB1c2VzLiBUaGVzZSBpbmNsdWRlIFBERiwgUE5HLCBKUEVHLCBTVkcsIGFuZCBUSUZGLiBXZSdsbCB0YWxrIG1vcmUgYWJvdXQgdGhlc2UgbGF0ZXIuDQoNCg0KVG8gYmUgY2xlYXIsIHdoZW4geW91IG1ha2UgYSBwbG90IGluIFIsIGl0IGhhcyB0byBiZSAic2VudCIgdG8gYSBzcGVjaWZpYyBncmFwaGljcyBkZXZpY2UuIFVzdWFsbHkgdGhpcyBpcyB0aGUgc2NyZWVuICh0aGUgZGVmYXVsdCBkZXZpY2UpLCBlc3BlY2lhbGx5IHdoZW4geW91J3JlIGRvaW5nIGV4cGxvcmF0b3J5IHdvcmsuIFlvdSdsbCBzZW5kIHlvdXIgcGxvdHMgdG8gZmlsZXMgd2hlbiB5b3UncmUgcmVhZHkgdG8gcHVibGlzaCBhIHJlcG9ydCwgbWFrZSBhIHByZXNlbnRhdGlvbiwgb3Igc2VuZCBpbmZvIHRvIGNvbGxlYWd1ZXMuDQoNCkhvdyB5b3UgYWNjZXNzIHlvdXIgc2NyZWVuIGRldmljZSBkZXBlbmRzIG9uIHdoYXQgY29tcHV0ZXIgc3lzdGVtIHlvdSdyZSB1c2luZy4gT24gYSBNYWMgdGhlIHNjcmVlbiBkZXZpY2UgaXMgbGF1bmNoZWQgd2l0aCB0aGUgY2FsbCBgcXVhcnR6KClgLCBvbiBXaW5kb3dzIHlvdSB1c2UgdGhlIGNhbGwgYHdpbmRvd3MoKWAsIGFuZCBvbiBVbml4L0xpbnV4IGB4MTEoKWAuICBPbiBhIGdpdmVuIHBsYXRmb3JtIChNYWMsIFdpbmRvd3MsIFVuaXgvTGludXgpIHRoZXJlIGlzIG9ubHkgb25lIHNjcmVlbiBkZXZpY2UsIGFuZCBvYnZpb3VzbHkgbm90IGFsbCBncmFwaGljcyBkZXZpY2VzIGFyZSBhdmFpbGFibGUgb24gYWxsIHBsYXRmb3JtcyAoaS5lLiB5b3UgY2Fubm90IGxhdW5jaCBgd2luZG93cygpYCBvbiBhIE1hYykuDQoNClJ1biB0aGUgUiBjb21tYW5kIGA/RGV2aWNlc2AgdG8gc2VlIHdoYXQgZ3JhcGhpY3MgZGV2aWNlcyBhcmUgYXZhaWxhYmxlIG9uIHlvdXIgc3lzdGVtLg0KDQpgYGB7cn0NCj9EZXZpY2VzDQpgYGANCg0KUiBEb2N1bWVudGF0aW9uIHNob3dzIHlvdSB3aGF0J3MgYXZhaWxhYmxlLg0KDQpUaGVyZSBhcmUgdHdvIGJhc2ljIGFwcHJvYWNoZXMgdG8gcGxvdHRpbmcuIFRoZSBmaXJzdCwgcGxvdHRpbmcgdG8gdGhlIHNjcmVlbiwgaXMgdGhlIG1vc3QgY29tbW9uLiBJdCdzIHNpbXBsZSAtIHlvdSBjYWxsIGEgcGxvdHRpbmcgZnVuY3Rpb24gbGlrZSBgcGxvdGAsIGB4eXBsb3RgLCBvciBgcXBsb3RgICh3aGljaCB5b3UgY2FsbCBkZXBlbmRzIG9uIHRoZSBwbG90dGluZyBzeXN0ZW0geW91IGZhdm9yLCBidXQgdGhhdCdzIGFub3RoZXIgbGVzc29uKSwgc28gdGhhdCB0aGUgcGxvdCBhcHBlYXJzIG9uIHRoZSBzY3JlZW4uIFRoZW4geW91IGFubm90YXRlIChhZGQgdG8pIHRoZSBwbG90IGlmIG5lY2Vzc2FyeS4NCg0KQXMgYW4gZXhhbXBsZSwgcnVuIHRoZSBSIGNvbW1hbmQgYHdpdGhgIHdpdGggMiBhcmd1bWVudHMuIFRoZSBmaXJzdCBpcyBhIGRhdGFzZXQsIGBmYWl0aGZ1bGAsIHdoaWNoIGNvbWVzIHdpdGggUiwgYW5kIHRoZSBzZWNvbmQgaXMgYSBjYWxsIHRvIHRoZSBiYXNlIHBsb3R0aW5nIGZ1bmN0aW9uIGBwbG90YC4gWW91ciBjYWxsIHRvIGBwbG90YCBzaG91bGQgaGF2ZSB0d28gYXJndW1lbnRzLCBgZXJ1cHRpb25zYCBhbmQgYHdhaXRpbmdgLiBUcnkgdGhpcyBub3cgdG8gc2VlIHdoYXQgaGFwcGVucy4NCg0KYGBge3J9DQp3aXRoKGZhaXRoZnVsLCBwbG90KGVydXB0aW9ucywgd2FpdGluZykpDQpgYGANCg0KU2VlIGhvdyBSIGNyZWF0ZWQgYSBzY2F0dGVycGxvdCBvbiB0aGUgc2NyZWVuIGZvciB5b3U/IFRoaXMgc2hvd3MgdGhhdCByZWxhdGlvbnNoaXAgYmV0d2VlbiBlcnVwdGlvbnMgb2YgdGhlIGdleXNlciBPbGQgRmFpdGhmdWwgYW5kIHdhaXRpbmcgdGltZS4gTm93IHVzZSB0aGUgUiBmdW5jdGlvbiBgdGl0bGVgIHdpdGggdGhlIGFyZ3VtZW50IGBtYWluYCBzZXQgZXF1YWwgdG8gdGhlIHN0cmluZyBgIk9sZCBGYWl0aGZ1bCBHZXlzZXIgZGF0YSJgLiBUaGlzIGlzIGFuIGFubm90YXRpb24gdG8gdGhlIHBsb3QuDQoNCmBgYHtyfQ0Kd2l0aChmYWl0aGZ1bCwgcGxvdChlcnVwdGlvbnMsIHdhaXRpbmcpKQ0KdGl0bGUobWFpbiA9ICJPbGQgRmFpdGhmdWwgR2V5c2VyIGRhdGEiKQ0KYGBgDQoNClNpbXBsZSwgcmlnaHQ/ICBOb3cgcnVuIHRoZSBjb21tYW5kIGBkZXYuY3VyKClgLiBUaGlzIHdpbGwgc2hvdyB5b3UgdGhlIGN1cnJlbnQgcGxvdHRpbmcgZGV2aWNlLCB0aGUgc2NyZWVuLg0KDQpgYGB7cn0NCmRldi5jdXIoKQ0KYGBgDQoNClRoZSBzZWNvbmQgd2F5IHRvIGNyZWF0ZSBhIHBsb3QgaXMgdG8gc2VuZCBpdCB0byBhIGZpbGUgZGV2aWNlLiBEZXBlbmRpbmcgb24gdGhlIHR5cGUgb2YgcGxvdCB5b3UncmUgbWFraW5nLCB5b3UgZXhwbGljaXRseSBsYXVuY2ggYSBncmFwaGljcyBkZXZpY2UsIGUuZy4sIGEgcGRmIGZpbGUuIFR5cGUgdGhlIGNvbW1hbmQgYHBkZihmaWxlPSJteXBsb3QucGRmIilgIHRvIGxhdW5jaCB0aGUgZmlsZSBkZXZpY2UuIFRoaXMgd2lsbCBjcmVhdGUgdGhlIHBkZiBmaWxlICpteXBsb3QucGRmKiBpbiB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5Lg0KDQpgYGB7cn0NCnBkZihmaWxlPSJteXBsb3QucGRmIikNCmBgYA0KDQpZb3UgdGhlbiBjYWxsIHRoZSBwbG90dGluZyBmdW5jdGlvbiAoaWYgeW91IGFyZSB1c2luZyBhIGZpbGUgZGV2aWNlLCBubyBwbG90IHdpbGwgYXBwZWFyIG9uIHRoZSBzY3JlZW4pLiBSdW4gdGhlIGB3aXRoYCBjb21tYW5kIGFnYWluIHRvIHBsb3QgdGhlIE9sZCBGYWl0aGZ1bCBkYXRhLiBVc2UgdGhlIHVwIGFycm93IGtleSB0byByZWNvdmVyIHRoZSBjb21tYW5kIGFuZCBzYXZlIHlvdXJzZWxmIHNvbWUgdHlwaW5nLg0KDQpgYGB7cn0NCndpdGgoZmFpdGhmdWwsIHBsb3QoZXJ1cHRpb25zLCB3YWl0aW5nKSkNCmBgYA0KDQpOb3cgcmVydW4gdGhlIGB0aXRsZWAgY29tbWFuZCBhbmQgYW5ub3RhdGUgdGhlIHBsb3QuIChVcCBhcnJvdyBrZXlzIGFyZSBncmVhdCEpDQoNCmBgYHtyfQ0Kd2l0aChmYWl0aGZ1bCwgcGxvdChlcnVwdGlvbnMsIHdhaXRpbmcpKQ0KdGl0bGUobWFpbiA9ICJPbGQgRmFpdGhmdWwgR2V5c2VyIGRhdGEiKQ0KYGBgDQoNCkZpbmFsbHksIHdoZW4gcGxvdHRpbmcgdG8gYSBmaWxlIGRldmljZSwgeW91IGhhdmUgdG8gY2xvc2UgdGhlIGRldmljZSB3aXRoIHRoZSBjb21tYW5kIGBkZXYub2ZmKClgLiBUaGlzIGlzIHZlcnkgaW1wb3J0YW50ISBEb24ndCBkbyBpdCB5ZXQsIHRob3VnaC4gQWZ0ZXIgY2xvc2luZywgeW91J2xsIGJlIGFibGUgdG8gdmlldyB0aGUgcGRmIGZpbGUgb24geW91ciBjb21wdXRlci4NCg0KVGhlcmUgYXJlIHR3byBiYXNpYyB0eXBlcyBvZiBmaWxlIGRldmljZXMsIHZlY3RvciBhbmQgYml0bWFwIGRldmljZXMuIFRoZXNlIHVzZSBkaWZmZXJlbnQgZm9ybWF0cyBhbmQgaGF2ZSBkaWZmZXJlbnQgY2hhcmFjdGVyaXN0aWNzLiAqKlZlY3RvcioqIGZvcm1hdHMgYXJlIGdvb2QgZm9yICpsaW5lIGRyYXdpbmdzIGFuZCBwbG90cyB3aXRoIHNvbGlkIGNvbG9ycyB1c2luZyBhIG1vZGVzdCBudW1iZXIgb2YgcG9pbnRzKiwgd2hpbGUgKipiaXRtYXAqKiBmb3JtYXRzIGFyZSBnb29kIGZvciAqcGxvdHMgd2l0aCBhIGxhcmdlIG51bWJlciBvZiBwb2ludHMsIG5hdHVyYWwgc2NlbmVzIG9yIHdlYi1iYXNlZCBwbG90cyouDQoNCjwvYnI+DQoNCldlJ2xsIG1lbnRpb24gNCBzcGVjaWZpYyB2ZWN0b3IgZm9ybWF0cy4gVGhlIGZpcnN0IGlzICoqcGRmKiosIHdoaWNoIHdlJ3ZlIGp1c3QgdXNlZCBpbiBvdXIgZXhhbXBsZS4gVGhpcyBpcyB1c2VmdWwgZm9yIGxpbmUtdHlwZSBncmFwaGljcyBhbmQgcGFwZXJzLiBJdCByZXNpemVzIHdlbGwsIGlzIHVzdWFsbHkgcG9ydGFibGUsIGJ1dCBpdCBpcyBub3QgZWZmaWNpZW50IGlmIGEgcGxvdCBoYXMgbWFueSBvYmplY3RzL3BvaW50cy4NCg0KVGhlIHNlY29uZCBpcyAqKnN2ZyoqIHdoaWNoIGlzIFhNTC1iYXNlZCwgc2NhbGFibGUgdmVjdG9yIGdyYXBoaWNzLiBUaGlzIHN1cHBvcnRzIGFuaW1hdGlvbiBhbmQgaW50ZXJhY3Rpdml0eSBhbmQgaXMgcG90ZW50aWFsbHkgdXNlZnVsIGZvciB3ZWItYmFzZWQgcGxvdHMuDQoNClRoZSBsYXN0IHR3byB2ZWN0b3IgZm9ybWF0cyBhcmUgYHdpbi5tZXRhZmlsZWAsIGEgV2luZG93cy1vbmx5IG1ldGFmaWxlIGZvcm1hdCwgYW5kIGBwb3N0c2NyaXB0IChwcylgLCBhbiBvbGRlciBmb3JtYXQgd2hpY2ggYWxzbyByZXNpemVzIHdlbGwsIGlzIHVzdWFsbHkgcG9ydGFibGUsIGFuZCBjYW4gYmUgdXNlZCB0byBjcmVhdGUgZW5jYXBzdWxhdGVkIHBvc3RzY3JpcHQgZmlsZXMuIFVuZm9ydHVuYXRlbHksIFdpbmRvd3Mgc3lzdGVtcyBvZnRlbiBkb27igJl0IGhhdmUgYSBwb3N0c2NyaXB0IHZpZXdlci4NCg0KPC9icj4NCg0KV2UnbGwgYWxzbyBtZW50aW9uIDQgZGlmZmVyZW50IGJpdG1hcCBmb3JtYXRzLiBUaGUgZmlyc3QgaXMgKipwbmcqKiAoUG9ydGFibGUgTmV0d29yayBHcmFwaGljcykgd2hpY2ggaXMgZ29vZCBmb3IgbGluZSBkcmF3aW5ncyBvciBpbWFnZXMgd2l0aCBzb2xpZCBjb2xvcnMuIEl0IHVzZXMgbG9zc2xlc3MgY29tcHJlc3Npb24gKGxpa2UgdGhlIG9sZCBHSUYgZm9ybWF0KSwgYW5kIG1vc3Qgd2ViIGJyb3dzZXJzIGNhbiByZWFkIHRoaXMgZm9ybWF0IG5hdGl2ZWx5LiBJbiBhZGRpdGlvbiwgcG5nIGlzIGdvb2QgZm9yIHBsb3RzIHdpdGggbWFueSBwb2ludHMsIGJ1dCBpdCBkb2VzIG5vdCByZXNpemUgd2VsbC4NCg0KSW4gY29udHJhc3QsICoqanBlZyoqIGZpbGVzIGFyZSBnb29kIGZvciBwaG90b2dyYXBocyBvciBuYXR1cmFsIHNjZW5lcy4gVGhleSB1c2UgbG9zc3kgY29tcHJlc3Npb24sIHNvIHRoZXkncmUgZ29vZCBmb3IgcGxvdHMgd2l0aCBtYW55IHBvaW50cy4gRmlsZXMgaW4ganBlZyBmb3JtYXQgZG9uJ3QgcmVzaXplIHdlbGwsIGJ1dCB0aGV5IGNhbiBiZSByZWFkIGJ5IGFsbW9zdCBhbnkgY29tcHV0ZXIgYW5kIGFueSB3ZWIgYnJvd3Nlci4gVGhleSdyZSBub3QgZ3JlYXQgZm9yIGxpbmUgZHJhd2luZ3MuDQoNClRoZSBsYXN0IHR3byBiaXRtYXAgZm9ybWF0cyBhcmUgKip0aWZmKiosIGFuIG9sZGVyIGxvc3NsZXNzIGNvbXByZXNzaW9uIG1ldGEtZm9ybWF0IGFuZCAqKmJtcCoqIHdoaWNoIGlzIGEgbmF0aXZlIFdpbmRvd3MgYml0bWFwcGVkIGZvcm1hdC4NCg0KQWx0aG91Z2ggaXQgaXMgcG9zc2libGUgdG8gb3BlbiBtdWx0aXBsZSBncmFwaGljcyBkZXZpY2VzIChzY3JlZW4sIGZpbGUsIG9yIGJvdGgpLCB3aGVuIHZpZXdpbmcgbXVsdGlwbGUgcGxvdHMgYXQgb25jZSwgcGxvdHRpbmcgY2FuIG9ubHkgb2NjdXIgb24gb25lIGdyYXBoaWNzIGRldmljZSBhdCBhIHRpbWUuDQoNClRoZSBjdXJyZW50bHkgYWN0aXZlIGdyYXBoaWNzIGRldmljZSBjYW4gYmUgZm91bmQgYnkgY2FsbGluZyBgZGV2LmN1cigpYC4gVHJ5IGl0IG5vdyB0byBzZWUgd2hhdCBudW1iZXIgaXMgYXNzaWduZWQgdG8geW91ciBwZGYgZGV2aWNlLg0KDQpgYGB7cn0NCndpdGgoZmFpdGhmdWwsIHBsb3QoZXJ1cHRpb25zLCB3YWl0aW5nKSkNCg0KZGV2LmN1cigpDQoNCiNOb3cgdXNlIGBkZXYub2ZmKClgIHRvIGNsb3NlIHRoZSBkZXZpY2UuDQoNCmRldi5vZmYoKQ0KDQojTm93IHJlcnVuIGBkZXYuY3VyKClgIHRvIHNlZSB3aGF0IGludGVnZXIgeW91ciBwbG90dGluZyB3aW5kb3cgaXMgYXNzaWduZWQuDQoNCmRldi5jdXIoKQ0KYGBgDQoNClRoZSBkZXZpY2UgaXMgYmFjayB0byB3aGF0IGl0IHdhcyB3aGVuIHlvdSBzdGFydGVkLiBBcyB5b3UgbWlnaHQgaGF2ZSBndWVzc2VkLCBldmVyeSBvcGVuIGdyYXBoaWNzIGRldmljZSBpcyBhc3NpZ25lZCBhbiBpbnRlZ2VyIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAyLiBZb3UgY2FuIGNoYW5nZSB0aGUgYWN0aXZlIGdyYXBoaWNzIGRldmljZSB3aXRoIGBkZXYuc2V0KDxpbnRlZ2VyPilgIHdoZXJlIDxpbnRlZ2VyPiBpcyB0aGUgbnVtYmVyIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ3JhcGhpY3MgZGV2aWNlIHlvdSB3YW50IHRvIHN3aXRjaCB0by4NCg0KPC9icj4NCg0KWW91IGNhbiBhbHNvIGNvcHkgYSBwbG90IGZyb20gb25lIGRldmljZSB0byBhbm90aGVyLiBUaGlzIGNhbiBzYXZlIHlvdSBzb21lIHRpbWUgYnV0IGJld2FyZSEgQ29weWluZyBhIHBsb3QgaXMgbm90IGFuIGV4YWN0IG9wZXJhdGlvbiwgc28gdGhlIHJlc3VsdCBtYXkgbm90IGJlIGlkZW50aWNhbCB0byB0aGUgb3JpZ2luYWwuIFIgcHJvdmlkZXMgc29tZSBmdW5jdGlvbnMgdG8gaGVscCB5b3UgZG8gdGhpcy4gVGhlIGZ1bmN0aW9uIGBkZXYuY29weWAgY29waWVzIGEgcGxvdCBmcm9tIG9uZSBkZXZpY2UgdG8gYW5vdGhlciwgYW5kIGBkZXYuY29weTJwZGZgIHNwZWNpZmljYWxseSBjb3BpZXMgYSBwbG90IHRvIGEgUERGIGZpbGUuDQoNCkp1c3QgZm9yIGZ1biwgcmVydW4gdGhlIHdpdGggY29tbWFuZCBhZ2FpbiwgYHdpdGgoZmFpdGhmdWwsIHBsb3QoZXJ1cHRpb25zLCB3YWl0aW5nKSlgLCB0byBwbG90IHRoZSBPbGQgRmFpdGhmdWwgZGF0YS4gVXNlIHRoZSB1cCBhcnJvdyBrZXkgdG8gcmVjb3ZlciB0aGUgY29tbWFuZCBpZiB5b3UgZG9uJ3QgZmVlbCBsaWtlIHR5cGluZy4NCg0KYGBge3J9DQp3aXRoKGZhaXRoZnVsLCBwbG90KGVydXB0aW9ucywgd2FpdGluZykpDQpgYGANCg0KTm93IHJlcnVuIHRoZSB0aXRsZSBjb21tYW5kLCBgdGl0bGUobWFpbiA9ICJPbGQgRmFpdGhmdWwgR2V5c2VyIGRhdGEiKWAsIHRvIGFubm90YXRlIHRoZSBwbG90LiAoVXAgYXJyb3cga2V5cyBhcmUgZ3JlYXQhKQ0KDQpgYGB7cn0NCndpdGgoZmFpdGhmdWwsIHBsb3QoZXJ1cHRpb25zLCB3YWl0aW5nKSkNCnRpdGxlKG1haW4gPSAiT2xkIEZhaXRoZnVsIEdleXNlciBkYXRhIikNCg0KI05vdyBydW4gYGRldi5jb3B5YCB3aXRoIHRoZSAyIGFyZ3VtZW50cy4gVGhlIGZpcnN0IGlzIGBwbmdgLCBhbmQgdGhlIHNlY29uZCBpcyBmaWxlIHNldCBlcXVhbCB0byBgImdleXNlcnBsb3QucG5nImAuIFRoaXMgd2lsbCBjb3B5IHlvdXIgc2NyZWVuIHBsb3QgdG8gYSBwbmcgZmlsZSBpbiB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5IHdoaWNoIHlvdSBjYW4gdmlldyBBRlRFUiB5b3UgY2xvc2UgdGhlIGRldmljZS4NCg0KZGV2LmNvcHkocG5nLCBmaWxlID0gImdleXNlcnBsb3QucG5nIikNCg0KI0Rvbid0IGZvcmdldCB0byBjbG9zZSB0aGUgUE5HIGRldmljZSEgRG8gaXQgTk9XISEhIFRoZW4geW91J2xsIGJlIGFibGUgdG8gdmlldyB0aGUgZmlsZS4NCg0KZGV2Lm9mZigpDQpgYGANCg0KDQpDb25ncmF0cyEgV2UgaG9wZSB5b3UgZm91bmQgdGhpcyBsZXNzb24gZGV2aWNlZCB3ZWxsIQ0KDQo8L2JyPg0KDQotLS0NCg0KPC9icj4NCg0KPGNlbnRlcj5FTkQ8L2NlbnRlcj4NCg0KPC9icj4NCg0KLS0t