Notebook

Short notes on various topics.


Graphics for manuscripts and presentations

July 5, 2009

Journals require graphics in specific file formats with sufficient resolution and font sizes. For example, the Geophysics Instructions to Authors) specifies:

EPS or TIFF file format.
300-600 dpi (dots per inch) for images, 600-1200 dpi for line art.
If color, then CMYK (not RGB).
8-pt sans-serif fonts for graphic text (e.g., axes labels)

First, which format should we use, EPS or TIFF? For reasons described below, my choice is often neither. Instead I use PNG images, and convert to TIFF only when necessary for publication.

The need for graphics in both manuscripts and presentations raises a second question. Can we use a single graphic in both? For graphics with text, the answer is no. Text in graphics for manuscripts will be too small for presentations. I show below how to compute the correct font size for graphic text.

Which format?

I like image formats. Scalable vector graphic formats like EPS, PDF, and SVG permit unlimited zooming without loss of resolution. In practice, however, no one needs unlimited zooming. A factor of 4 (400% zoom) is almost always sufficient. So we need only ensure that our images have sufficient resolution, not infinite resolution.

Moreover, EPS does not support partial transparency, and none of the vector formats EPS, PDF, or SVG support 3D graphics, such as those generated by OpenGL. So an image format may sometimes be the only option available.

Note that neither of the two formats EPS and TIFF required by Geophysics is supported by the program pdflatex. Instead, pdflatex supports JPEG, PNG and PDF formats. Among these three, I choose the PNG image format for most figures.

The widely used PNG format has lossless compression, honors partial transparency, and can easily be converted to TIFF as necessary for publication. In particular, for color figures, the RGB PNG format can be easily converted to the CMYK TIFF format required by Geophysics.

Image resolution and dimensions

The Mines Java Toolkit (JTK) package edu.mines.jtk.mosaic can save graphics in PNG format with arbitrary resolution. To facilitate zooming up to 400%, I save graphics in compressed PNG images with resolution 720 dpi.

So what figure dimensions - width and height - should we use? Many figures have a natural aspect ratio, so that the height depends on the width, or vice-versa. If we know one dimension, we know the other. For other figures, we may choose width and height independently.

In manuscripts, figure width is usually the limited dimension, because the width of a text column is less than its height. Geophysics allows figures with three different widths, specified in picas. Using 1 pica = 12 pt and 1 inch = 72 pt, these widths are:

1-column = 20 picas = 240 pt ~ 3.33 inches
4/3-column = 26 picas = 312 pt ~ 4.33 inches
2-column = 42 picas = 504 pt ~ 7.00 inches

The 2-column width is not specified in the Geophysics Instructions to Authors, but Geophysics does apparently accept 2-column figures, and they appear to be about 42 picas wide when printed. Both the 1-column and 2-column widths work well with LaTeX styles.

In presentations, figure height is typically more limited than width, because the slide width:height aspect ratio is 4:3 (or higher, for wide-screen formats) and because slides often have a title, which further limits the height available for graphics. Therefore, graphics that fit well in manuscripts may be too tall for slides in presentations. And while we can scale any graphics to fit on a slide, this scaling will always make graphic text too small.

Font size

As noted above, Geophysics requires 8-pt sans serif fonts for graphic text, such as axes labels. Legibility in presentations requires that the font size be at least 1/20 of slide height. These requirements are conflicting.

To see why, suppose that we make a 1-column figure with width 240 pt. If the figure height is also 240 pt, then the 8-pt font size is too small, because 8/240 = 1/30 is less than 1/20 of the graphic height, which cannot exceed the slide height.

The disparity is worse in slides with a title, where graphic height is significantly less than slide height. It is much worse for a two-column figure (again, assuming graphic height = width), for then font size is less than 8/504 = 1/63 of slide height.

The best case occurs when the aspect ratio of our graphic is exactly the 4:3 aspect ratio of a slide. In this case, the graphic height for a 1-column figure in geophysics is 240×3/4 = 180 pt, and the 8-pt font size is approximately 1/22 (~ 8/180) of slide height. By the 1/20 rule, the 8-pt font is almost legible. In fact, a 9-pt font would be perfect for this graphic.

