



Software to deal accurately and efficiently with complex angular masks of galaxy surveys.  

Angular mask of the Northern part of the 2dF QSO Redshift Survey 10k release. The upper panel depicts the exact mask. The 5° × 5° rectangles delineate the parent UKST fields, while the black 2° diameter circles are the fields of the 2dF spectroscopic survey. The red things are holes in the UKST fields. The middle panel shows the 1178 connected polygons, bounded by 4883 edges (including abutting edges), into which mangle resolves the mask. The lower panel shows the mask reconstructed by mangle from harmonics up to l = 1000. 

The URL of this page is
http://casa.colorado.edu/~ajsh/mangle/ .  
The algorithms and mathematics underlying mangle are written up in
Hamilton & Tegmark (2004).  
This page contains the documentation for the mangle software.
The only other ways to find out about mangle are
(1) by reading the abovereferenced paper, (2) by running the commands, (3) by reading the source code. 

Source and executable compiled for LinuxIntel:
mangle1.4.3i386.tar.gz (5.5MB version of 14 Sep 2006) mangle1.4.1i386.tar.gz (5.4MB version of 30 Mar 2004) mangle1.4i386.tar.gz (5.4MB version of 3 Sep 2003)  
Source and executable compiled for Solaris:
mangle1.4.3sun.tar.gz (5.6MB version of 14 Sep 2006) mangle1.4.1sun.tar.gz (5.0MB version of 30 Mar 2004) mangle1.4sun.tar.gz (5.1MB version of 3 Sep 2003)  
Patch to upgrade mangle 1.4.1 to 1.4.3 mangle1.4.1_to_1.4.3.patch (17K)  
Patch to upgrade mangle 1.4 to 1.4.1 mangle1.4_to_1.4.1.patch (33K) 
Both of the above include mask files for PSCz, for the 2dF QSO 10k Redshift Survey, and for the 2dFGRS 100k.
Mangle works by resolving a mask into disjoint polygons. Each polygon is a convex angular region bounded by an arbitrary number of edges. The polygons may be regarded as the `pixels' of a mask, with the feature that the pixels are allowed to take a rather general shape, rather than following some predefined regular pattern.
Among other things, mangle computes analytically the spherical harmonics of a mask. The algorithm for computing spherical harmonics is recursive and stable, and can reasonably defended as being fast, considering what it does. However, you should be aware that there is a numerical penalty to be paid for allowing a mask to have arbitrary shape: the computation time for harmonics up to l increases as l^{3}, a pretty steep penalty when l is large. The computation time is proportional to the number of edges of the mask, and on my laptop (a 750MHz Pentium III), it takes 3 cpu minutes per edge to compute harmonics up to l = 1000.
The mangle software consists of two parts:
a frontend, a set of commands written in c;  
a backend, a suite of fortran routines that do much of the angular mathematics. 
The scheme that evolved into mangle began life in the delightful atmosphere of an Aspen Center for Physics workshop in 1985. The mathematics of harmonization and other aspects of the computation of angular integrals are written up in the Appendix of Hamilton (1993) ApJ 417, 1935. The mathematics of balkanization and other features of mangle are described by Hamilton & Tegmark (2004), MNRAS, 349, 115128.
To start using mangle, you must first define your mask. A description of a mask is contained in `polygon files', which may take a variety of formats. For example, the masks of the 2dF survey are defined by 3 polygon files which define the boundaries of: (1) UKST plates, (2) 2° fields, (3) holes in UKST plates.
You do not need to resolve your mask into polygons: mangle will do that for you with the balkanize command. Typically, a mask is defined by boundaries of plates or fields or cuts in declination or galatic latitude, and by holes drilled in those plates or fields to avoid bright stars, satellite trails, and such.


For example, the most general angular region that mangle can handle is a mask, as defined in the table.

