Archive | code RSS for this section

Install Julia on Cygwin — use minGW

The Julia language is interesting — interactive yet fast, apparently. Here is installing from source on Cygwin.

$ git clone https://github.com/JuliaLang/julia.git

(around 170 MB)

Used setup-XXX.exe or apt-cyg to install dependencies; I had to add patch. Then:

$ cd julia
$ make

... some output to screen ...

Makefile:242: *** can't find lib.dll. Stop.

No luck. I noticed that the install looks for minGW compilers, so I tried installing the mingw toolchain, including the minGW Fortran 7.4 packages. Here are the minGW pakages I installed:

$ apt-cyg list mingw
mingw64-i686-binutils
mingw64-i686-gcc-core
mingw64-i686-gcc-fortran
mingw64-i686-gcc-g++
mingw64-i686-headers
mingw64-i686-runtime
mingw64-i686-windows-default-manifest
mingw64-i686-winpthreads
mingw64-x86_64-binutils
mingw64-x86_64-gcc-core
mingw64-x86_64-gcc-fortran
mingw64-x86_64-gcc-g++
mingw64-x86_64-headers
mingw64-x86_64-runtime
mingw64-x86_64-windows-default-manifest
mingw64-x86_64-winpthreads

I don’t know if all these are needed — I doubt it (probably don’t need the i686 toolchain) — but I’m not looking for a minimal solution, just one that works, so I hit it with everything. Then:

$ make clean
$ make
$ make install

Note that the make-ing includes some downloading of extra material — so ought to be online while doing it.

$ grep http Makefile
	@echo 10. Upload to AWS, update https://julialang.org/downloads and http://status.julialang.org/stable links
	$(JLDOWNLOAD) https://sourceforge.net/projects/sevenzip/files/7-Zip/19.00/7z1900.exe && \
	../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_Leap_42.2 \
	$(JLDOWNLOAD) https://downloads.sourceforge.net/project/sevenzip/7-Zip/19.00/7z1900-x64.exe && \
	../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_Leap_42.2 \
	$(JLDOWNLOAD) https://sourceforge.net/projects/nsis/files/NSIS%203/3.04/nsis-3.04-setup.exe && \

Anyway, that seemed to work! The install did not put Julia in the path. Probably I needed to give it a prefix when running make. (Or I can just use it from here, or add the path to the julia.bat file to the path, or make a link, or … Anyway, that is left as an exercise for the reader.)

screenshot showing a simple interactive julia session

Julia in MATE-terminal on Cygwin


Or, since Cygwin runs on Windows, you could just install the Windows native package. Much easier!

Much easier.

The ZMC page from RSC