But remember that this is the best case. If we need a title in our slide or change the aspect ratio of the graphic, making it either wider or taller, then the 8-pt font may become much too small for the slide.

Here is an example of the best case, where the graphic has the ideal 4:3 aspect ratio. In this example, the title is part of the graphic image.

A graphic with a font suitable for a one-column figure in a printed manuscript. In this best-case scenario, for a 4:3 aspect-ratio, the text is almost large enough for slides.
The same graphic with a slightly larger font that follows the 1/20 rule for slides.

In summary, we should not use the same graphic text for both printed manuscripts and presentation slides. If we do, then graphic text in slides will be too small.

Computing the font size

The Mines JTK creates graphics in on-screen windows, and includes classes with methods to save them in PNG files with higher resolution. It also provides methods that enable the font size to be specified explicitly or computed automatically for either printed figures or slides.

Windows for on-screen graphics can be resized, so that both the width and height of a graphic can be changed interactively. But for any graphic width, it is easy to compute the font size for a figure in a printed manuscript. That is,


fontSizeGraphic = fontSizePrint*widthGraphic/widthPrint

For a 1-column figure in Geophysics, fontSizePrint = 8 pt and widthPrint = 240 pt.

For slides, the computation of font size is more complex, in part because not all of the slide width or height may be available for our graphic. Remember that some space may be required for a title or other elements, or we may want to put two graphics on the same slide. So we first introduce two parameters:

widthFraction = fraction of slide width available
heightFraction = fraction of slide height available

We then compute the font size for our graphic window as follows:


widthAvailable = 4*widthFraction
heightAvailable = 3*heightFraction
if widthGraphic*heightAvailable > heightGraphic*widthAvailable:
  heightScale = (heightGraphic*widthAvailable) /
                (widthGraphic*heightAvailable)
else:
  heightScale = 1
fontSizeGraphic = heightGraphic/heightFraction/heightScale/20

The importance of heightScale in this calculation is not obvious. The purpose of this scale factor is to account for the decreased height of a graphic placed on a slide when the width:height ratio of the graphic exceeds that of the space available on the slide.

The complexity of the font size calculation above contributes to the problem of making slides with legible text. I work with folks who all know when text on a slide is too small, but most of them would solve the problem by trial and error. Or they might be safe and always use fonts that are too large. But this simple solution wastes space that might be better used for other content. For example, axes may be necessary in a display of a seismic image, but are usually less important than the image itself.

Indeed, our desire to reserve space for the most meaningful content is the reason that Geophysics specifies a small 8-pt font for text in figures. But, as noted above, this font size is too small for slides used in presentations.

The calculation of font size for slides is tedious without a computer, and for this reason the class edu.mines.jtk.mosaic.PlotFrame in the Mines JTK will optionally compute the font size for a slide (or printed figure) automatically. With this option, as we grow or shrink the window for an on-screen graphic, the font size grows or shrinks accordingly.

Making slides and figures (for Mac users)

Given a 720-dpi PNG image with correct font sizes, we must often annotate this graphic by adding additional text, arrows, boxes, and so on. We may also need to create a composite of two or more graphics. I use Apple's Keynote presentation software for Macs to do this.

When making a slide in Keynote, I simply drag a PNG image onto the slide. For presentations I use the default 1024×768 slide size, and so must scale my high-resolution PNG images to fit the space available. I accounted for this scaling in the calculation of font size above, so that any text in the graphic will be legible when presented. I then annotate the graphic using Keynote's drawing tools and, for mathematical symbols and equations, the freely available program LaTeXiT.

Because creating slides for presentations is a visual process, I find that using KeyNote and LaTeXiT in this way is usually more efficient than using the Beamer class with LaTeX. For presentations at technical conferences, I export my KeyNote slides in PDF format.

I also use Keynote when making figures for printed manuscripts. For this purpose, I specify custom slide sizes that conform to print column widths:

1-column = 240 pt = 1200 pixels
4/3-column = 320 pt = 1560 pixels
2-column = 504 pt = 2520 pixels

The Keynote widths in pixels correspond to a resolution of 360 dpi, which is sufficient for precise editing, but half the 720-dpi in our images. That's OK, because Keynote retains the original images, and will preserve their 720-dpi resolution when exporting to a PDF file.