snap balkanize unify weight harmonize map drangle ransack poly2poly polyid
Typing a command with no arguments will give you a brief summary of its usage.
Typing a command with the d switch will tell you what the defaults are.
Most commands read and/or write to `polygon files'. Here is the Format of Polygon Files.
Command line switches are consistent over all mangle commands, although any one command will admit only some subset of switches.

snap [d] [q] [S] [a<a>[u]] [b<a>[u]] [t<a>[u]] [y<r>] [m<a>[u]] [s<n>] [e<n>] [vovn] [p[+]<n>] [i<f>[<n>][u]] [o<f>[u]] polygon_infile1 [polygon_infile2 ...] polygon_outfileYou should always start by running snap on all the original files that define your mask. If you have several original files, then you should also run snap on the combined output. If you do not run snap, then you are asking for trouble, and you can email complaints to /dev/null.
The problem is that the positions of the intersections of two almost but not exactly coincident circles (cap boundaries) on the unit sphere may be subject to significant numerical uncertainty. To avoid numerical problems, such circles must be made exactly coincident, and snap does just that. You might think that that nearbutnotexactlycoincident circles would hardly ever happen, but in practice they occur often, because a mask designer tries to make two polygons abut, but imprecision or numerical roundoff defeats an exact abutment.
Snap adjusts the edges of each polygon, but it leaves the number and order of polygons the same as in the input file(s). Edges that appear later in the input file(s) are snapped to earlier edges.
Here for example is the incantation for the 2QZ 10k North survey (my private convention is to begin all junk files with a j):
snap ir1r ngp_ukstfld.lims.txt jnu snap ic1h s6 ngp_field_coords.txt jnf snap iv4r ngp.used.rahole.txt jnh snap jnu jnf jnh jnufhThe first three snap commands snap the cap boundaries of each of the three original mask files. The fourth snap snaps the combined set of cap boundaries. The i.. switches specify the format of the input polygon files. The i.. switches can be omitted if each polygon file is prefaced with a few lines containing keywords with appropriate parameters that specify the format.
The snap command offers four tunable tolerances
snap a<angle>[<unit>] b<angle>[<unit>] t<angle>[<unit>] y<ratio> ...The various <angle>s and ratio are real numbers, while [<unit>] is an optional angular unit, one of r (radians), d (degrees), m (arcminutes), s (arcseconds), or h (Right Ascension in hours, minutes, and seconds, Declination in degrees, arcminutes, and arcseconds). You can find out what the defaults are with
snap dAs of writing (June 2001), the default angles are all 2s, which is two arcseconds, while the default value of ratio is 0.01.
If the boundaries of your mask are precisely defined, then you should tighten the snap angles appropriately (the default value of ratio, the argument of the y switch, should be fine in virtually all cases), in order to prevent snap from snapping boundaries that should not be snapped.
snap
accomplishes its work in two stages:
Stage 1:  Snap axes and latitudes of pairs of caps together, passing repeatedly through all pairs of caps until no more caps are snapped.  
Stage 2:  Snap edges of polygons to other edges, again passing repeatedly through all pairs of caps until no more caps are snapped. 

balkanize [d] [q] [a<a>[u]] [b<a>[u]] [t<a>[u]] [y<r>] [m<a>[u]] [s<n>] [e<n>] [vovn] [p[+]<n>] [i<f>[<n>][u]] [o<f>[u]] polygon_infile1 [polygon_infile2 ...] polygon_outfileThe idea for this routine emerged in a phone conversation with Max Tegmark, who spontaneously invented the name. Balkanization fragments an input set of possibly overlapping polygons into many nonoverlapping connected polygons. The process involves two successive stages:
Stage 1:  Fragment the polygons into nonoverlapping polygons, some of which may be disconnected.  
Stage 2:  Identify disconnected polygons and subdivide them into connected parts. 
(a)  Is the intersection of two polygons neither empty nor equal to the first polygon? If so, find a circle, a cap boundary, of the second polygon that divides the first polygon, and split the first polygon into two along that circle.  
(b)  Iterate. 
Stage one of the balkanization procedure yields polygons
that can contain two or more disconnected parts, as illustrated below.
Stage two subdivides such disconnected polygons into connected parts
by computing the connected boundaries of the polygon,
and lassoing each connected boundary with an extra cap.
A polygon that contains two disconnected parts. 
Polygons can have intricate multiplyconnected shapes, with many disconnected parts, each punctuated with many holes. mangle is designed to deal with almost any polygon you can throw at it, though it could fail on a polygon whose vertices are arranged in a sufficiently complex fractal pattern. If mangle fails on a polygon, it is a bug; please email me.


To complete its task, balkanize snaps the edges of each balkanized polygon, prunes redundant edges, and discards polygons with zero area.
Assume that you have run snap on the original files that define your mask. By default, snap writes output files in polygon format. The polygon format includes a weight attached to each polygon. You can edit these by hand.
The rule used by balkanize is that the weight of a polygon that appears later in the input file overrides weights of earlier polygons. In other words, if balkanize finds that two polygons intersect, then the weight applied to the intersection is the weight of the later polygon. The nonintersecting parts of the polygons inherit the weights of their parents.
For example, if you want to add (subtract?) a hole, an empty polygon, to a mask, then append a polygon with zero weight to the file of polygons. In practice, you might do this in the following way. Suppose you have a file fields.dat defining a list of fields, and another file holes.dat defining a list of holes. The first step is, as usual, to apply snap:
snap fields jf snap holes jhwhere of course you may need to use the i.. switch to specify the format of the input polygon files. Now edit the holes file jh to set the weight for all polygons to zero. You can probably leave the fields file jf as is, since the default weight is 1, which may be what you want. Then snap the fields and holes files together:
snap jf jh jfhThe order of the input files jf and jh is important here, fields first and holes second, because you want the holes to override the fields. Next balkanize:
balkanize jfh jbIn the output file jb of balkanized polygons, some of the polygons will have weight 1 (those inside the fields but not in a hole), and the rest will have weight 0 (the holes). Applying unify to the balkanized file
unify jb pretty.polygets rid of the polygons of weight 0, the holes, and merges, as far as possible, the polygons of weight 1, giving a pruned file pretty.poly of nonoverlapping polygons ready to harmonize. If you are daring, you can pipe the snapbalkanizeunify commands together with
snap q jf jh   balkanize q    unify  pretty.polysince an input filename of  instructs to read from stdin, while an output filename of  instructs to write to stdout. The q switch instructs the first two commands to be quiet, since otherwise they would write advice to their output polygon files, which is probably not what you want. Note that advice is written to stdout; only error messages are written to stderr.
weight [d] [q] z<survey> [m<a>[u]] [s<n>] [e<n>] [vovn] [p[+]<n>] [i<f>[<n>][u]] [o<f>[u]] polygon_infile1 [polygon_infile2 ...] polygon_outfile
weight requires the z<survey> switch as an argument. The <survey> argument may be either:
(a)  the name of a file containing a list of weights, or  
(b)  a string that tells weight which (usersupplied) subroutine to use in computing the weight at a point. 
Option (a) is much more practical, because there is no need to recompile mangle.
In case (a), where <survey> is the name of a file containing a list of weights, then that file should consist of an arbitrary numbers of header lines (not beginning with a number), followed by a list of weights, one weight per line for each polygon in the polygon_infiles. The weight is taken to be the first number in the line; anything beyond the first number on a line is ignored. If the weight file contains only a single weight, then that weight is applied to every polygon. Otherwise the weight file should contain a separate weight for each polygon, and it is an error for there to be fewer weights than polygons.
Suppose you have your own software which returns a weight given an angular position. You can get mangle to create a file containing a list of angular positions of midpoints of polygons by
poly2poly om polygon_infile midpoint_outfileHere the om switch specifies an output file in midpoint format. The midpoint_outfile becomes input to your own software, which should produce another file containing a list of weights, which can be fed to weight.
In case (b), where <survey> is a string telling weight which (usersupplied) subroutine to use in computing the weight, then you will need to write a fortran or c subroutine that returns a weight given an azimuth and an elevation. You might like to use the 2QZ 10k subroutine twoqz.f as a template. Having written such a subroutine, you must then plumb it into the mangle code by updating weight_fn.c, which should be selfexplanatory. Finally, you must update the Makefile to include your subroutine, and recompile with the make command.
As of writing (June 2001), the only survey plumbed into mangle is the 2QZ 10k survey. Thus
weight z2QZ10k jb jwreads polygons from the balkanized polygon file jb, applies weights from the 2QZ 10k survey, and writes the polygon file jw.
Update (1 July 2001): Peder Norberg and Shaun Cole's weights for the 2dFGRS 100k survey are now also plumbed in. The incantation is z2dF100k.
unify [d] [q] [m<a>[u]] [s<n>] [e<n>] [vovn] [p[+]<n>] [i<f>[<n>][u]] [o<f>[u]] polygon_infile1 [polygon_infile2 ...] polygon_outfileThe unify command eliminates polygons with zero weight, and does its best to merge polygons with the same weight, so as to yield a minimal file of nonoverlapping polygons. The command is not strictly necessary, but it tidies things up, and it can save harmonize and other programs a lot of computer time.
If the oldid vo switch is used, then unify will unify only polygons sharing the same id in the input polygon file(s). That is, if the vo switch is used, then to be considered as candidates for merging, a pair of polygons must have not only the same weight, but also the same id number. The default (vn) is that unify attempts to merge polygons of the same weight regardless of their id numbers, and assigns new polygon ids to polygons in the output polygon file.
Note that unify
does not necessarily accomplish the most efficient unification,
nor, as illustrated below, is the unification necessarily exhaustive.
What
unify
does is pass repeatedly through the polygon file,
merging a pair of polygons wherever the pair can be merged into a single polygon
by eliminating a single abutting boundary.
A system of 4 polygons that unify fails to merge into a single polygon, because no pair of polygons can be merged. 
harmonize [d] [q] [l<lmax>] [m<a>[u]] [s<n>] [e<n>] [p[+]<n>] [i<f>[<n>][u]] polygon_infile1 [polygon_infile2 ...] Wlm_outfileThe spherical harmonics are computed analytically, in the manner described in the Appendix of Hamilton (1993), MNRAS, ApJ 417, 1935. The algorithm is recursive and stable, able to compute harmonics to machine precision to arbitrarily high order, limited only by computer power and patience. The recursion recovers correctly from underflow, which can occur at large harmonic number l.
The spherical harmonics of an angular mask are given by integrals of spherical harmonics over the area of the mask. As detailed in the aforementioned reference, the key mathematical trick is to integrate by parts to convert the integrals over the area of the mask into integrals over its boundary. If the boundary is resolved into arc segments, or edges, then the integral over each arc segment can be done analytically, and the integral over the boundary is the sum of the integrals over each arc segment. The problem is wellsuited to computation: the computational problem is to identify the arc segments of the boundary of the mask, and then to accumulate the harmonics contributed by each arc segment. The computation is naturally parallelizable, if there were need.
The most timeconsuming part of the computation is rotating the harmonics of an arc segment from its natural frame of reference into the final frame of reference. The computational time for a rotation goes as l^{3} where l is the maximum harmonic number. The rotation is unnecessary if the circle is a line of constant latitude in the final reference frame, and the computation goes faster (as l^{2}) in this case.
harmonize
detects polygons which are rectangles,
polygons bounded by lines of constant azimuth and elevation,
and applies an accelerated computation for such polygons.
The computation is accelerated in two respects:
(1)
the computation of the harmonics contributed by lines of constant elevation
is naturally faster, because no rotation to the final frame is necessary;
(2)
if two rectangles have the same minimum and maximum elevation,
then the harmonics contributed by lines of constant azimuth
are related by a simple rotation about the polar axis,
for which the rotation matrix is diagonal.
Note that the second acceleration
works only if at least two rectangles
have the same minimum and maximum elevation.
Two such rectangles need not be adjacent in the polygon file:
mangle reorders the computation of polygons
so as to take advantage of accelerations where possible.
map [d] [q] w<Wlmfile> [l<lmax>] [g<lsmooth>] [u<inunit>[,<outunit>]] [p[+]<n>] azel_infile outfilemap requires the w<Wlmfile> switch as an argument. The command
map w<Wlmfile> azel_infile outfilereads harmonics from the <Wlmfile> created by harmonize, reads lines of azimuthal and elevation from azel_infile, and writes lines of azimuthal, elevation, and value to outfile.
The azel_infile may contain arbitrary numbers of header lines, after which each line should contain two angles, an azimuth az and an elevation el, as in
Header lines ... az_{1} el_{1} az_{2} el_{2} ...An example is the file azel.dat in the mangle directory.
The outfile contains the azimuth and elevation from azel_infile, together with the value w(n) of the summed weighted harmonics at that position (see the formula in the table below).
The
u<inunit>[,<outunit>]switch specifies the units of the angles az and el in azel_infile and outfile. The u<unit> switch, with only one unit present, specifies the units of the angles in both azel_infile and outfile. You can find the default angular units by running
map d
The map command may be run interactively with
map w<Wlmfile>  which instructs map to read from stdin, and to write to stdout.
map offers two optional parameters, a maximum harmonic number lmax, and a Gaussian smoothing harmonic number lsmooth
map l<lmax> g<lsmooth> ...

The result is equivalent to the angular crosscorrelation (commonly denoted <DR>, or DataRandom, in cosmological parlance) between given points D and points R in the mask separated from the D points by a given angle. If the data points D are random points generated by ransack, then the result will be equivalent to the angular autocorrelation (commonly denoted <RR>, or RandomRandom, in cosmological parlance) between pairs of points in the mask separated by a given angle.
drangle [d] [q] [h] [m<a>[u]] [s<n>] [e<n>] [u<inunit>[,<outunit>]] [p[+]<n>] [i<f>[<n>][u]] polygon_infile azel[th]_infile [th_infile] dr_outfile
The first file given on the command line is the mask, a polygon file polygon_infile.
If three files are given on the command line, then the second file, azelth_infile, is taken to contain the centre az and el, and radii th, of each circle, as in
Header lines ... az_{1} el_{1} th_{11} th_{12} ... th_{1n1} az_{2} el_{2} th_{21} th_{22} ... th_{2n2} ...The azimuth and elevation on each line specifies the centre of concentric circles with radii th running over the values in the rest of the line. The number of values of th may vary from line to line. If there are m centres, and the i'th centre has n_{i} radii, then there are n_{1} + n_{2} + ... + n_{m} circles altogether.
Alternatively, if four files are given on the command line, then the second file, azel_infile, is taken to contain the centre of each circle, its azimuth az and elevation el, as in
Header lines ... az_{1} el_{1} az_{2} el_{2} ...while the third file, th_infile, contains the angular radii th, as in
Header lines ... th_{1} th_{2} ...The azimuth and elevation on each line of the azel_infile file specifies the centre of concentric circles with radii th running over all values in the th_infile file. Thus if the second file azel_infile contains m centres, and the third file th_infile contains n radii, then the two files specify mn circles altogether.
The last of the three or four files specified on the command line is the output file dr_outfile.
The default is to write a full table of results to the output file, a value for each input az, el, and th. If there are separate azel_infile and th_infile input files (4 files on the command line), then the output file looks like:
_{ } th(u): az(u)_{ } el(u)_{} th_{1 } th_{2 } ... th_{n } az_{1} el_{1} dr_{11} dr_{12} ... dr_{1n} az_{2} el_{2} dr_{21} dr_{22} ... dr_{2n} ... az_{m} el_{m} dr_{m1} dr_{mm} ... dr_{mn} Average:_{ } dr_{1 } dr_{2 } ... dr_{n }The first line is a header line. The second line is a header line that repeats the values of th from the th_infile. The last, Average, line contains the averages dr_{j} of the values dr_{ij}, i = 1, ..., m, on the preceding m lines.
If there is a single azelth_infile file (3 files on the command line), then the output file looks similar, but without the final line containing the Average.
If you don't want the full table of results, but only the summary Average, then use the h switch
drangle h polygon_infile azel_infile th_infile dr_outfileThe h option is available only if there are separate azel_infile and th_infile input files (4 files on the command line).
The algorithm is as follows. drangle loops in turn through each point az, el of azimuth and elevation. Thus two points take twice as much CPU time as one point. For each point, drangle attempts to accelerate the computation with respect to the angular separations th by first computing the minimum and maximum angles between the point and each polygon in the mask. drangle uses the information about the minimum and maximum angles to decide whether the circle lies entirely outside or entirely inside a polygon, in which case the (unweighted) angle subtended within the polygon is zero or 2 pi. In practical cases the angle subtended is often zero for the great majority of polygons of a mask, especially when the mask is composed of many polygons. Since calculation of the subtended angle can be skipped if the angle is zero, computation can be greatly speeded. Further acceleration comes from ordering the polygons in increasing order of the minimum angle from the point to each polygon. This allows the computation to loop to the next value of th as soon as it hits a polygon for which the subtended angle is zero, rather than checking through large numbers of polygons that all have zero subtended angle.
ransack [d] [q] [c<n>] [r<n>] [m<a>[u]] [s<n>] [e<n>] [u<inunit>[,<outunit>]] [p[+]<n>] [i<f>[<n>][u]] polygon_infile1 [polygon_infile2 ...] azel_outfileThe c<n> switch seeds the random number generator with integral seed <n>.
The r<n> switch commands to generate <n> random numbers.
polygon_infile1 [polygon_infile2 ...] are polygon files specifying the mask.
azel_outfile is the name of a file to which to write the random positions. In addition to recording the azimuth and elevation of each position, ransack writes the id number of the polygon inside which the random position falls.
The algorithm is as follows. ransack first selects randomly a polygon in the mask, with probability proportional to the product of the polygon's weight and area. It lassos that polygon with a circle that is intended to be a tight fit, but is not necessarily minimal. It generates a point randomly within the circle, tests whether the point lies inside the polygon, and keeps the point if it does.
ransack lassos polygons as needed, recording a lasso so that a lasso is computed only once for any polygon. If the desired number of random points exceeds the number of polygons in the mask, then ransack starts by lassoing every polygon in the mask.
poly2poly [d] [q] [m<a>[u]] [j[<min>][,<max>]] [k[<min>][,<max>]] [n] [s<n>] [e<n>] [vovn] [p[+]<n>] [i<f>[<n>][u]] [o<f>[u]] polygon_infile1 [polygon_infile2 ...] polygon_outfile
The default output format is polygon format. Thus both
poly2poly polygon_infile polygon_outfileand
poly2poly op polygon_infile polygon_outfilehave the same effect of converting polygons in the polygon_infile to an output polygon file polygon_outfile written in polygon format.
One particularly useful output format is the graphics format. The command
poly2poly og<n> polygon_infile polygon_outfileproduces a polygon file containing <n> points per (2 pi) along each edge of each polygon.
Not all polygons are rectangles. The command
poly2poly or polygon_infile polygon_outfilereads polygons from polygon file polygon_infile, identifies which of the polygons are rectangles (polygons bounded by lines of constant azimuth and elevation), and writes the surviving polygons in rectangle format to outfile. Polygons that are not rectangles are discarded.
If conversion with poly2poly produces lots of errors, chances are it's because the input polygon file needs snapping. Use snap instead. For example, poly2poly will often fail if the input file is in edges edges format, even if that input file was created from a snap'd polygon file, because the edges format discards information about two edges coming from the same cap.
By default poly2poly retains the polygon id numbers found in the input polygon file(s), unlike the snap, balkanize, and unify commands. If you want poly2poly to stamp the polygons in the output file with a new set of sequential polygon id numbers (perhaps because the input polygon file contained no polygon id numbers), then use the vn switch.
poly2poly offers the following optional parameters:
poly2poly j[<min>][,<max>] k[<min>][,<max>] n vovn p[+]<n> ...

polyid [d] [q] [u<inunit>[,<outunit>]] [p[+]<n>] polygon_infile azel_infile outfile
The polygon_infile is a single polygon file, complete with polygon id numbers. The polygon file will normally have been created as the output of some other mangle command. To avoid ambiguity in id numbers, the i switch (specifying the format of the polygon_infile) is not supported by the polyid command.
The azel_infile may contain arbitrary numbers of header lines, after which each line should contain two angles, an azimuth and an elevation, as in
Header lines ... az_{1} el_{1} az_{2} el_{2} ...An example is the file azel.dat in the mangle directory.
The outfile contains the azimuth and elevation from azel_infile, together with a list of the id numbers of polygons containing that angular position.
How does mangle determine polygon id numbers? By default, the snap, balkanize, and unify commands produce sequential polygon id numbers in the output polygon file, ignoring any polygon id numbers in the input polygon files. The weight, poly2poly, and polyid commands, on the other hand, use the polygon id numbers found in the input polygon file(s). You can change this default behaviour with the von switch.
The u<inunit>[,<outunit>] switch specifies the units of the angles az and el in azel_infile and outfile. The u<unit> switch, with only one unit present, specifies the units of the angles in both azel_infile and outfile. You can find the default angular units by running
polyid d
polyid takes no short cuts: it tests all points against all polygons. This can take time if there are large numbers of points and large numbers of polygons.
The mangle software recognizes a variety of formats for files defining an angular mask, hereafter called `polygon files'. All mangle programs read and write polygon files through the same subroutines rdmask.c and wrmask.c. If the worst comes to the worst, you can look in those subroutines to see what is happening.
The intention is that the read subroutine rdmask should be flexible, and fairly tolerant of syntax. If a line of data yields an error on the first or second words (all formats expect at least two numbers in a line of data), then rdmask goes to the next line, on the assumption that the line contains a header or a comment. Thus polygon files can contain arbitrary quantities of commentary. If on the other hand rdmask reads the first and second words of a line successfully, then it assumes that it has found a line in the required format. Any error encountered later in the line is then considered to be a genuine error, upon which rdmask issues an error message, and proceeds to the next line. The policy is to carry on regardless as long as possible.
The formats mimic those actually used by various galaxy surveys, and it should not be difficult to cast the mask for your survey into one or other of the formats. It may well be that your existing mask files are already in a suitable format, and can be read without change. If you think your format is different and deserves to be plumbed in, email me. There are seven possible input formats:
c circle v vertices e edges r rectangle p polygon s spolygon R RegionThere are five additional formats that can be written but not read:
a area g graphics i id m midpoint w weight
It is good practice to adopt the policy of specifying the format of polygon files with keywords inside the polygon file, since in that way the polygon file becomes selfdocumenting: the polygon file remembers its own format without further intervention.
Command line switches apply to all input polygon files, but keywords inside an input polygon file affect only that file, not any subsequent input polygon files.

