I Did Imaging in 2009

|
76,000 people used my site last year, which is cool, even though that's only 6% more than 2008.  Visits were up 12%, the average user visited 1.5 times. Modest, but growth of a sort.

newzealand.pngSometimes I wonder how big the total 'market' is for a web site about medical imaging software, free or otherwise.  It's a bit daunting to look at the whole picture and try to work out how many radiology departments there are in the world, so sometimes I look at a smaller sample.  Last year, for instance, Google tells me I got 315 visits from New Zealand, a place I know reasonably well.  Australia had about 1,700 visits which is about right given the relative populations.  Google Stats gives you all sorts of useful information, such as I had strong growth in Wollongong, but  the radiologists in Hobart seem to be losing interest.  Guess I'll have to step up the Tasmanian marketing effort.  There are those who may argue that 'meaningful' statistics require larger samples than the number of frugalWollongongian radiologists, or readers of infrequently updated free imaging software blogs.  To them, I say, pshaw.
woolongong.png
Back to my example.  There are about 50-100 radiologists per million population, so New Zealand has say 300.  And for each of them let's say there are four others who might be interested in imaging - programmers, physicists, technologists, students.  So I'm going to define my New Zealand target market as 1,500 with a professional interest and who knows how many patients sent home with their scans on a DVD.  If I count only the pros and ignore the sent-homes, I'm getting about 20% of them to visit my site each year.  Not bad but I do want the remaining 80% to alexa.pngat least see how much great software is available.  And that, extrapolated world wide, would give me close to half a million unique visitors a year.  That might help me achieve one of my more modest goals: get a global site ranking with only one comma in it.


November Version Releases

|
vinci_head.pngVinci has another new version release.  I've mentioned this program before; it is a heavyweight neuro imaging program specializing in PET imaging, and is a leader in this field.  That said, it's a pretty narrow field, but it happens to be my field which is why I like this program so much.  Their release schedule is regular and substantial - for example, one 'maintenance' release a while ago was to expand their platform base to the Mac and Linux.  I see no reason why this program couldn't be used for non-neuro imaging and its feature list will keep the most demanding analyst busy for days.

huntington.jpg
Anatomist / BrainVISA is another major program in neuro image processing and analysis, though specializing in MRI this time.  It is a product of a consortium of French academic institutions and is frequently updated and well supported.  It's true open source and has been built on many operating systems, though prefers Linux.  I've not used this program, it's specialized and not in my particular field.  I will download and test it for a review, though, and I've admired their images, does that count?

radscaper.png
RadScaper is a Java applet-based image viewer from Divinev, and the recently released updates feature an attractive redesign along with technical improvements.  There are a couple of these around, but RadScaper is in continuous development and its capabilities have grown considerably.  There are obvious limitations to viewing images in a web browser rather than a stand-alone imaging application, but Radscaper can be run on just about any computer and requires no software installation at all.  The image files are supplied via straight HTML so there should be no issue in accessing the image server through a firewall or other security appliance.  

osirix_logo.jpg
Osirix has another of its regular updates released.  It's the program I almost love to hate, since it could be argued that it is the only DICOM program you need, which would make my site obsolete!  As a general purpose radiology workstation, or indeed for many specialized purposes, Osirix will do pretty much everything with DICOM files.  I use it all day long for imaging and PACS work, and I recommend it to colleagues.  If they are not currently Macintosh users, this program probably justifies purchasing a Mac.  Of course, it is limited to DICOM and is limited to Macintosh (it utilizes so many advanced Mac core technologies that porting it to another OS would mean redesigning it).  Try this program.

No image file for dcm4che, the comprehensive DICOM Java library and related applications, which has another update out.  This vast toolkit is all command-line business, specializing in PACS operations, networking, getting images from A to B with complete accuracy and great efficiency.  How hard core is it?  The 'che' is actually 'Che' as in Guevara - the developer was "inspired by the revolutionary nature of open source".  Some programs have a special place in my heart, but dcm4che has something even more special, a permanent place in my directory path.  All my machines (from 6 to 60 of them depending on how you count them) have /usr/local/dcm4che/bin hard coded in my path (even Windows machines, since I do most of my work at the Cygwin command line).  For me, a standard step in getting any machine to a minimal functional state is to install Java and then dcm4che.  In fact just today I was installing a WIndows 7 virtual machine (I run Parallels on the Mac), getting Java to install in C:\java, since the default 'Program Files (x86)' directory causes all sorts of issues in the path, what with all those spaces and parentheses.  dcm4che's sibling is dcm4chee (the 'e' is for 'Enterprise'), a powerful PACS server in Java that provides the core of my test lab.