I do not use 720 dpi in Keynote, because the maximum size of a Keynote slide is 4000×4000 pixels. A 2-column figure at 720 dpi is 5040 pixels wide, too wide for Keynote. Also, at 720 dpi, the height of a 1-column figure could easily exceed 4000 pixels. Therefore, I use 360 dpi when annotating print figures in Keynote.

When using Keynote to add text to my figures, I select a font size of 40 pt, because 40 = 8*1200/240 = 8*1560/320 = 8*2520/504. In this way, text that I add to a figure with Keynote is the same size as that in the graphic created with the Mines JTK.

Exporting from Keynote to a PDF preserves the high resolution of any text or other annotation that I add to a figure, as well as the 720-dpi resolution of the graphic images. When I inspect the PDF file using Apple's Preview application, it will have a resolution of 72 dpi, and a large width in inches; e.g., 16.67 inches = 1200/72 for a 1-column figure.

In Apple's Preview (included with Mac OS X), we can save any PDF page as a TIFF (or PNG or JPEG) image with a resolution of 720 dpi. If necessary, with Preview we may also crop the image and, for a color image, convert (match) its RGB color profile to a CMYK color profile.

Apple's support for PDF in Preview is wonderful, but the conversion from PDF to TIFF can be tedious when repeated often as we prepare manuscripts. Therefore, I use a small Python program that exploits Mac OS X services to automate the conversion from PDF to PNG, JPEG, or TIFF.

When preparing drafts, I use low-quality JPEG images, which at 720 dpi, still look sharp, but require far less space than PNG images. Because CMYK TIFF images can be huge, even when compressed, and because pdflatex does not handle TIFF, I use this format only when submitting final figures for a journal like Geophysics.

What's it like to be in geophysics?

January 26, 2008

Dan Shannon is a student-athlete at Grandview Heights High School in Columbus, Ohio. Dan recently asked me some thought-provoking questions:

What do you want your students to get the most out of what you teach (concerning geophysics)?

Most of our students enjoy thinking analytically; they think physics, math, and computer science are fun. I want them to learn how to extend and apply what they already enjoy to design and implement new technology for geophysical exploration, which can be even more fun. In other words, I want my students to develop skills that will enable them to enjoy their work so much that it becomes play, something they might do for only room and board; but they won't because their skills are both rare and valuable.

How do you believe the continued study of geophysics affects the world?

Geophysics enables us to see and better understand the earth's interior. Our ability to do this has many applications. Some geophysicists explore for resources (oil, gas, water, minerals, ...), unexploded ordinance, aging infrastructure in urban areas, ancient civilizations, sites for nuclear waste and CO2 sequestration, and so on. Other geophysicists look much deeper and try to understand geologic processes and forces that cause earthquakes. Or they might use seismic waves generated by earthquakes to better image the earth's core and mantle. This list is far from complete. I should at least mention other planets, and similarities between geophysical and medical imaging. But these are some of the applications of geophysics that have worldwide importance.

What are the unique aspects of geophysical engineering?

The applications described above are rather unique. And perhaps the difference between science and engineering is less well-defined in geophysics. But beyond that, geophysical engineering is much like other engineering fields. For example, I used to think that geophysicists have more opportunities to travel abroad, to see the world. But I have learned by talking with Mines graduates in other engineering fields that many have such opportunities today.

How do the working conditions compare to other jobs; are they indoors, outdoors, both?

Geophysicists work both indoors and/or outdoors. In my geophysical career, I have worked outside covered in drilling mud and inside programming some of the world's fastest supercomputers. Never at the same time, of course, and more of the latter.

What skills can/need to be integrated with geophysical engineering in order to be successful?

In addition to geology and physics (clearly!), successful geophysicists are likely to be skilled in mathematics, computer science, and to a lesser extent chemistry. When I ask my colleagues what subject they wish they had studied more while in school, most of them say math, because that one seems to be most difficult to pick up on the job while solving geophysical problems.

How interpersonal is the study of geophysics?

Probably no more or less so than any other scientific or engineering discipline. But few geophysicists work alone, and many today work in teams with other geoscientists and engineers.

What opportunities does geophysical engineering offer, while in school, that other areas of study do not offer?