The default output format is polygon. The output format can be changed with the o (output) switch.
The only formats that retain complete information about polygons are the circle, polygon, and spolygon formats. The edges, rectangle, and vertices formats in general lose information about polygons.

az_{1} el_{1} th_{1} ... az_{n} el_{n} th_{n}
defines a polygon with n caps. In circle format, a line with 3n angles defines a polygon with n caps.
For convenience, and to allow extra precision in defining caps covering the whole sky except for a tiny hole, the sign of a polar angle th is used to signify whether the cap is the region north or south of the circle. If the polar angle is positive, th >= 0, then the cap is the region north of the circle. If the polar angle is negative, th < 0, then the cap is the region south of the circle. A circle with th = 0 (or th = pi) signifies a cap with zero area, while a circle with th = pi signifies a cap covering the entire sky.
Here for example is a part of the 2QZ 10k North field file:
coordinates (B1950) radius Field hh mm ss.ss dd mm ss.s d ngp178 11 58 42.31 02 17 59.2 1 ngp179 12 04 35.46 02 17 59.2 1 ngp180 12 10 26.56 02 17 59.2 1 ...This can be read with
s6 ic1hThe s6 switch says to skip the first 6 characters of each line. The ic switch specifies that the input format is circle. The 1 on ic1 says to read only 1 circle on each line. Notice that the specification is 1 circle, not 3 angles; mangle expects to read 3 angles per circle. The h on ic1h declares that the azimuth and elevation are in hms(RA) and dms(Dec) format, while the radius is in degrees. The above example could also be read with
s6 ichin which the 1 on the ic1h switch is omitted, since there are no trailing characters on the line to confuse matters. With the 1 omitted, mangle counts the number of angles on the line, namely 3, and deduces that there is 1 circle per line.
The command line switches can be omitted if appropriate keywords and corresponding arguments are incorporated into the input file before the relevant lines of data. In the above example, the addition of 3 lines at the beginning of the file:
skip 6 circle 0 1 unit h coordinates (B1950) radius Field hh mm ss.ss dd mm ss.s d ngp178 11 58 42.31 02 17 59.2 1 ngp179 12 04 35.46 02 17 59.2 1 ngp180 12 10 26.56 02 17 59.2 1 ...is equivalent to specifying the s6 ic1h switches on the command line, and indeed overrides any such switches that may have been specified on the command line. The first integer, 0, following the circle keyword is an id number, whose value here is irrelevant. The point of the id number is that it is sensible to stick to the same format in both input and output files, and it is useful for polygons in output files to be labelled with id numbers, to help keep track of things. The second integer, 1, following the circle keyword is the number of circles per line. Actually the arguments of the circle keyword could be omitted in this case, because mangle can deduce the number of circles by counting the number of angles, here 3, on each line.
If you create polygon files in circle format by using the oc switch, and you find that the precision of angles in the output polygon files is inadequate, then you should use the p[+]<n> switch to adjust the number <n> of digits after the decimal point in output angles.
4 1 3 2with elevation increasing upward, and azimuth increasing to the LEFT (as it does when you look at the sky with the north pole at zenith). Imagine that the above rectangle of numbers forms a constellation of 4 stars on the sky. Point at the stars with your right hand, and you see that the numbers increase righthandedly.
There must be at least 3 vertices per polygon: a polygon bounded by 1 vertex is illdefined, and a polygon bounded by 2 vertices is null. The interior angle at each vertex must be less than or equal to 180° (that is, the polygon must be convex; convex here means precisely that each interior angle must be less than or equal to 180°). It is up to you to ensure that your polygon is convex; mangle does not check that it is.
The general form of a line specifying a polygon in vertices format is
az_{1} el_{1} az_{2} el_{2} ... az_{n} el_{n}
which defines a polygon with n caps. In vertices format, a line with 2n angles defines a polygon with n caps.
If a successive pair of vertices is the same, then the line joining them is suppressed. Thus, for example, it is ok to specify a triangle by 4 vertices, with 2 of the vertices coincident.
If a successive pair of vertices is antipodeal, then the line joining them is quietly suppressed, since the great circle joining antipodeal pairs is not unique.
Here for example is part of the 2QZ 10k North holes file:
# RA3 dec3 RA4 dec4 RA2 dec2 RA1 dec1 plate hole field # 2.6431146954 0.0260858968 2.6431114304 0.0229366782 2.6462475007 0.0229342082 2.6462509201 0.0260833404 1 1 j10658_853 2.6387513686 0.0213119826 2.6387495321 0.0192968522 2.6407561104 0.0192953857 2.6407579987 0.0213104873 1 4 j10658_853 2.6176910610 0.0128549279 2.6176890352 0.0159353951 2.6207561335 0.0159372895 2.6207580623 0.0128568247 1 5 j10658_853 ...Each of the lines defines a polygon with 4 vertices. You can see from the header that I had to permute the columns of the original file, since mangle wants the vertices in order about the polygon, whereas the original file had the vertices in bowtie order.
A few lines down, the 2QZ 10k North holes file has the following line:
r 2.6601273142 0.0478372811 2.6548644982 0.0478373114 2.6548692406 0.0415046876 2.6601289920 0.0388904455 1 17 j10658_853which boasts a single character r (followed by a blank) at the beginning of the line. The initial r character is a flag (ok, a hack) that tells mangle to reverse the order of the vertices. The problem is that mangle wants the vertices ordered righthandedly about the polygon. If the vertices are ordered in the opposite direction, it specifies a different polygon (antipodeal to the desired polygon, since in vertices format the edges are great circles). In the original 2QZ 10k holes file, some of the vertices were ordered one way, and some the other. Rather than mess about permuting the numbers, I introduced the r flag, to tell mangle to reverse the order of vertices on that line.
The above holes file can be read with
iv4rin which v specifies the vertices format, the 4 specifies 4 vertices per line, and the r specifies radians. With 4 vertices per line, mangle expect 8 angles per line.
edges format can also be useful on input for defining certain kinds of polygons. If you know the angular positions of the vertices and a midpoint on each edge of your polygon, then edges format is a good choice  though read the caveat in the last paragraph of this section. Or, if you want to construct a polygon that passes exactly through some given angular position, then again edges format is a good way to do this.
The edges format is a soupedup version of the vertices format (see §5.4 above). Whereas the vertices format joins each pair of vertices with a great circle, the edges format uses an additional point, or additional points, between each pair of vertices to define the shape of the circle joining the vertices. There may be several points on each edge between a pair of vertices, but on input only one of the points between each pair of vertices  the first one not at the position of the first vertex  is used to define the shape of the circle; any additional points are ignored, and no check for consistency is made. An exception to this rule is that if there is only one edge, then the last point on the edge is taken to be a second vertex. On output, points are spaced uniformly along the edge between each pair of vertices. The vertices and edges points wind righthandedly about the enclosed polygon, as in
1 1 9 2 6 2 or 8 3 5 4 3 7 6 5 4with elevation increasing upward, and azimuth increasing to the LEFT (as it does when you look at the sky with the north pole at zenith). Imagine that the above triangles of numbers form constellations of stars on the sky. Point at the stars with your right hand, and you see that the numbers increase righthandedly. In the triangle above left, the points 1, 3, 5 are vertices, while the points 2, 4, 6 are edgepoints. In the triangle above right, the points 1, 4, 7 are vertices, and the remainder are edgepoints.
The form of a line specifying a polygon in edges format is
az_{1} el_{1} az_{2} el_{2} ... az_{m} el_{m} ... az_{mn} el_{mn}
which defines a polygon with n caps.
There are m points per edge, and n edges,
for a total of mn points.
A line with 2mn angles defines a polygon with n caps.
The sequence of points is