Firefox Rules!

|
firefox.jpg
mozilla.jpgBy which of course I mean, it rules the ratings.  Though it could also be said to rule, because it is a really good browser and was the first real alternative to Internet Explorer, back in the days when it was called Mozilla.  I kind of miss the old logo and the spirit of rebelliousness that came with not running Internet Explorer back in those heady days.  Though if we're going to talk old web browsers I could hark back to 1993 and getting NCSA Mosaic for the first time...but I digress.

report_browser.pngSo, these ratings.  Here at I Do Imaging World HQ we (I) analyze the web logs on a regular schedule - given that I've done it twice,that is hard to disprove.  And when I looked at the web browser statistics I see that some time around July, Firefox because the most popular web browser used to access this site.  Of course, I credit my readers with being high achieving trend setters, so I don't know if this reflects the web use as a whole.  Still, I think it's a significant point in Web history.  Over the last two years, Internet Explorer has gone from almost 60% to just under 40% share, while Firefox has climbed from about 35% to just over 40%.  Safari and Opera have seen modest gains, from about 5% to about 8% each, with Chrome, which of course didn't exist two years ago, now at about the same level.

Any one of these is a perfectly good browser.  In the last year I've been using Internet Explorer occasionally and have found that the latest release is actually really good.  I've been using Firefox for so long that IE has caught up a lot.  I use all five of these on the PC, on the Mac I use Safari, Firefox and Opera, and on Linux I run Firefox and Opera.  I really like Opera, partly for their adherence to standards (though all browsers these days are pretty good about that), but also I like to stick up for the little guy.  And, I can't shake the idea that any software from Scandinavia is just plain cool.

report_os.pngOn the operating system side, things are a little less dramatic.  Most people still run Windows, though in two years this share has fallen from almost 90% to just over 80%.  The Mac has seen a steady rise, growing 50% in share from about 8% to about 12%.  Linux trucks along on the desktops of about 7% or so of the desktops of my readers.  For years and years I was among those hard-core souls, using a Solaris or Fedora machine as my primary workstation, but recently I've found little reason to use any machine other than my Mac Pro.  I still use it as a Unix workstation at the command line, but as far as my web stats are concerned, hello, I'm a Mac.


Mac OS 10.6 and Windows 7

|
Two new OS releases in the last month and I've installed them both.

My 10.6 / Snow Leopard Mac installations went smoothly though I've heard of friends who had issues during the installation.  I did a reformat and fresh install as I do every time I install a new OS, not that it's necessary but it's good to know where you stand.  Plus, it's an opportunity to look at what I have on the machine and how it's organized, and think about a better way to arrange things.  I reinstall all the applications either from the DVD or download.

The major issues I had with 10.6 were with Java incompatibilities.  I can't connect to our VPN at work, though this is partly due to the VPN server software not being upgraded.  Still, one would hope that changing versions of a language didn't break anything.  I had another problem with a commercial Java-based imaging application, though the latest update fixed this.  

Overall the changes in 10.6 have been minor.  The machine does boot faster though I don't often do this; the workstation stays on and the laptop goes to sleep between uses.  Programs perhaps load a bit faster.  I don't like the new Expose arrangement where all the mini windows are scaled to the same size, and arranged in a grid rather than in their approximate positions as used to be the case.  I've always thought that people remember sizes and locations well - such as looking back through a newspaper for an article you've read, and remembering about where on the page it was.  The new Expose behavior removes these visual cues.  Hopefully they'll make it an option to turn off the new look.