The opportunity to learn how mathematics, physics, computer science and geology can all be woven together to do amazing things. Our students tend to be those who enjoy putting these subjects together. Opportunities to work both outdoors, acquiring geophysical data, and indoors, developing and using computer software that analyzes those data, may also be unusual. An example of this is our four-week summer field session, which our students seem to especially enjoy, relative to other students at Mines.

What compels you to be involved in geophysics?

I am more compelled to design and build computer programs, software machines that can be wonderful combinations of art and engineering. Geophysics just happens to provide some of the most challenging computational problems and opportunities. With that interest in computing and an education in physics, I more or less stumbled into geophysics.

What does an ordinary day of work involve?

This varies quite a lot from day to day, but typically includes one or more of the following activities: preparing and teaching classes, working with students, working with colleagues, analytical work for research, writing computer software, writing prose, responding to email, and so on.

What does an extraordinary day of work involve?

A breakthrough in any of the activities listed above followed by a workout with the Mines varsity swimming team with some favorite music running in my brain. So what is a breakthrough? For me that could be working with a student to find a simple and elegant solution to an analytical or computational problem. Or perhaps it is when I am stuck with a programming error while lecturing in a computer science class, and everyone becomes very still (because this rarely happens), and then a student finds the error before I do. Such days are extraordinary.

Tiny displacements in time-lapse seismic images

January 24, 2007

In time-lapse seismic imaging, we often observe displacements of features in images recorded at different times. After accounting for changes in data acquisition, these displacements can be related to compaction of reservoir rocks as fluids are produced from them. We call these displacements apparent shifts because they may be more directly related to changes in seismic wave velocity outside the reservoir than to physical movements of reservoir boundaries.

One of the two seismic images we cross-correlated to detect tiny displacement vectors, one for each image sample.

Today, we typically measure only vertical apparent shifts, for two reasons. First, the force of gravity leads us to expect vertical shifts to be larger than horizontal shifts. Second, it is easier to measure shifts perpendicular to image features than to measure shifts parallel to those features.

The second problem is illustrated in the figure below, which shows 2-D cross-correlations of local Gaussian windows of two seismic images. The correlation peaks are well resolved vertically, but poorly resolved horizontally. Because the locations of the peaks correspond to the apparent shifts we seek to estimate, horizontal components of those shifts are poorly resolved.

Local cross-correlations (normalized). This is is a small subset of the correlations that we compute for every image sample. Note the small vertical shifts of some correlation peaks. Horizontal shifts are more difficult to see.

We say "vertical" and "horizontal", when what we really mean is "perpendicular" and "parallel" to features in our images. If those features were dipping at an angle of 45 degrees, then resolution would be equally poor in both horizontal and vertical directions.

Ideally the peaks of our cross-correlations would be isotropic, with roughly the same resolution in all directions, as in the figure below. The processing used here is an example of adapting techniques from general image processing to solve specific problems in seismic imaging. Here we computed so-called phase correlations, and our adaptation is to do this in a seamless way for every sample in our images.

Local phase correlations (normalized). Again, a small subset of the correlations that we compute for every image sample. Both vertical and horizontal components of shifts can be accurately estimated from the locations of peaks of these phase correlations.

Using phase correlations, we can reliably estimate both vertical and horizontal shifts in time-lapse seismic images with sub-pixel precision. In one example, we have used phase correlations to observe horizontal apparent shifts of about five meters in 3-D images sampled with twenty-five meter trace spacings; and these small sub-sample shifts are correlated with the geometry of the target reservoir.

Our problem now is to analyze these apparent shift vectors, to better understand how they are related to changes within and above producing reservoirs.

Parallel loops with atomic integers

July 29, 2006

A computer you buy today is likely to have multiple cores. A "core" is a CPU that may coexist with other CPUs within a single microprocessor. For example, if you have a dual-processor system with dual-core processors, then you really have a quad-core system, one with essentially four CPUs.

Systems like these are becoming commonplace, because CPUs are not getting faster as they once did. Instead, we are getting more CPUs in a single package.

To take advantage of multi-core computers, we might simply run multiple applications simultaneously. But this solution may be impractical. Sometimes we need a single software application to run faster. In this case, we need to get multiple processors working simultaneously on the same problem within a single application.