On input, edges format with <m> points per edge is specified with
ie<m>and on output
oe<m>The default is 2 points per edge, a vertex and a midpoint. On input, to specify <m> points per edge and <n> edges, for a total of <m> × <n> points, use
ie<m>,<n>The default is to deduce the number of edges from the number of angles on the line.
The only difference between edges format with 1 point per edge and vertices format is that on output edges writes points along all boundaries of a polygon, including boundaries which are circles with no intersections, whereas vertices does not record points on circles with no intersections, since such circles contain no vertices.
If all the points of a vertexedgepointsvertex sequence are the same, then the edge joining them is suppressed. Thus, for example, it is ok to specify a triangle by 4 edges, with 1 of the edges being degenerate.
If the two vertices of a vertexedgepointsvertex sequence differ, but the intervening edgepoints are all equal to either of the vertices, then the line joining them is taken to be a great circle, as in the vertices format.
In accordance with this rule, a polygon with one edge and 2 points per edge has one cap, whose boundary is a great circle running righthandedly from the vertex to the edgepoint and back around to the vertex.
On input in edges format, the usual rule is to discard all but one but one of the edgepoints between any pair of vertices. As a special case, however, if there is just one edge and there are 3 or more points per edge, then the edge is taken to define a polygon with a single cap, whose boundary is a circle running righthandedly from the vertex, through the first edgepoint not equal to the vertex, through the last edgepoint, and back around to the vertex.
To define a cap whose boundary is a nonintersecting circle that is not a great circle, it is necessary to specify either 1 edge with at least 3 points per edge, requiring at least 6 angles, or 2 or more edges with at least 2 points per edge, requiring at least 8 angles. Evidently this is less efficient than circle format, where a single cap is defined with just 3 angles. On output in edges format, each cap whose boundary is a nonintersecting circle is written with two edges.
If all the points of a vertexedgepointsvertex sequence are the same or antipodeal to each other, then the line joining them is quietly suppressed, since the great circle joining antipodeal pairs is not unique.
The interior angle at each vertex must be less than or equal to 180° (that is, the polygon must be convex; convex here means precisely that each interior angle must be less than or equal to 180°). It is up to you to ensure that your polygon is convex; mangle does not check that it is.
Warning:
Although the
edges format retains more information about a polygon
than the vertices format,
in general it does not retain all information about a polygon.
The only formats that retain all information are the circle
and polygon formats.
When mangle reads a polygon in edges format,
it converts each edge to a cap.
The resulting polygon is, as usual, taken to be the intersection of the caps.
As illustrated below,
this polygon may not be the same as the polygon you intended,
although in most cases it will be.
If a polygon file is translated from polygon format
into edge format and then back into polygon format,
then the final polygon file may not be exactly the same as the original.
A polygon in which the 6 points delineating the 3 edges of a triangle actually define a more complicated polygon, with two disconnected parts. 
The graphics format is similar to edges format, but is generally more economical. Whereas in edges format there is a specified number of points per edge, in graphics format there is a specified number of points per (2 pi) of azimuthal angle along each edge. Thus in graphics format curvier edges get more points than straighter edges.
For example, a triangular polygon in graphics format might have 6 vertices as follows:
1 6 5 4 3 2in which the three edges have zero, one, and two intermediate points.
The graphics format is implemented only as output, not as input, because of ambiguity in the interpretation of the format. That is, mangle can write a polygon file in graphics format, but it will refuse to read such a file.
On output, graphics format with m points per (2 pi) along each edge is specified with
og<m>The default is m = 2, giving 2 points per (2 pi) of azimuthal angle, which is a pretty miserable resolution. In practice you will probably want higher resolution, with m = 12 or more.
Warning: The azimuthal extent of a rectangle is constrained to be in the interval [0, pi] radians, or else to be a full circle of 2 pi radians. This follows from the requirement that a rectangle be a polygon, an intersection of caps. If the azimuthal extent is a full circle, azmax  azmin = 2 pi, then there is no azimuthal constraint. Otherwise the azmin limit is implemented with a hemispherical cap which constrains the azimuth to lie within [azmin, azmin + pi] (modulo 2 pi); similarly the azmax limit is implemented with a hemispherical cap which constrains the azimuth to lie within [azmax  pi, azmax] (modulo 2 pi). This works fine if the azimuthal extent (azmax  azmin)(modulo 2 pi) is less than or equal to pi, but if (azmax  azmin)(modulo 2 pi) exceeds pi, then the computed polygon will actually have azimuthal extent from azmax  pi to azmin + pi, which is probably not what was intended. In the latter case mangle issues a warning, but passes the rectangle through. It is up to you to make sure that every rectangle has azimuthal extent in the interval [0, pi] radians, or else to be a full circle of 2 pi radians.
A line in rectangle format looks like
azmin azmax elmin elmax
Here for example is a part of the 2QZ UKST North field file:
# 2dF QSO Redshift Survey: UKST field limits for the NGP # RA/Dec in radians, B1950, original APM coord. system # RA_min RA_max Dec_min Dec_max UKST_field 2.572862 2.660129 0.047837 0.039429 853 2.660129 2.746899 0.047563 0.039704 854 2.746899 2.833492 0.047460 0.039806 855 ...This can be read with
ir1rThe ir switch specifies that the input format is rectangle. The 1 on ir1 says to read only 1 rectangle on each line. The final r on ir1r declares that the angles are in radians. Actually, the 1 argument in ir1r is redundant, because mangle insists on only one rectangle per line. This is reasonable because the polygon defined by the intersection of two rectangles is itself a rectangle, so there is never any point in allowing more than one rectangle. Thus it suffices to specify
irrand the read will succeed, even though the lines of the input file contain trailing characters, namely the UKST field numbers.
In the above example, the command line switches can be omitted if the rectangle and unit keywords are specified in the input file, as in
rectangle unit r # 2dF QSO Redshift Survey: UKST field limits for the NGP # RA/Dec in radians, B1950, original APM coord. system # RA_min RA_max Dec_min Dec_max UKST_field 2.572862 2.660129 0.047837 0.039429 853 2.660129 2.746899 0.047563 0.039704 854 2.746899 2.833492 0.047460 0.039806 855 ...The rectangle keyword requires no arguments (any arguments present are ignored), because it is assumed (and required) that there is one rectangle per line.
It seems doubtful that one would want to create an original mask file in polygon format, since it is a bit peculiar, but it is the standard format used by the mangle software, since it specifies polygons in the manner expected for many years past by the fortran backend. If you don't like that, blame history, which can be blamed for a lot of things.
An entry for a polygon in polygon format looks like:
polygon <id> ( <n> caps, <double> weight, <double> str):
x_{0} y_{0} z_{0} cm_{0}
x_{1} y_{1} z_{1} cm_{1}
...
z_{n} y_{n} z_{n} cm_{n}
Each x_{i} y_{i} z_{i} is a unit vector (x_{i}^{2} + y_{i}^{2} + z_{i}^{2} = 1) defining the north polar axis of the cap, while cm_{i} = 1  cos(theta_{i}) defines the cap latitude, theta_{i} being the polar angle. Positive cm_{i} designates the region north of the latitude, while negative cm_{i} designates the region south of the latitude.
Here are two example polygons, the first two in 2QZ 10k North, specified in polygon format:
polygon 0 ( 6 caps, 0.736196 weight, 0.000207860166080 str): 0.9989940782261225 0.0200145430763467 0.0401279171473552 0.0001523048436087608 0.0000000000000000 0.0000000000000000 1.0000000000000000 1.0469757058067 0.9981574940502457 0.0455122767695589 0.0401279171473552 0.0001523048436087608 0.9991937369794350 0.0012752436969931 0.0401279171473552 0.0001523048436087608 0.9991645123188478 0.0373565773479794 0.0165759902112463 0.0001523048436087608 0.9998014206069079 0.0110614601624467 0.0165759902112463 0.0001523048436087608 polygon 1 ( 4 caps, 0.666667 weight, 0.000115712115129 str): 0.9981574940502457 0.0455122767695589 0.0401279171473552 0.0001523048436087608 0.0000000000000000 0.0000000000000000 1.0000000000000000 1.0469757058067 0.9989940782261225 0.0200145430763467 0.0401279171473552 0.0001523048436087608 0.9991645123188478 0.0373565773479794 0.0165759902112463 0.0001523048436087608
In accordance with the mangle philosophy of being as tolerant as possible of the format of input polygon files, the polygon lines in polygon format can be abbreviated on input. For example, the above excerpt from the 2QZ 10k North polygon file could be abbreviated to
polygon 0 6 0.9989940782261225 0.0200145430763467 0.0401279171473552 0.0001523048436087608 0.0000000000000000 0.0000000000000000 1.0000000000000000 1.0469757058067 0.9981574940502457 0.0455122767695589 0.0401279171473552 0.0001523048436087608 0.9991937369794350 0.0012752436969931 0.0401279171473552 0.0001523048436087608 0.9991645123188478 0.0373565773479794 0.0165759902112463 0.0001523048436087608 0.9998014206069079 0.0110614601624467 0.0165759902112463 0.0001523048436087608 polygon 1 4 0.9981574940502457 0.0455122767695589 0.0401279171473552 0.0001523048436087608 0.0000000000000000 0.0000000000000000 1.0000000000000000 1.0469757058067 0.9989940782261225 0.0200145430763467 0.0401279171473552 0.0001523048436087608 0.9991645123188478 0.0373565773479794 0.0165759902112463 0.0001523048436087608and mangle will still happily read it.
polygon <id> ( <n> caps, <double> weight, <double> str):in spolygon format the corresponding lines are a stripped down version consisting only of numbers:
<id> <n> <double> <double>
The is command line switch, which supposedly specifies that an input polygon file is in spolygon format, has no effect, although it is permitted. Similarly, the spolygon keyword is not required in the polygon file, although it is permitted. Instead, mangle detects that an input polygon file is in spolygon format from the presence of a line that starts with two integers, which are interpreted as specifying the id number <id> and the number <n> of caps of the polygon. Mangle expects such a line to be followed by <n> lines containing 4 real numbers on each line. To avoid misinterpretation, lines that start with two integers are considered as possible spolygon lines only if no other input format has been specified, either on the command line or with a keyword in the input polygon file. However, it is possible to switch from another format to spolygon format by explicitly prefixing a spolygon line with the spolygon keyword in the input polygon file.
To specify the spolygon format on output, use the os switch, as in
poly2poly os polygon_infile spolygon_outfile
For example, the first two polygons in in 2QZ 10k North, specified in spolygon format, are:
0 6 0.736196 0.000207860166080 0.9989940782261225 0.0200145430763467 0.0401279171473552 0.0001523048436087608 0.0000000000000000 0.0000000000000000 1.0000000000000000 1.0469757058067 0.9981574940502457 0.0455122767695589 0.0401279171473552 0.0001523048436087608 0.9991937369794350 0.0012752436969931 0.0401279171473552 0.0001523048436087608 0.9991645123188478 0.0373565773479794 0.0165759902112463 0.0001523048436087608 0.9998014206069079 0.0110614601624467 0.0165759902112463 0.0001523048436087608 1 4 0.666667 0.000115712115129 0.9981574940502457 0.0455122767695589 0.0401279171473552 0.0001523048436087608 0.0000000000000000 0.0000000000000000 1.0000000000000000 1.0469757058067 0.9989940782261225 0.0200145430763467 0.0401279171473552 0.0001523048436087608 0.9991645123188478 0.0373565773479794 0.0165759902112463 0.0001523048436087608
poly2poly oa polygon_infile area_outfilecreates a file area_outfile in area format which contains on successive lines the area and id of each polygon of polygon_infile.
poly2poly oi polygon_infile id_outfilecreates a file id_outfile in id format which contains on successive lines the id of each polygon of polygon_infile.
poly2poly om polygon_infile midpoint_outfilecreates a file midpoint_outfile in midpoint format which contains on successive lines a midpoint and id of each polygon of polygon_infile.
The midpoint selected by mangle is not guaranteed to be the midpoint, but it is guaranteed to lie inside the polygon, and mangle tries hard to select a point well inside the polygon, away from its edges. mangle tries several judiciously chosen trial points, and picks the best one, namely the one which is farthest from any edge of the polygon.
poly2poly ow polygon_infile weight_outfilecreates a file weight_outfile in weight format which contains on successive lines the weight and id of each polygon of polygon_infile.
Mangle requires both c and fortran 77 compilers.
Mangle is known to compile with the gnu versions of cc, f77, and make, namely with gcc, g77, and gmake.
It should be necessary to run snap only on the initial input files, not on balkanized or subsequent polygon files. On the other hand, running snap on balkanized or subsequent polygon files should be harmless, and in most cases should have no effect.
Whatever the case, if you are getting lots of incomprehensible error messages, your first reaction should be to run snap on the input polygon files.
Snapped polygon files should be stored in polygon (the default) or circle format, since other formats (edges, vertices, and rectangle) can lose information about having been snapped. All snapped files should be stored in the same format, to avoid introducing numerical discrepancies.
However, multiplyintersecting and kissing circles do pose a potential source of numerical problems, because the topology of the distribution of near multiplyintersecting and near kissing circles may vary depending on precisely how the intersections are computed, as illustrated in the animation below right. Mangle is equipped to deal with these problems, and is designed to cope in almost all cases. But it is possible to fool mangle with a sufficiently complicated polygon, for example a polygon whose vertices have a fractal distribution of separations.
Mangle can deal with this  and this  
and this  and this. 
The strategy adopted by mangle is to consider all vertices closer than a certain tolerance angle to be coincident. The algorithm is friendsoffriends: two vertices closer than the tolerance are friends, and a friend of a friend is a friend.
There is a command line switch
m<angle>[<unit>]that adjusts the initial tolerance angle for multiple intersections and kisses. You may want to use this switch if your polygons have many multiple intersections or kisses and the default tolerance proves too loose or too tight.
If you use the m switch in balkanizing your polygons, then you should make sure to use the m switch with the same tolerance angle in subsequent operations, for example with the unify or poly2poly commands.
You can find out the default value of the initial tolerance angle for multiple intersections with
balkanize dAs of writing (June 2003), the default initial angle is 10^{5} arcseconds.