macintosh.jpg
Windows 7 was a bit harder to install.  Though I've had a Mac since 1985 I don't knock Windows, it's a good operating system.  Neither do I disparage Vista which I've been running since it came out, with no problems, and find it better in every way to XP.  I did have problems installing Windows 7 though.  I did a fresh install, which I consider essential when upgrading Windows.  In fact, once a year I reformat and reinstall, just to get rid of the detritus that has accumulated in the interim and is bogging the system down (this is one aspect of Windows I don't defend).  

In this case I had trouble getting the installation to start at all, the installer kept quitting.  Once I got the install running, it would proceed to the final stage then freeze at "Completing Installation".  I'd leave it there for an hour and nothing would happen.  This seems to be a common problem as there were lots of accounts of it in Google.  There were various suggestions to work around this problem:

  • Unplug USB devices
  • Disable USB in BIOS
  • Turn on SATA AHCI in BIOS
  • Reduce RAM to below 4 GB
  • Burn the installation DVD at lowest speed
  • Remove option cards
  • Upgrade BIOS

time-machine.jpg
Of these the consensus seemed to be that Windows 7 can't handle USB keyboards during installation, and you have to find and use a PS/2 keyboard.  What decade is this again?  Fortunately I have a Napolen Dynamite time machine and was able to go back to 1982 and find a PS/2 keyboard.  I don't know how people without a computer museum will cope.

Since each installation attempt was taking over an hour, I performed all the recommended hacks and left the installation running overnight.  Whether it was the 1980's keyboard or the leaving it for 12 hours, it eventually ground through the process.

On the surface, Windows 7 looks and behaves a lot like Vista.  It seems a little faster.  It has the same insanely complex file protection labyrinth and kept insisting that I, the sole user and installer of the computer, "do not have permission" to delete my own files.  And when I used Internet Explorer once, as I always do, to download Firefox, double-clicking on the file I just downloaded gives me the message "Windows cannot access the specified file.  You may not have the appropriate permissions".  I don't know why I defend Windows sometimes, I think it's more that I've lowered my expectations as to what it can do.

Tracked that problem down eventually.  I hadn't actually reformatted the disk as I should have, and while Windows put in a new copy of the Windows and Program Files directories, it kept my existing directories on C such as 'tmp' and 'cygwin', both of which I'd be using again.  But these directories now belong to an unknown user despite being in my home directory.  There is a very lengthy procedure I got through to reset the directorry ownership, and file permissions, and 'effective file permissions' because file permissions in Windows can mean almost anything, and whether this directory should inherit properties from its parents, and whether its subdirectories should inherit from it...and it gets more complex from there.  After messing with this for an hour I did what I should have done initially, plug in the 1982 keyboard, boot from DVD, and this time delete and recreate the disk partition to be sure all my old files are dead and buried.  I'm used to this sort of awfulness as a result of running Windows Server, but now it's made its way to desktop Windows.

Big Numbers in Perl

|
A simple numerical overflow had been causing an error in my code for ages, and I just found it.  The problem arose from using numbers greater than 2^32 in Perl. I've become so used to 64-bit systems that I'd forgotten to check for it.

I use powers of 2 to encode values such as file formats into a single numerical field in MySQL (which briefly was SunSQL and is now OracleSQL?).  So I have code that looks like:

our %cat_formats = (
  2**1  => ['DICOM'],
  2**2  => ['NEMA'],
  2**3  => ['Analyze'],

and so on, adding the numbers together gives me a unique value, encoding combinations of values, which I can store in a BIGINT field in MySQL.  This was fine while I was listing 32 file formats or less, but I now list 36.  The test I had been using for matching a format-encoding value against the stored MySQL value is something like this, if I were testing for a value of 2.

  $ret = (($readfmt * 1) & 2) ? 1 : 0;

I multiply the value by 1 to be sure it's in a numerical context, and I pedantically set the return value to 1 or 0 for consistency with cases where I might want to set it to something else. 

Problem was, this was returning true whenever the stored value was greater than 2^32, and I use the value 2^34 to denote NIFTI format.  So whenever I was testing for a value of 2 (denoting DICOM, common), I was returning true for any program that could read NIFTI format (somewhat rarer).  Which lead to the FSL program being listed as the second highest ranked DICOM viewing program.  Now FSL is a fine program, but sadly it cannot read DICOM.

All I had to do to fix it was enable big numbers, and all was well.

use bignum;

Conflicting Reports on IE Market Share

|
Internet Explorer 8 came out today, I've been using the beta a bit and it's actually pretty good.  I've never used IE routinely but as it renders pages differently from other browsers, I use it for compatibility testing.  Come to that, I use lots of Microsoft products, I don't disparage them just because they're Microsoft.  I do prefer alternatives though, if they do what I need.

So the news sites have the obligatory stories on IE's declining browser market share.  I came across this gem of misinformation on Wired, from Reuters: 

According to a recent survey by IT consultants Janco Associates Inc, Internet explorer has a 72.2 percent market share, ahead of the Mozilla Foundation's Firefox browser with 17.2 percent. Google Inc's new Chrome browser has only 2.8 percent of the market, while Apple Inc's Safari has less than 1 percent.

Not quite sure what they mean by 'recent', perhaps five years ago?  OK Chrome wasn't out then, but, still.  So I did a little survey of my own website stats going back to September 2007, when I switched to Google stats.

browser_share_sm.png
So in 2007, IE's share was just under 60%, now it's just under 50%.  Firefox is up from 32% to almost 40%, Safari and Opera are trucking along at 4-5% each (though some stats sites have Safari at 8-9%), and Chrome is 3% and growing.

I think it's safe to say my site does not attract a broad cross-section of society, which would explain why it leads the way in embracing the values of Anything But Microsoft.


Lots of Screen Captures

|
Recently I got around to another thing I've been meaning to do, which is to allow more than one screen capture per program.  I was getting pretty tired of seeing the same pictures, and plenty of programs have lots of sample images up on their web sites.  Part of the reason was laziness on my part, and part was poor software design.  I'm not sure which of these I feel better about.

The software design aspect was something that has bitten me before, and I haven't learned. 
prog_208_anatomist_0_200_197.jpg
 In my haste to get the screen captures feature implemented, I made 'screencap' a field of the 'program' table in the database.  This is easy: it only requires adding one field to the database and then remembering to extract the name of the screen capture image file when I retrieve the program's name, URL and so forth.  Of course, the limitation here is that there is only one field for a screen capture file so it doesn't scale nicely,  or at all.

So I went back in recently and as usual improving the design took no time at all.  I made a new database table called 'image', which will be used to store the details of all images.  There's a field in the table that links back to the 'program' table, so with one more MySQL call I can get all the screen captures that relate to a program.  I should have done it this way to start with.

Of course, once I started with the database table for the image files, new improvements suggested themselves.  The biggest gain is that I can now quickly pull up the exact size of an image and include this as part of the img tag in the HTML.  This should help the pages load faster as the browser now knows exact image sizes in advance, instead of having to load the images to determine their size.

prog_109_isosurf_0_109_200.jpg
The other improvement was to pre-calculate reduced size versions of each image capture file.  I use three sizes: full sized, for the popup screen captures, 320 pixel width for the pages of just screen caps, and 200 pixel width for the screen cap tooltip popup.  I have to admit that previously I'd been loading the entire image file even when it was just displayed at 320 pixel width.  With the reduced image files, the 320-width version can be 10 times smaller than the full size.  Needless to say I used PerlMagick, the Perl API to ImageMagick, as I have hundreds of image files to process and am not fond of doing things by hand (I characterize this as Actual Work whereas programming is more along the lines of recreation).  The image-creating program got a bit involved, as it has to check for database duplicates, come up with unique image file names and so forth.  But the gist of the work is done in just a few lines:

        $image->Scale(width  => $newwidth,
                      height => $newheight);
        $image->Composite(image   => $magimage,
                          compose => 'Atop',
                          gravity => 'SouthEast');
 
prog_276_mevis_3_320_236.jpg
The first bit does the scaling, obviously, and the second adds the little magnifying glass icon to the bottom right corner.  I'd pre-calculated this to be 40% transparent so it doesn't overpower the screen cap image.  Now that I've put the work into writing a program to create the reduced size image files, I can easily change their size or add a new size.  Should have done it this way the first time.

The screen caps on this page are largely gratuitous.  And they're all volume renderings because they just look good.  All the programs that do volume renderings do a lightbox view as well, but for the purposes of general illustration the volume renderings work well.  And I have plenty of images to use, I just added 170 so now have just over 300 screen caps.  I started with the most active programs and now slowly I'm working my way through all the programs, visiting their websites and capturing images (I'm up to 'D').  Programs that I have personally used often have a capture of my own MRI.



Icons Worth One Word Each

|
A month ago I added icons to most program names and listings, to show the platform the program runs on, and its user interface.  I used to have this information only listed on each program's page but I'd like to make it more obvious before you click on a program, what it runs on, and whether it's GUI or not.  I try not to use images where words can work, but words like 'Windows' take up a lot of horizontal space.

So this guy and its permutations are for the operating systems.  To get them to line up plat_win_mac_linux.png when stacked above each other in a table, I made all the constituent icons 16 pixels wide with a 1-pixel space either side.  So the 3-wide icon group is always 54 pixels wide.  The icons themselves I made up myself just by shrinking logos and then cleaning them up a bit with a graphics program.  I put them together along with 16-pixel wide transparent spacers using the amazing ImageMagick.  They're actually 50% transparent as with so many of them on a page, they were looking a bit overpowering, particularly the Apple icon. 

The interface icons are a bit less intuitive, and I debated whether to include them.  I have hover-text explanations on them so after reading that once or twice I hope it'll be interface_gui_cmd_lib.png clear what they mean (they are 'GUI', 'Command Line', and 'Library', in that order).  They're also 16 pixels wide; I got them from famfamfam's beautiful 'Silk' icon set.  Categorizing by interface probably isn't as important to a lot of users, particularly as most Windows programs are GUI, but for Linux (and hence Mac) power users, it's nice to be able to find the command line programs.  And for super users, programs that provide programming libraries or APIs are just wonderful.

The name of the icon group is systematic so I can create it in the CGI programs, the image files are named like plat_win_mac_linux.png for all 3 platforms as above, or plat__mac_.png for just Macintosh.   I put them into groups of 3 to avoid lots of little sub-tables, or tables with dozens of columns, and yet still get them nicely aligned horizontally.  They seem to load pretty quickly despite the front page having 68 of the platform and interface icons.  They're only about 2 kB each (ImageMagick is frugal with bytes) and the browser will cache them, so they each should only need to be loaded once. 

The tip text Javascript comes from Dynamic Web Coding's 'Tooltip' library.  This is a really nicely designed and implemented library with all sorts of features.  I felt guilty for not learning Javascript and doing it myself, but this passed in about 10 seconds.  This is a good library and I'm fine with licensing someone else's code.  I next want to incorporate their 'Scrolling Divs' library for the screen capture images.

February Updates

|
I've recently added a number of version updates after a delay of a month.  I was working on changing the data structures I use within the CGI programs, so that I could easily pass around more information about each program.  I want to include with the internal object I pass around, such peripheral information as the name of the screen capture and thumbnail image files, and their sizes.  That's done now, so I have caught up with some new versions, some of which are listed here.

 Vinci is a remarkable program from Stefan Vollmar and group at the Max Planck Institute for Neurological Research, in Cologne.  It is an extremely advanced analysis tool for neurological images, particularly PET.  I use this program daily and still am discovering functions and features I didn't know were in the program.  That said, it would also be possible to use it simply for image viewing; it handles a wide range of input formats, and also conversions.  In the area of functional analysis, it has few peers.

Loni Debabler is another huge program from the extremely prolific LONI group at UCLA.  It takes an ambitious and interesting approach to image file conversion, providing a specialized programming environment for reading, manipulating and writing image files.  This is all controlled through a graphical programming environment, and processing schemas are stored as XML files.  Sample conversion programs are provided for the most usual image formats, or you can develop your own.  This is a program I've not yet used as much as I want to, its internals are complex but it's tackling a difficult job.  I have to admit I've only used and modified the pre-programmed sample files.

PixelMed Java DICOM Toolkit is another advanced project, providing an extremely comprehensive implementation of DICOM tools.  It comes from David Clunie, a name familiar to everyone who has done any work at all in the field of DICOM programming.  This toolkit will provide more functionality than most people can utilize and comes from the foremost authority.  It is updated extremely frequently, such that version numbers are not used.  It's difficult to convey on my site how frequently it is released, as almost all other projects release versions on a monthly to annual basis.  This software is revised almost weekly.  Perhaps I should make it a 'sticky' at the top of the 'New Releases' list.

Another very comprehensive library, in C++ this time, is Imebra from Paolo Brandoli, of PuntoExe software.  Here is another true open source program, where the free version is identical to the commercial, and source code is provided in both cases.  This project has recently gained its own website (imebra.com), and related projects based on the library are at the Puntoexe website.

DP Tools, from Denis Ducreux, is another active program.  It specializes in the field of functional MRI and MR Diffusion.  I know nothing about this field but have seen an increasing amount of excellent software emerging.  It's written in Delphi, in common with some of Chris Rorden's very widely used imaging software.  I am also profoundly ignorant of Delphi, I seem to be exposing my weaknesses here.

ITK-SNAP is another specialized neuro program, this time for segmenting brain images.  It incorporates elements of the NLM Insight Segmentation and Registration Toolkit, hence the name.  Formerly developed at UNC-Chapel Hill and now at Penn, this project provides automatic and manual brain segmentation methods.  It's cross-platform.

TomoVision is a little program that displays DICOM images and doesn't do much else.  And, the free version is limited to 5 images.

MedImaView has a new version out.  It's another small DICOM viewer, when I tried it just now I could only open multiple files via drag and drop, and when I dropped a 192-frame MRI sequence I got: 192 windows.  Hmmm.



Sed Cleverness

|
I got sed to do something clever today, though sadly the cleverness was not mine.  I tried to solve the problem myself and although in the process I learned a great deal about sed, I had to resort to copying the answer.

I want to add Google Analytics code to my sister's website, which she's writing using iWeb.  Analytics is enabled by including in your HTML a javascript snippet that Google gives you.  iWeb does a really nice job, but you have to do things their way, and that means no javascript.  Fair enough, I guess, Apple want to be ensure that websites produced using their software will always work, and introducing a programming language pretty much ensures that things frequently won't work.

cyberduck.png
The website is hosted on a Linux server, not an Apple account, so to publish the site we export its contents to a directory, then FTP the directory contents to the server.  Initially we used Filezilla but it does not have incremental directory synchronization, so we switched to the awesome Cyberduck.

So my first thought was, well perhaps we can modify the HTML files before they leave her Mac.  There are a couple of approaches available, one is an iWeb add-on which looked more complex than needed, and you have to buy it.  Another was an Automator action you can download that will insert the Google javascript into the HTML files.  That sounded good but was one more action to perform, and I've never used Automator.

sedawk.gif
So I thought, I'll knock up a little script that the web server can run as an hourly cron job, and edit any HTML files that don't contain the Google code.  Ha!  Little script though it is, it took a while.  I got a lot of help from Bruce Barnett's sed guide, as I don't have a good shell book with me right now.  I should buy O'Reilly's 'Sed & Awk' book, a classic if ever there was one, and I believe may even have been their first ever book published. I remember it in print in the early 90's, and they even had a T shirt of the cover, which I dearly wish I'd bought.

The tricky part was, the Google code is supposed to be included immediately before the </body> tag in each HTML page.  Two problems: I couldn't be sure that the </body> tag would be on a line by itself, and sed file inclusion acts after the matched pattern, not before.

Problem 1 was addressed using a simple substitution with newlines:
sed -e '
s|<\/body>|\
&\
|

I used pipe-character delimiters.  The substitution is of the string </body>, and the newlines are inserted literally.  So the line-continuation backslashes continue the substitution pattern.  The ampersand is the matched string, so this substitution puts a newline before and after the </body> tag, to ensure it's on its own line.

Problem 2 was harder.  I didn't know about the file-insertion operator till today, though I figured that sed would have one.  It does, but it inserts after the matched pattern.  My initial approach to insert the file Google Analytics Javascript code, ga.js was:
sed -e '                                                                                       
/<\/body>/ {                                                                                       
r ga.js'
}   
But this inserted the file after the </body> tag, which wasn't allowed.  

Next thought was to take a two-way approach.  I'd print every line not matching the </body> pattern, and in a separate rule matching the </body> pattern, delete the pattern, insert the file, then print the pattern.
sed -e '
/<\/body>/ !{
p
}
/<\/body>/ {
r ga.js
d
p
}'                                                                                                 
Not to be.  The pattern matching quits at the delete as explained by Barnett, so the print command is never executed.

At this point after some hours of learning sed, I looked for an answer to inserting a file before a sed pattern, and found one.  At least by this point I knew enough to understand it (sort of).  This post by Tapani Tarvainen gave me a very succinct answer for the second pattern action:

/<\/body>/ {
r ga.js
' -e N -e '}'

OK I wouldn't have thought of that one.  As he explains,
 
The 'r' command actually outputs the file just before reading a new line to the pattern buffer (or at EOF). That can be forced in mid-script by 'n' or 'N', and while 'n' will also print the
buffer before 'r' does its thing.

He goes on to cover more general cases.  There is also another approach described in the same forum which employs use of the hold command, h, and the swap operator, x.

Having tested the code that does the file insertion, I put it into a shell script that finds all *.html files, checks to see if they have the GA code in them already (you're only allowed to put it in once), and if not, performs the insertion.

Next problem...the ISP's server doesn't offer cron!  I need this to run the sed script on the HTML files without having to ssh in to run it.  Aargh.  Neither can I execute an arbitrary command on the server using my FTP client.  I might try making a passwordless ssh script (using id_rsa.pub keys) and then see if I can get Cyberduck (FTP client) to run that after it performs the transfer.

That's enough for one day, though.  I learned a lot about sed, and a lot about how much I don't know.