My ZMC software used to be (might still be) hosted on the computers at ANU (http://rsc.anu.edu.au/~goossens/ZMC.html). But I don’t know how long that will last!

Therefore, this is a copy of that page, with the files linked to the RSC for now. If the links don’t work, let me know. Could also try here.

Overview

Conventional crystal structure refinement and solution relies on an analysis of the Bragg peaks, the sharp, well-defined scattering in a diffraction pattern. In doing this, the structure can be considered as an array of identical unit cells, and this reduces the ‘solution’ of the crystal structure to the determination of the unit cell contents.

In a disordered material, while the average unit cell does indeed obey the space group symmetry of the crystal structure, such that solving the asymmetric unit within the cell ‘solves’ the structure, this is not the case for a disordered material — or even for what would generally be considered as an ordered material if considering instantaneous molecular and atomic motions.

Even an ordered crystal will show thermally induced vibrations of the atoms. If we could ‘freeze’ the crystal and look at the atoms, we would find that the space group symmetry is not obeyed. It is obeyed on average. In a disordered material it could be that the average occupation of a given site is 50% one type of atom and 50% another, in which case no site obeys the average symmetry.

What does this mean for analysis of diffuse scattering? It means that you can no longer consider all unit cells as identical. It means that you have to now work with an ensemble of unit cells big enough that averaging across it recovers the average and big enough that it can contain a statistically valid population of the local (short-range order) structures present in the crystal.

This means that analysis of diffuse scattering requires different tools from analysis of conventional Bragg scattering. ZMC is an attempt at a program to allow relatively ready implementation of a simulation of diffuse scattering from (particularly but not solely) molecular crystals. Eric Chan has prepared this flyer to show some of the details of the program, and I am very grateful to him. Further, he has developed a tutorial, available here, and it is really worth a look. His webpage is at https://sites.google.com/site/echanj/ and contains modified ZMC versions that can do some great stuff, including modulated structures. He has also done some work on a graphical interface! He’s an amazing guy.

Obtaining ZMC

ZMC is alpha software at best, and always will be; nothing about its performance is guaranteed nor promised. The code and binaries are licensed under the Academic Free License version 3.0; details in the files DISCLAIMER.txt and COPYRIGHT.txt (http://opensource.org/licenses/AFL-3.0).

Here is a bundle of statically-linked binaries for Linux, from April 2016 — the real current version:

Static binaries for Linux.

Here is a bundle of statically-linked binaries for Windows (compiled using g95 on Win 7; I don’t even know if it is 32 or 64 bit), from April 2016 — the real current version, but not much tested:

Static binaries for Win.

Here is the current source code plus a simple Linux compile script — package has transitioned to gfortran, and all the most important binaries seem to work (thanks to Aidan Heerdegen as always):

Source.

Refer to the older packages below for documentation, examples, and so on. Please also refer to this article and its associated deposited material, because it provides a complete working simulation.

Please note that this article was specifically published as Open Access in order to allow for anyone to make use of it.


Here are packages, older versions compiled for different systems. Comments about g95 are not current.

Despite my better judgement, I am putting it up here for download. You can download the current 2014 ZMC in the following formats:
Windows
Linux
Mac OS X
source.

The README file for Windows is here. Be aware that there are many versions of Linux (and OS X is not known for its long term user support or version-to-version compatibility), so your best bet might well be to contact me about the source code. If you can get g95 working (www.g95.org, version 0.92 I suggest) then the compile is pretty trivial (he says hopefully…).


While ZMC is relatively straightforward to use, and a great deal of work has been undertaken to give it a usable (if text file-based) interface, it is not yet ‘production’ software (and never will be). It is written in Fortran90 and uses a module library developed by Dr Aidan Heerdegen, and some components of the system have not been tested on various combinations of hardware and operating system. Currently, As of 2014, binaries exist for g95 on Intel Macintosh (Mac OS X 10.6), Intel Fortran Compiler on Debian stable on Intel i7 (ie, most Intel-compatible) and Windows xp, and that is about it. So far, once the modules are ported, the main program seems to compile without problems, but I am not in a position to make a general distribution.

Further, there is no comprehensive manual, though it comes with an in-progress version of what will one day, time permitting, be a manual (unlikely). The program contains some basic help options, and the distribution packages contain a (simple) simulation that should work out of the box, and the adumbral manual contains some code that might be useful also.

Some things to note: ZMC is essentially a program for displacive relaxation/equilibration of the model crystal. Any occupancy ordering needs to be done externally. The software needs a suite of toolbox programs, which also need to be bundled with any distribution. These include programs for working with crystal geometry, calculating diffraction patterns (DIFFUSE, Butler, B. D. & Welberry, T. R. (1992). J. Appl. Cryst. 25, 391–399), performing any occupancy simulations and so on.

References

ZMC is used and the method described in the following publications, amongst others. Apologies for the rough layout.

E.J. Chan and D. J. Goossens, ‘A method to perform modulated structure studies using the program ZMC’, J. Appl. Cryst., 2017 50 1834–1843.

This article and its associated deposited material contain a working simulation with occupancy and displacive elements — a good place to start: ‘A Process for Modelling Diffuse Scattering from Disordered Molecular Crystals, Illustrated by Application to Monoclinic 9-Chloro-10-methylanthracene’, Advances in Condensed Matter Physics, 2015 (2015), Article ID 878463, 7 pages, DOI: http://dx.doi.org/10.1155/2015/878463

D.J.Goossens, A.P.Heerdegen, E.J.Chan and T.R.Welberry, ‘Monte Carlo Modelling of Diffuse Scattering from Single Crystals: The Program ZMC‘, Metallurgical and Materials Transactions A, 42A (2011) 23-31. DOI: 10.1007/s11661-010-0199-1.
(PDF)

D.J.Goossens and T.R.Welberry, ‘Diffuse Scattering from Molecular Crystals’, chapter in Diffuse Scattering and the Fundamental Properties of Materials, edited by Rozaliya I. Barabash, Gene E. Ice and Patrice E.A. Turchi. Momentum Press, 2009. Print ISBN: 978-1-60650-000-2. E-book ISBN: 978-1-60650-002-6

E.J.Chan, T.R.Welberry, D.J.Goossens, A.P.Heerdegen, A.G.Beasley and P.J.Chupas, ‘Single-crystal diffuse scattering studies on polymorphs of molecular crystals. I. The room-temperature polymorphs of the drug benzocaine’, Acta Cryst. B65 (2009) 382-392.

D.J.Goossens, A.G.Beasley, T.R.Welberry, M. J. Gutmann and R.O.Piltz, ‘Neutron diffuse scattering in deuterated para-terphenyl, C18D14‘, J. Phys.: Condens. Matt., 21 (2009) 124204.

D.J.Goossens and M.J.Gutmann, ‘Revealing how interactions lead to ordering in para-terphenyl’, Physical Review Letters, 102 (2009) 015505-1-4.

D.J.Goossens, A.P.Heerdegen, T.R.Welberry and A.G.Beasley, ‘The Molecular Conformation of Ibuprofen, C13H18O2, Through X-ray Diffuse Scattering’, International Journal of Pharmaceutics 343 (2007) 59-68.

D.J.Goossens, T.R.Welberry, A.P. Heerdegen and M.J. Gutmann, ‘Simultaneous Fitting of X-ray and Neutron Diffuse Scattering Data’, Acta Crystallographica A A63 (2007) 30-35.

————————-
Updated May 12, 2016
————————-

xFig convert all

xFig is hardly cutting edge any more, but it has some useful advantages; .fig files can be edited in a text editor, and much more readily than eps files, and fig2dev can output a whole bunch of other formats and can be run on the command line.

This is just a ‘note to self’ giving a little script that converts all the fig files into other formats ready for insertion into web pages or  documents. It generates eps, emf and svg files and puts them into appropriate directories, creating the directories if need be.

Can add any number of conversion targets to the list, but bitmap ones (png etc) generally need options to ensure the resolution is good enough. That precludes putting them inside the inner loop. The png example shows how this works. I have magnified it by 4, which, when the image is shrunk back to original size, has the effect of quadrupling the pixels per inch relative to the default. The default is low — a screen resolution, so something like 96 ppi.

$ cat convert_all.sh
for f in *.fig
do
  prename=`basename $f .fig`
# Vector formats don't need custom arguments
  for extn in eps emf svg
  do
    mkdir -p $extn
    echo "fig2dev -L $extn $f > $extn/$prename.$extn"
    fig2dev -L $extn $f > $extn/$prename.$extn
  done
# Bitmap formats need custom arguments
  mkdir -p png
  echo "fig2dev -L png -m 4 $f > png/$prename.png"
  fig2dev -L png -m 4 $f > png/$prename.png
done

Just run it in the folder where the files are.

 

fig2devilish

Windows path to Mac/Linux path

I work in a place that uses Macs and Windows machines, plus I use Cygwin. We collaborate on documents that live on a server. The windows machines map the server to G:, the Mac machines go to ‘groups’.

w2m.bat

This takes a Windows G: path and converts it to one for a Mac so I can send a colleague an email saying ‘file is at groups/xxx/xxx/’ and they can get at it readily.

@echo off
echo %1 | sed "s/\\/\//g" | sed "s/G:/groups/g"

It uses sed to first replace backslashes with forward (recalling that slashes need to be escaped and the escape character is the backslash … makes for a funny looking command). Second sed just replaces ‘G:’ with ‘groups’. It is called thus:

H:> w2m "G:\00-Level1\00-Level2\01-2018\ABC\ABCDEF\PANEL\01 Drafts\file-name(01) and etc.docx"
"groups/00-Level1/00-Level2/01-2018/ABC/ABCDEF/PANEL/01 Drafts/file-name(01) and etc.docx"

And there is a reverse one called m2w.bat that lets me open their paths easily on the Windows machine I have to use.

The quotes are because modern file names can have spaces, brackets and all kinds of things that can mess things up.

Paths of glory.

Installing ZMC on Windows

ZMC is a suite of code for modelling diffuse scattering. If you don’t know what any of that means, there’s nothing to see here.

Binary distribution

Downloaded http://rsc.anu.edu.au/~goossens/ZMC_files/ZMC_Nov2015_Win_g95.zip OR http://djg.altervista.org/downloads/ZMC_files/ZMC_Nov2015_Win_g95.zip into an install directory and unzipped.

Opened a commandline window and cd’d to the directory where files were unpacked.

C:\WHATEVERTHEPATHIS> cd ZMCWin_g95
C:\WHATEVERTHEPATHIS> ZMC.exe --help2

Seems to run.

That’s it. Could have added the directory to my path.

Downloaded http://rsc.anu.edu.au/~goossens/ZMC_files/ZMC_source_package_Mar20_2014.tar.gz OR http://djg.altervista.org/downloads/ZMC_files/ZMC_source_package_Mar20_2014.tar.gz and explored the documentation and the sample simulation included, but used the more current binaries.

Also, went to http://dx.doi.org/10.1155/2015/878463 and downloaded the paper and the simulation hosted there. It is a complete working example. The simulation is also hosted at http://djg.altervista.org/downloads/ZMC_files/878463.f2.zip.

That’s the easy part done…

Installing from source — Cygwin

(1) Install gfortran

Ran Cygwin setup-XXX.exe (x86-64 in my case) and installed gcc-fortran package and any dependencies.

(2) Opened a Cygwin terminal and made an install directory

$ cd installs

$ mkdir ZMC

$ cd ZMC

$ wget http://djg.altervista.org/downloads/ZMC_files/ZMC_toolbox_source_April_2016.tar.gz

$ tar x -vzf ZMC_toolbox_source_April_2016.tar.gz

$ cd ZMC_toolbox_source_April_2016

(3) Run the compile script

$ bash compile_all_Linux_gfortran.sh

Errors!

(4) OK, try 32-bit toolchain.

install cygwin32-gcc-fortran

(5) Copy the script and change the compiler name to i686-pc-cygwin-gfortran.exe

$ bash compile_all_Linux_gfortran_32bit.sh

Mostly works, but bin2gray does not compile, and it is essential.

(6) Try using djgpp fortran (install via Setup.exe)

Change compiler to i586-pc-msdosdjgpp-gfortran.exe

$ bash compile_all_Linux_gfortran_djgpp.sh

Much like 32-bit compile– no bin2gray.

(7) What’s the error? We’ll fix it for the 32-bit gcc compile, rather than djgpp.

$ i686-pc-cygwin-gfortran.exe -w -static -O2 -o bin2gray_static bin2gray.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
bin2gray.f90:15:40:

bin2gray.f90:6:6:

use cmdline_arguments
2
bin2gray.f90:15:40:

character(len=*), parameter :: version = "$Id: bin2gray.f90,v 1.6 2007/06/04 05:23:11 aidan Exp $"
1
Error: Symbol ‘version’ at (1) conflicts with symbol from module ‘cmdline_arguments’, use-associated at (2)

OK, some kind of scope thing. I’ll just change ‘version’ in bin2gray.f90 to ‘versionbg’.

Works!

OK, download new bin2gray from:

$ wget http://djg.altervista.org/downloads/ZMC_files/bin2graybg.f90

And modify the script to the the 32-bit compiler and to compile this file instead of the other one.

(8) Make some links

$ ln -s /home/darren/installs/ZMC/ZMC_toolbox_source_April_2016/ZMCLinux_gfortran_static_32bit/ZMC_static.exe /home/darren/bin/ZMC

and so on.

(9) Testing finds that the binary ‘runs’ in that it throws no errors, but it does nothing. OK. We have a problem.

(10) Add ‘.exe.’ to end of each output file from the compile commands. Does not help.

(11) Retry 64-bit compile. It’s the native one, after all. See what the errors are.

Says: undefined symbol `strtoflt128′
But the relevant library is installed. Adding an explicit call to it -lquadmath does not seem to help.

Oh dear.

Installing from source — MinGW

What if we try for a Windows compile outside of Cygwin?

https://gcc.gnu.org/wiki/GFortranBinaries#Windows

Installed the MinGW bunch of stuff. Went to start menu and opened the MinGW terminal.

H:\Other\ZMC\ZMC_toolbox_source_April_2016>which gfortran
C:\Program Files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin\gfortran.EXE

Used the version of bin2gray.f90 modified to replace the ‘version’ variable with, say, ‘versionbg’, (bin2graybg.f90 as noted above, though copied over the top of bin2gray.f90) then…

Created a new install batch file that looks like this:

H:\Other\ZMC\ZMC_toolbox_source_April_2016>type compile_all_Win_gfortran.bat
@echo off
REM Manual compile of ZMC, DZMC and toolbox programs.
REM
REM Note: I have gnuwin32 installed, so I hve access to pwd etc
REM Dependencies are accounted for by the order of the
REM compilations -- some modules depend on others.
REM This means that this could be broken by upstream changes
REM to the modules by Aidan Heerdegen (aidan@rsc.anu.edu.au)
REM
REM However, if this does not happen, compilation is simple.
REM
REM NOTE!!: Some manual customisation of this file will
REM probably be needed, but it is very simple:
REM
REM Namely the -I and -L flags to gfortran need to point
REM to the directory where the compilation is happening,
REM and that it is easiest for a relatively simple project
REM like this to use the flat structure, then just copy out
REM the executables to a directory in the path.
REM
REM No guarantees/warranties are given or implied. Use at
REM your own risk. Caveat emptor. Buyer beware.
REM
REM And you get what you pay for...
REM
REM darren.goossens@gmail.com Jul 2018
REM
echo ---------------------------
echo on
del *.o *.O *.mod *.MOD
set bindir=ZMCWin_gfortran_static
echo ---------------------------
mkdir %bindir%
echo ---------------------------
gfortran -static -O2 -ffree-line-length-0 -c precision.f90
gfortran -static -O2 -ffree-line-length-0 -c fundamental_constants.f90
gfortran -static -O2 -ffree-line-length-0 -c varying_string.f90
gfortran -static -O2 -ffree-line-length-0 -c globals.f90
gfortran -static -O2 -ffree-line-length-0 -c cartesian_class.f90
gfortran -static -O2 -ffree-line-length-0 -c array_functions.f90

gfortran -static -O2 -ffree-line-length-0 -c sort_functions.f90
gfortran -static -O2 -ffree-line-length-0 -c variable_array.f90
gfortran -static -O2 -ffree-line-length-0 -c binary.f90

gfortran -static -O2 -ffree-line-length-0 -c string_functions.f90
gfortran -static -O2 -ffree-line-length-0 -c statistics.f90

gfortran -static -O2 -ffree-line-length-0 -c binary_io.f90

gfortran -static -O2 -ffree-line-length-0 -c file_functions.f90

gfortran -static -O2 -ffree-line-length-0 -c hash_table.f90
gfortran -static -O2 -ffree-line-length-0 -c polysample.f90
gfortran -static -O2 -ffree-line-length-0 -c vector_class.f90

gfortran -static -O2 -ffree-line-length-0 -c mol2_class.f90
gfortran -static -O2 -ffree-line-length-0 -c cmdline_arguments.f90
gfortran -static -O2 -ffree-line-length-0 -c keyword_class.f90
gfortran -static -O2 -ffree-line-length-0 -c rotmatrix_class.f90

gfortran -static -O2 -ffree-line-length-0 -c crystallography_class.f90
gfortran -static -O2 -ffree-line-length-0 -c image_transforms.f90
gfortran -static -O2 -ffree-line-length-0 -c quaternion_class.f90
gfortran -static -O2 -ffree-line-length-0 -c zmatrix_class.f90

gfortran -static -O2 -ffree-line-length-0 -c pnm_class.f90
gfortran -static -O2 -ffree-line-length-0 -c superimpose.f90

gfortran -w -static -O2 -o ZMC_static zmc_Nov03_2015.f90 rannum.f ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o DZMC_static readat_zmc_Aug29_2014.f90 diffuse_allocatable_March20_2014.f90 rannum.f ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o bin2gray_static bin2gray.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o zmat_maker_static zmat_maker.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o zmat2xyz_static zmat2xyz.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o zmatchk_static zmatchk.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o zmat_anim_static zmat_anim.f90 rannum.f ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o zmat2mol2_static zmat2mol2.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o pgmave_static pgmave.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o pgmcombine_static pgmcombine.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o make_random_occ_static make_random_occ.f90 rannum.f ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o mol2xyz_static mol2xyz.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o catmol2_static catmol2.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o chkmol2_static chkmol2.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o pgm2mask_static pgm2mask.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o pgm2ni_static pgm2ni.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o ni2pgm_static ni2pgm.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
gfortran -w -static -O2 -o raw2pgm_static raw2pgm.f90 ps_routines.f fundamental_constants.o varying_string.o globals.o precision.o cartesian_class.o array_functions.o sort_functions.o variable_array.o binary.o binary_io.o string_functions.o statistics.o file_functions.o hash_table.o polysample.o vector_class.o mol2_class.o cmdline_arguments.o keyword_class.o rotmatrix_class.o crystallography_class.o image_transforms.o quaternion_class.o zmatrix_class.o superimpose.o pnm_class.o
move *.exe %bindir%
copy *.txt %bindir%
copy READ* %bindir%

Opened a Windows command prompt, went to the directory where the files are. Ran the batch file and all was well.

Done!

After this, it’s a case of actually putting together a simulation, putting ZMC binaries where they need to be, and so on.

 

Just for completeness.

Printing to the Brother EP-44: Escape codes and ASCII symbols

The EP-44 is a thermal printing typewriter from around 1984. It also comes with an RS-232c port and the documentation sys it can be used as a printer and terminal.

I’ve been exploring how to use it as a printer.

Here’s some stuff about escape sequences and formatting text when printing to the EP-44.

The EP-44 can be set to expect text encoding as ‘7BIT’, ‘8BIT’ and ‘T/W’. 7 and 8 bit correspond to ASCII codes and T/W is a slightly different code table that includes a couple of escape sequences for controlling the typewriter.

T/W mode

If we set the typewriter in T/W mode, we can make it do superscripts, subscripts and underlines by entering escape sequences into the string of text sent to the machine. One can enter escape sequences in Vim by going into insert mode and typing Ctrl+v then Esc. In the editor screen it should look like ^[ (but typing caret then square bracket won’t work!). Then type the key. ^[D scrolls to give superscript; scroll back down with ^[U; reverse the order to do subscript. ^[E turns underline on, ^[R turns it off.

Here is a screenshot of a text file in Vim:

A screenshot of the file, showing escape codes.

A file, with escape codes, viewed in Vim.

Vim kindly syntax highlights the escape codes.

Here is the printout, printed by simply catting the file to /dev/ttyS1 (in this case):

A scan of the printout.

The printout.

So we can see that the escape codes do their job. Remember, this is with the typewriter in T/W mode; in 7BIT or 8BIT this does not work.

Quirks of T/W mode include: if you send a keyboard caret (^) it prints a raised 2 (like a squared). Left brace gives a one-quarter symbol, right brace gives pilcrow, back tick gives degree symbol, pipe gives one-half and tilde gives section mark. Actually, probably this is pretty useful.

So that’s T/W mode — ideal if super- and subscript and underline are important and the unaccented, first 128 ASCII characters are all you need. (Basically, the characters you can access using the keys with or without the shift key).

Also, for some reason ^[Y gives a plus/minus symbol.

8BIT mode

8BIT mode gives access to (some of) the ASCII characters up to FF (number 256). But if we set the typewriter to 8BIT and send the text file shown above, we get this:

Screenshot, showing how the escape codes don't work.

Same file, 8BIT mode.

So the escape codes don’t work. But we do get access to some more characters.

I fired up bvi and made a file consisting of hex values from 20 (a space) up to FF, plus a little trick in the second half. Here’s what it looks like in bvi (I love that VGA font):

Screenshot showing the bvi window.

Hex view of the file.

When we print this file, we get:

Scan of printout.

Printing to the typewriter using ASCII values up to 256 (FF).

First, we can see that the caret etc are correctly interpreted. Though I cannot see a pilcrow anywhere! So what’s the code for that?

Second, we see that (as the EP-44 manual shows) we get access to a lot more characters. Most can be entered from the EP-44 keyboard, though not all (I can’t see guillemets on the EP-44 keyboard, but I guess they’re in the ROM somewhere since they’d be used on French versions, for example).

The line shown as: 0000…///###.##

Actually consists of four O, three backspace characters (hex value 08), three slashes, three hashes, one tab character and two hashes.

We can see that the backspaces work, and give us three slashed O. This means in 8BIT mode we can superimpose characters; for example we could put a hat (caret) on top of a variable, or a degree symbol for an accent (though accented A and a are available elsewhere).

The last bit of the file shows that this lets us overcome the lack of underline escape codes in 8BIT mode — we can backspace and then print an underscore character. I’ve done it character-by-character, but based on the clattering of the typewriter that this engendered, it might be better to write the whole phrase then backspace and do the underline all in one go.

This would also allow strike-through, using a series of hyphens, though of course they would not meet, so it would be a dashed line.

Could be quite good for ASCII art.

Since the 8BIT codes include a superscript 2, if we were only typing stuff with squares that would be the way to go!

I think the tab character worked, but I’m not sure since the gap is only about 1 character wide — but that could reflect the tab stop, I’m not sure.

Useful references for this were: http://www.asciitable.com/.

and

The manual: http://munk.org/projects/Brother-EP44-User_manual.pdf.

Conclusion

The 8BIT mode is preferable unless superscript and subscript are important. 7BIT was just like 8BIT but limited to the first 128 characters.

 

Madness.

Printing PowerPoints with notes two (or more) to a page (repeat)

This is just a text-only version of the previous iteration with some new details. Just for the record. I had to work up the documentation, so why not post it?

This is what I did to print out PowerPoint slides two per page including the notes underneath.

There is (as of 2018) no option in the PowerPoint print dialogue for this. Note also that I do not have access to a full version of Adobe Acrobat Professional or whatever they are calling it at the moment.

(1) ‘Designed’ notes text in PPT; something like 12 pt for notes and 9 pt for refs/sources (Myriad Pro, though Univers works well too). Formatted notes consistently. To work with the slide notes in the text block under the slide, used ‘Notes Page’ under View. Can resize and so on and get WYSIWYG while formatting.

(2) Used CutePDF (http://cutepdf.com/) to print to PDF file. Went into Advanced settings for CutePDF and made sure paper was A4. Set Print Quality to ‘1200 DPI’, Set TrueTypeFont setting to ‘Download as Softfont’. Under PostScript Options set PostScript Output Options to ‘Optmimize for Portability’ and TrueType Font Download Option to ‘Native TrueType’. Other PDF print options might be acceptable; don’t know. Mac tends to work better with PDF than Windows. Cannot just use ‘Save as PDF’ option from the File menu because that does not give the notes pages.

The Print settings for PowerPoint (rather than the printer) were:
* Color (sic)
* Portrait
* Collated
* Notes Page (Print slides with notes)
* Print all slides (or the range you want)
* Printer: CutePDF
* No header or footer

Then printed and saved the file.

(3) I decided to crop the resulting PDF using a command line tool, because that is highly reproducible — I can get exactly the same cropped box every time.

I used pdfcrop.sh in Cygwin. Cygwin (https://www.cygwin.com/) is a Unix-like environment for Windows; pdfcrop.sh would probably work seamlessly in a command line terminal on a Mac if the software tools it draws on were already installed, possibly through Macports or similar.

pdfcrop.sh is available from https://askubuntu.com/questions/270493/how-to-crop-a-multi-page-image-scanned-pdf-file-which-wont-crop-with-pdfcrop, and also from https://darrengoossens.wordpress.com/2018/02/25/crop-every-page-in-a-multipage-pdf-file.

The pdfcrop.sh command looked like this:

$ pdfcrop.sh -t "105 112 105 112" infile.pdf outfile.pdf

The four numbers are how much to crop from left, top, right, bottom; I worked them out by opening the PDF in GSview (http://pages.cs.wisc.edu/~ghost/gsview/), a Windows-based viewer for PostScript and PDF files that gives coordinates of the pointer, so I could just move my mouse to where I wanted to crop and note down the coordinates.

I know there are graphical cropping tools, but this works and can do lots of pages. Feel free to use whatever tool works for you, but keep in mind that the ability to make exactly the same crop box every time is very useful. An automatic cropping of white space is not ideal since might vary from slide to slide or vary with alterations of the PPT file. It will also fail to remove any page numbers or footers/headers that are present.

(4) I now had a PDF file with the pages, including notes, cropped to have narrow margins. The next step was to put two onto a single landscape page. You can do this by opening the cropped PDF in say Acrobat and then printing to PDF again, after selecting ‘2 pages per sheet’ or equivalent in the print dialogue.

My preference was to use a command line tool. pdfnup (version 2.08 when I used it) is part of pdfjam, which in turn builds on the pdfpages stuff that is part of LaTeX:

$ pdfnup --batch --suffix '2up' outfile.pdf

This takes the ‘outfile’ from the pdfcrop.sh step and makes a new PDF with two pages per page and adds the suffix ‘2up’ to the file name, so the final file is ‘outfile-2up.pdf’

I have noticed that pdfnup gives less white space around the slides (and thus bigger images and text) than printing two per page using Acrobat.

Darren Goossens
darren.goossens@biotext.com.au

29 May 2018

Plotly on cygwin; the absolute basics

This has to be about the absolute basics. I don’t know anything else.

Plotly (https://plot.ly/) is an interactive, online graphing tool. It can be called from JavaScript, Python, whatever. This post is about getting it to work through Python on Cygwin.

This all mostly follows instructions on the Plotly website.

(1) Installed via pip. What’s pip? A Python package manager. I ran the Cygwin setup.exe program and made sure that Puython was installed (in my case it was 2.7) and then installed the matching pip2.7 (Cygwin package python2-pip). So installed that and all its dependencies.

(2) Opened a Cygwin terminal (not an X terminal, just mintty) and typed:

$ pip install plotly

and watched some magic occur.

(3) Went to the Plotly website and created my (free) account. Went to my account settings and selected ‘API keys’. Could not see key — just looked like a row of dots! But hitting ‘Regenerate key’ gave me a new, visible one. Copied that text and noted my username.

(4) In Cygwin, (note, $ is the Cygwin prompt, >>> is the python prompt) typed:

$ python
Python 2.7.13 (default, Mar 13 2017, 20:56:15)
[GCC 5.4.0] on Cygwin

>>> import plotly
>>> plotly.tools.set_credentials_file(username='DarrenG2', api_key='<<insert your key here>>')

quit()

This set up the info needed for the local Plotly/Python installation to talk to the website where the graph will appear.

(5) Checked that this had worked out. Back at Cygwin prompt, in home directory, typed:

$ cat .plotly/.credentials
{
    "username": "DarrenG2",
    "stream_ids": [],
    "api_key": "<<your key here>>",
    "proxy_username": "",
    "proxy_password": ""
}

(6) OK, looked good. Now, tested it by grabbing an example from the Plotly website. Created a file ‘plotly_example.py’ and pasted in some text copied from the website:

import plotly.plotly as py	
from plotly.graph_objs import *

trace0 = Scatter(
    x=[1, 2, 3, 4],
    y=[10, 15, 13, 17]
)
trace1 = Scatter(
    x=[1, 2, 3, 4],
    y=[16, 5, 11, 9]
)
data = Data([trace0, trace1])

py.plot(data, filename = 'basic-line')

(7) Then saved and ran the script

$ python2.7.exe plotly_example.py
High five! You successfuly sent some data to your account on plotly. View your plot in your browser at https://plot.ly/~DarrenG2/0 or inside your plot.ly account where it is named 'basic-line'

Looked good, though they’ve spelled ‘successfully’ unsuccessfully.

(8) But where was the graph? Well, I was working in a basic terminal window. It sent the graph to the web, but then tried to open it using the default links, the text browser. So all I got was a blank screen (typed ‘q’ to quit links). There are a couple of options to see the graph — one is just to paste the given URL into Edge, Chrome, Firefox. Another is to tell Cygwin to look elsewhere for its browser…

(9) Edited my .bash_profile file in my Cygwin home directory and added these two lines:

$ BROWSER=/cygdrive/c/Users/darren/AppData/Local/Mozilla\ Firefox/firefox.exe
$ export BROWSER

This set up the environment variable BROWSER and pointed it at the firefox.exe file (non-admin install, so in an unusual place). I also ran these two lines in the terminal window to save me closing and reopening it.

(10) Repeated step (7) and — lo and behold! — a Firefox window popped up and the graph was in it!

Plotly graph in Firefox, after running the script in Cygwin.

Plotly graph in Firefox, after running the script in Cygwin.

Now, mastery of Plotly and Python is a much bigger project, but at least this offers the beginnings. Note also that the graph can be edited interactively within the webpage where it appears.

 

Plots away!

 

Old g95 (for the make use of)

I needed to compile a Windows g95 binary for someone. I have Win 7 in a VM on VirtualBox. I had the g95 install tree from a (quite old) back-up of a previous computer, but not a proper install.

The install tree looks like this:

C:\util>dir /s g95
 Volume in drive C has no label.
 Volume Serial Number is 8440-3CD9

 Directory of C:\util\g95

23/08/2012  09:42 AM              .
23/08/2012  09:42 AM              ..
23/08/2012  09:42 AM              bin
23/08/2012  09:42 AM              doc
23/08/2012  09:42 AM              lib
23/08/2012  09:42 AM            55,782 uninstall-g95.exe
               1 File(s)         55,782 bytes

 Directory of C:\util\g95\bin

23/08/2012  09:42 AM              .
23/08/2012  09:42 AM              ..
26/03/2008  11:49 AM           553,984 ar.exe
26/03/2008  11:49 AM           827,904 as.exe
17/06/2009  09:44 PM           123,046 g95.exe
26/03/2008  11:49 AM           782,848 ld.exe
28/12/2007  12:23 AM            15,964 mingwm10.dll
26/03/2008  11:49 AM           554,496 ranlib.exe
26/03/2008  11:49 AM           685,568 strip.exe
               7 File(s)      3,543,810 bytes

 Directory of C:\util\g95\doc

23/08/2012  09:42 AM              .
23/08/2012  09:42 AM              ..
16/10/2004  09:36 PM            17,015 bg.gif
27/11/2004  03:51 AM            18,007 COPYING.txt
08/12/2005  06:19 AM            22,431 docs.html
23/11/2004  12:00 PM           107,122 g95.bmp
02/01/2007  01:59 AM           170,619 G95Manual.pdf
31/05/2008  06:59 AM            11,858 Readme.html
31/05/2008  07:00 AM             6,687 README.txt
               7 File(s)        353,739 bytes

 Directory of C:\util\g95\lib

23/08/2012  09:42 AM              .
23/08/2012  09:42 AM              ..
28/12/2007  12:23 AM             2,192 crt1.o
28/12/2007  12:23 AM             2,288 crt2.o
28/12/2007  12:23 AM             1,239 dllcrt2.o
23/08/2012  09:42 AM              gcc-lib
22/10/2006  01:27 AM           408,608 libadvapi32.a
30/10/2005  11:13 AM           253,890 libgdi32.a
22/10/2006  01:27 AM           594,018 libkernel32.a
28/12/2007  12:23 AM               458 libm.a
28/12/2007  12:23 AM             7,514 libmingw32.a
28/12/2007  12:23 AM           267,880 libmingwex.a
28/12/2007  12:23 AM            82,558 libmoldname.a
28/12/2007  12:23 AM           503,692 libmsvcrt.a
22/10/2006  01:27 AM           128,262 libshell32.a
22/10/2006  01:27 AM           435,754 libuser32.a
30/10/2005  11:13 AM            82,086 libws2_32.a
              14 File(s)      2,770,439 bytes

 Directory of C:\util\g95\lib\gcc-lib

23/08/2012  09:42 AM              .
23/08/2012  09:42 AM              ..
23/08/2012  09:42 AM              i686-pc-mingw32
               0 File(s)              0 bytes

 Directory of C:\util\g95\lib\gcc-lib\i686-pc-mingw32

23/08/2012  09:42 AM              .
23/08/2012  09:42 AM              ..
23/08/2012  09:42 AM              4.0.4
               0 File(s)              0 bytes

 Directory of C:\util\g95\lib\gcc-lib\i686-pc-mingw32\4.0.4

23/08/2012  09:42 AM              .
23/08/2012  09:42 AM              ..
23/08/2012  09:42 AM             1,022 cc1.lnk
17/06/2009  09:44 PM         5,242,021 f951.exe
17/06/2009  09:44 PM           859,168 libf95.a
17/06/2009  09:44 PM            61,284 libgcc.a
               4 File(s)      6,163,495 bytes

     Total Files Listed:
              33 File(s)     12,887,265 bytes
              20 Dir(s)  42,207,707,136 bytes free

Now, all that is required to make this work is to set some environment variables. (Start → Control Panel → System → Advanced System Settings → Environment Variables).

First, I had to put some directories in the path, so I edit the PATH variable. It works if I have the path to the g95.exe binary and also to the f951.exe file. That is:

PATH=C:\util\g95\bin;c:\util\winvi;c:\util\g95\lib\gcc-lib\i686-pc-mingw32\4.0.4;[[INSERT REST OF PATH HERE]]

I’ve put [[INSERT REST OF PATH HERE]] at the back, but I’ve actually got the g95-related paths at the back (you want the most commonly used bits of the path at the front, not that it matters with modern fast coomputers). Then, I want to create a new variable called LIBRARY_PATH:

LIBRARY_PATH=c:\util\g95\bin;c:\util\g95\lib\gcc-lib\i686-pc-mingw32\4.0.4;c:\util\g95\lib

Now, I don’t know if I need all three directories in the LIBRARY_PATH, but it works so I am not complaining.

So to compile my tiny little program I can now type:

X:\Downloads\Brill_dir>g95 -o Brill.exe brillouin.f90

And it works. Is it statically linked? Well, on Linux, dynamically linked, compiled with GFortran, it’s about 68 kB. This binary is about 360 kB, so I sure hope it is statically linked!

Caveats: I have not tried anything fancier than this absolutely basic compile. It works. Compiling with the -static flag makes no difference to the size of the binary.

FWIW

A VGA font in a terminal emulator

How’d I do it? It was quite a while ago and I can’t remember, I can’t recall. I’m trying to reconstruct it…

I grew up in the IBM compatible, DOS era. That VGA font that you got by default in DOS still, to this day, looks ‘right’ to me on a terminal screen, even after years of using Linux and Mac OS X and what not. I know it is not a great font in numerous ways, but I am so familiar I don’t even see it. It’s invisible, like a good writing tool should be. So I wanted to use it in my terminal window on Debian. It’s not very hard, maybe. I can’t remember if these were all the things I needed to do…

I am using mrxvt because I like the simplicity of it. This is my very simple mrxvt configuration file, .mrxvtrc:

Mrxvt.sl: 65535
MRxvt.ps: true

Mrxvt.xft:                      1
Mrxvt.xftFont:                  Perfect DOS VGA 437 Win
Mrxvt.xftSize:                  16
Mrxvt.xftAntialias:             1

Mrxvt.saveLines:                10000

And I have aliased the command mrxvt to this string:

alias mrxvt='mrxvt-full -fade 50 -ps -title " " -tn rxvt'

So to get the VGA font, I first went and found a good X windows font, called “Perfect DOS VGA 437 Win”, which is a ttf (TrueType font) when I unzip the archive. I put the file (called Perfect_DOS_VGA_437_Win.ttf) in a subdirectory of my .fonts directory

1 create ~/.fonts/perfect
2 copy files into it
3 mkfontdir ~/.fonts/perfect/
4 xset fp+ /home/goossens/.fonts/perfect/
5 xset fp rehashq
6 fc-cache

I put it under ‘perfect’, and ran fc-cache to update the list of available fonts:

$ ls ~/.fonts/perfect
Perfect_DOS_VGA_437_Win.ttf

$ fc-cache -f -v .fonts

And, on a modern Linux system, that seems to be all that is required. Except I do notice that my .fonts.conf file looks like this (also serves as an example of what the font looks like in action):

Perfect DOS VGA 437 Win font used in mrxvt managed by FLWM.

Perfect DOS VGA 437 Win font used in mrxvt managed by FLWM.

Notice that the line at the end lists my local ~/.fonts directory? I think that might be important, but like I said it was a long time ago and I’m not sure.

So there you have it. Finding Perfect_DOS_VGA_437_Win.ttf somewhere on the web and putting it in your ~/.fonts directory and making sure that that directory is listed in your ~/.fonts.conf file and then changing the font selection line in the config file for whichever terminal emulator you are using might or might not let you use a font you don’t like.

Fonty McFontface.