If that is not the problem, then either you have a rather complicated polygon, like a fractal, or this is a genuine bug.
If it is a bug, I'd love to know. Please email me the following information:
Solution: Doublecheck the units, and the format in general. For example, the h unit tells balkanize that the RA and Dec in the input file(s) are in hms and °´" respectively, and that any other angle, such as the radius of a circular field, is in degrees.
Solution: Reorder the vertices righthandedly about the polygon. Alternatively, introduce an r character (followed by a blank) as the first character of each line of vertices that you wish to reverse.
Solution: Reorder the points righthandedly about the polygon. Alternatively, introduce an r character (followed by a blank) as the first character of each line of points that you wish to reverse.
poly2poly k1e10 polygon_infile polygon_outfilecopies polygon file polygon_infile to polygon file polygon_outfile keeping only polygons with areas greater than or equal to 1e10 steradians.
But if you want to get rid of zero weight polygons without unifying them, then use the j switch on the poly2poly command. For example
poly2poly j1e10 polygon_infile polygon_outfilecopies polygon file polygon_infile to polygon file polygon_outfile keeping only polygons with weights greater than or equal to 1e10.
A nonsimplyconnected polygon. 
Solution: It's not a problem.
Alternative diagnosis: When balkanizing, you used the m<angle> switch to specify a nondefault value for the tolerance <angle> for multiple intersections.
Solution: Use the m<angle> switch with the same tolerance <angle> when converting your file to graphics format. More generally, if you use the m<angle> switch, then you should apply the switch consistently with the same tolerance <angle> in all mangle commands.
Solution:
WARNING: The following hack only works if each number in the unformatted fortran file is a single word, i.e. an INTEGER or REAL (not DOUBLE PRECISION). 
1. 
Make a cpio archive file from the original files, as in
ls 1 file1 file2 ...  cpio o > files.cpioNotice that the switch 1 is a one, not an ell. 
2. 
Move the cpio archive to another directory where it will not overwrite
the old files
mv files.cpio other_directory 
3. 
Extract the files from the cpio archive in the new directory
cd other_directory cpio i b < files.cpioThe b switch is the thing that does the byteswapping. 
harmonize pretty.poly 
polygon 0 ( 0 caps, 1 weight, 12.56637061435917 str):The line could be abbreviated to
polygon 0 0which specifies a polygon of 0 caps, with a default weight of 1.
Similarly, in circle format, the allsky polygon can be specified with
circle 0 0or more verbosely with
circle 0 ( 0 caps, 1 weight, 12.56637061435917 str):Normally, a line of the form
circle 0 nin a polygon file (n is some integer) would instruct mangle to expect subsequent lines in the file to contain n circles per line. However, for the particular case where n is zero, mangle assumes that only one polygon can be an allsky polygon. Therefore, it is essential that the format be reinitialized following the declaration of an allsky polygon, as for example in
circle 0 0 circle az_{1} el_{1} th_{1} ... az_{n} el_{n} th_{n} ...The first line, circle 0 0, specifies an allsky polygon (you can add an optional blank line for clarity, if you want), while the circle keyword on the second line instructs mangle that subsequent lines are in circle format. The fact that circle appears with no arguments declares that the number of circles per line is variable; mangle deduces the number of circles from the number of angles it finds in a line.
1. 
As always, start by running snap:
snap holes.pol jhwhere you may need to use the i.. switch to specify the format of the input polygon file holes.pol. 
2.  Edit the snap'd output polygon file jh so that the weights of all polygons are zero. A weight of 0 will cause balkanize to treat the holes as being empty. 
3. 
Run balkanize on the allsky polygon file allsky.pol
(in the mangle/masks/allsky/ directory)
and the editted polygon file jh of excluded regions:
balkanize allsky.pol jh jbThe order here is important, the allsky file allsky.pol first and the holes file jh second, because you want the holes to override the allsky. If the allsky file came second, it would override the holes, the net result (after much worthless work) being allsky again. 
4. 
Run unify on the balkanized polygon file jb:
unify jb complement.polVoilà. You have a polygon file complement.pol defining the complement of your mask. 
If the resulting set of balkanized polygons looks a mess, or if you think there are more balkanized polygons than there should be, then you might consider creating a special allsky.pol polygon file that subdivides the whole sky in a judiciously chosen fashion better matched to the geometry of your holes. See mangle/masks/pscz/allsky.rect for an example.
In practice, you could proceed as follows:
1. 
As always, start by running snap:
snap holes.pol jhwhere you may need to use the i.. switch to specify the format of the input polygon file holes.pol. 
2.  Edit the snap'd output polygon file jh so that the weights of all polygons are 1. A weight of 1 will cause harmonize to subtract (add with weight 1) the harmonics of each excluded polygon in jh. 
3. 
Run harmonize
on the combination of the allsky polygon in allsky.pol
(in the mangle/masks/allsky/ directory)
and the holes in jh
harmonize l<lmax> allsky.pol jh complement.wlmThe file complement.wlm contains the harmonics of the sky less the excluded regions. 