Our current situation is summarized well by Herb Sutter, in The Free Lunch is Over: A Fundamental Turn Toward Concurrency in Software (2005, Dr. Dobb's Journal, v. 30, n. 3).

An example

Scientific computing often has outer loops with iterations that can be performed independently and concurrently. For example, when computing a matrix product C = A×B, we might compute each column of the matrix C independently. Here is some Java code that computes the j'th column of C:


static void computeColumn(
  int j, float[][] a, float[][] b, float[][] c) 
{
  int ni = c.length;
  int nk = b.length;
  for (int i=0; i<ni; ++i) {
    float cij = 0.0f;
    for (int k=0; k<nk; ++k)
      cij += a[i][k]*b[k][j];
    c[i][j] = cij;
  }
}

We usually optimize this code by mixing and unrolling these loops, but those optimizations are not relevant here.

To compute the matrix product C, we need only an outer loop over its columns:


int nj = c[0].length;
for (int j=0; j<nj; ++j)
  computeColumn(j,a,b,c);

The problem with this single-threaded program is that it will not run any faster on a quad-core system than it would on a single-core system. Three CPUs may be idle while one does all the work.

Multi-threading

To use all four cores concurrently in a single program, we need multiple threads. We could write the outer loop like this:


int nthread = 4;
final int nj = c[0].length;
Thread[] threads = new Thread[nthread];
for (int ithread=0; ithread<nthread; ++ithread) {
  threads[ithread] = new Thread(new Runnable() {
    public void run() {
      for (int j=0; j<nj; ++j)
        computeColumn(j,a,b,c);
    }
  });
}
startAndJoin(threads);

The last statement calls a utility method that simply starts and then joins all of the threads in the specified array of threads. This is easy enough with Java's standard classes Thread and Runnable.

But this multi-threaded program is no faster! Each thread maintains it's own loop index j and will simply duplicate the work of the other three threads. All four cores will be busy (good) doing the same work (bad).

Chunky multi-threading

We want different threads to compute different columns. But which columns do we assign to each thread? We could simply divide our outer loop into four chunks, so that each of the four threads computes one fourth of the columns:


int nthread = 4;
int nj = c[0].length;
int mj = 1+nj/nthread;
Thread[] threads = new Thread[nthread];
for (int ithread=0; ithread<nthread; ++ithread) {
  final int jfirst = ithread*mj;
  final int jlast = min(jfirst+mj,nj);
  threads[ithread] = new Thread(new Runnable() {
    public void run() {
      for (int j=jfirst; j<jlast; ++j)
        computeColumn(j,a,b,c);
    }
  });
}
startAndJoin(threads);

This program is better, but is efficient only when all four threads get equal access to the four CPUs. That seldom happens. Threads that finish computing their chunk of columns simply stop working. They do not help other threads complete their chunks. (Have you ever worked with a group like this?) This program is only as fast as its slowest thread.

An atomic outer loop index

A more efficient solution is to have all four threads keep working until all columns have been computed. (No one stops working until the job is done.) Let's have each thread compute the next column not already computed or being computed. We do that by letting all four threads share a single outer loop index, using the standard Java class AtomicInteger:


int nthread = 4;
final int nj = c[0].length;
final AtomicInteger aj = new AtomicInteger();
Thread[] threads = new Thread[nthread];
for (int ithread=0; ithread<nthread; ++ithread) {
  threads[ithread] = new Thread(new Runnable() {
    public void run() {
      for (int j=aj.getAndIncrement(); j<nj; 
               j=aj.getAndIncrement())
        computeColumn(j,a,b,c);
    }
  });
}
startAndJoin(threads);

The AtomicInteger aj holds the shared outer loop index that all threads get and increment. The name AtomicInteger implies that this get-and-increment is an indivisible atomic operation, one that cannot be interrupted or corrupted by another thread doing the same thing.

With this program, our four threads need not perform an equal amount of work, and all threads continue to run until all of the columns are computed. On an otherwise quiet quad-core system, this program runs approximately four times faster than the single-threaded version.

Moreover, on a single-core system this program is almost as fast as the single-threaded version. For large matrices, the extra computation required to launch multiple threads and get-and-increment an AtomicInteger is negligible. For small matrices, we might apply the same technique to some other more outer loop.