From 7c1fbc0bc23f9f68d575252a37858552ba2a8e82 Mon Sep 17 00:00:00 2001 From: David Berry Date: Thu, 2 Oct 2014 17:57:22 +0100 Subject: [PATCH] smurf: Handle HPX discontinuity at RA=12h --- applications/smurf/libsmf/Makefile.am | 3 + applications/smurf/libsmf/jsatiles.h | 37 ++- applications/smurf/libsmf/smf_getrefwcs.c | 127 +++------ applications/smurf/libsmf/smf_jsadicer.c | 74 +++--- applications/smurf/libsmf/smf_jsaproj.c | 142 ++++++++++ .../smurf/libsmf/smf_jsaproj_fromstr.c | 112 ++++++++ applications/smurf/libsmf/smf_jsaproj_tostr.c | 108 ++++++++ applications/smurf/libsmf/smf_jsatile.c | 54 ++-- applications/smurf/libsmf/smf_jsatileheader.c | 249 +++++++++++++----- applications/smurf/libsmf/smf_jsatiles_data.c | 10 +- .../smurf/libsmf/smf_jsatiles_region.c | 13 +- applications/smurf/libsmf/smf_jsatilexyconv.c | 174 +++++++----- applications/smurf/libsmurf/smurf_jsadicer.c | 32 +-- applications/smurf/libsmurf/smurf_jsapaster.c | 53 +++- .../smurf/libsmurf/smurf_jsatileinfo.c | 72 +++-- .../smurf/libsmurf/smurf_jsatilelist.c | 18 +- applications/smurf/libsmurf/smurf_makecube.c | 4 +- applications/smurf/libsmurf/smurf_makemap.c | 4 +- applications/smurf/scripts/jsajoin.py | 24 +- applications/smurf/scripts/jsasplit.py | 77 ++---- applications/smurf/scripts/starutil.py | 20 +- applications/smurf/smurf.ifd.in | 20 +- 22 files changed, 981 insertions(+), 446 deletions(-) create mode 100644 applications/smurf/libsmf/smf_jsaproj.c create mode 100644 applications/smurf/libsmf/smf_jsaproj_fromstr.c create mode 100644 applications/smurf/libsmf/smf_jsaproj_tostr.c diff --git a/applications/smurf/libsmf/Makefile.am b/applications/smurf/libsmf/Makefile.am index 9ded0463270..8b334b3341a 100644 --- a/applications/smurf/libsmf/Makefile.am +++ b/applications/smurf/libsmf/Makefile.am @@ -281,6 +281,9 @@ smf_isfft.c \ smf_iteratemap.c \ smf_jsainstrument.c \ smf_jsadicer.c \ +smf_jsaproj.c \ +smf_jsaproj_fromstr.c \ +smf_jsaproj_tostr.c \ smf_jsatileheader.c \ smf_jsatile.c \ smf_jsatiling.c \ diff --git a/applications/smurf/libsmf/jsatiles.h b/applications/smurf/libsmf/jsatiles.h index 26c48a51052..b8dfb279d33 100644 --- a/applications/smurf/libsmf/jsatiles.h +++ b/applications/smurf/libsmf/jsatiles.h @@ -15,6 +15,19 @@ typedef enum { } smf_inst_t; +/* The four HPX-related projections available for mosaics of JSA + tiles. The projection for a mosaic is chosen in order to avoid any + discontinuities being present within the mosaic. Individual JSA tiles + always use SMF__JSA_HPX. */ +typedef enum { + SMF__JSA_NULL, /* Not an JSA projection */ + SMF__JSA_HPX, /* HPX projection centred on RA=0, Dec=0 */ + SMF__JSA_HPX12, /* HPX projection centred on RA=12h, Dec=0 */ + SMF__JSA_XPHN, /* XPH projection centred on RA=0, Dec=90 */ + SMF__JSA_XPHS /* XPH projection centred on RA=0, Dec=-90 */ +} smf_jsaproj_t; + + /* Struct to store information about the JSA tiling scheme for a given JCMT instrument. */ @@ -37,14 +50,15 @@ void smf_jsainstrument( const char *param, AstFitsChan *fc, smf_inst_t def, smfJSATiling *tiling, int *status ); void smf_jsadicer( int indf, const char *base, int trim, - smf_inst_t instrument, int usexph, size_t *ntile, - Grp *grp, int *status ); -void smf_jsatile( int itile, smfJSATiling *jsatiling, - int local_origin, int usexph, AstFitsChan **fc, + smf_inst_t instrument, smf_jsaproj_t proj, + size_t *ntile, Grp *grp, int *status ); +void smf_jsatile( int itile, smfJSATiling *jsatiling, int local_origin, + smf_jsaproj_t proj, AstFitsChan **fc, AstFrameSet **fs, AstRegion **region, int lbnd[2], int ubnd[2], int *status ); -AstFitsChan *smf_jsatileheader( int itile, smfJSATiling *jsatiling, - int local_origin, int usexph, int *move, int *status ); +AstFitsChan *smf_jsatileheader( int itile, smfJSATiling *skytiling, + int local_origin, smf_jsaproj_t proj, + int *move, int *status ); void smf_jsatilei2xy( int itile, smfJSATiling *jsatiling, int *xt, int *yt, int *fi, int *status ); int * smf_jsatiles_region( AstRegion *region, smfJSATiling *tiling, @@ -53,9 +67,12 @@ int * smf_jsatiles_data( ThrWorkForce *wf, Grp *igrp, size_t size, smfJSATiling *tiling, int *ntile, int *status ); int smf_jsatilexy2i( int xt, int yt, smfJSATiling *jsatiling, int *status ); -void smf_jsatilexyconv( smfJSATiling *skytiling, int usexph, int xt_hpx, - int yt_hpx, int *xt_out, int *yt_out, int *status ); +void smf_jsatilexyconv( smfJSATiling *skytiling, smf_jsaproj_t proj, + int xt_hpx, int yt_hpx, int raw, int *xt_out, + int *yt_out, int *status ); void smf_jsatiling( smf_inst_t instrument, smfJSATiling *jsatiling, int *status ); - - +smf_jsaproj_t smf_jsaproj( int ntile, const int *tiles, + smfJSATiling *skytiling, int *status ); +smf_jsaproj_t smf_jsaproj_fromstr( const char *str, int rep, int *status ); +const char * smf_jsaproj_tostr( smf_jsaproj_t proj, int *status ); diff --git a/applications/smurf/libsmf/smf_getrefwcs.c b/applications/smurf/libsmf/smf_getrefwcs.c index a459a2e9f29..02bb4f1b4b5 100644 --- a/applications/smurf/libsmf/smf_getrefwcs.c +++ b/applications/smurf/libsmf/smf_getrefwcs.c @@ -20,10 +20,10 @@ * param = const char * (Given) * The name of the ADAM parameter used to get the reference NDF. A * value of "JSA" may also be provided for the parameter, in which -* case the WCS defined by the JSA all-sky pixel grid is returned. -* The choice of JSA projection (HPX, XPHS or XPHN) is based on -* whether the map crosses an HPX discontinuity. Alternatively, -* "JSA-HPX", "JSA-XPHS" or "JSA-XPHN" can be supplied if it is +* case the WCS defined by the SMF__JSA_HPX all-sky projection is +* returned. The suitable JSA projection is chosen to ensure that +* the map does not cross any discontinuities. Alternatively, +* "HPX", "HPX12", "XPHS" or "XPHN" can be supplied if it is * necessary to specifiy the JSA projection explicitly. * igrp = Grp * (Given) * A group holding the paths to the input science files. The first @@ -91,10 +91,12 @@ * 26-AUG-2014 (DSB): * Allow some tolerance for rounding errors when checking whether the * observation instersects an HPX discontinuity. +* 1-OCT-2014 (DSB): +* Added support for HPX projections centred on RA=12h. * {enter_further_changes_here} * Copyright: -* Copyright (C) 2007,2013 Science & Technology Facilities Council. +* Copyright (C) 2007,2013-2014 Science & Technology Facilities Council. * All Rights Reserved. * Licence: @@ -146,22 +148,20 @@ void smf_getrefwcs( const char *param, Grp *igrp, AstFrameSet **specwcs, AstMapping *splitmap = NULL; /* Mapping from required wcs to PIXEL coords */ AstRegion *circle; char text[ 255 ]; /* Parameter value */ - double centre[ 2 ]; - double hpxlat[] = {0.0, 90.0, 180.0, 270.0 }; - double p0[ 2 ]; - double radius; + int *tiles; int i; int inax[ 2 ]; /* Indices of required WCS axes */ int jsatiles; int lbnd[2]; /* Lower pixel index bounds of mid tile */ + int ntile; int outax[ 7 ]; /* Indices of corresponding PIXEL axes */ int refndf; /* NDF identifier for the refence NDF */ int ubnd[2]; /* Upper pixel index bounds of mid tile */ - int usexph; size_t code; smfData *data = NULL; /* Structure describing 1st input file */ smfJSATiling skytiling; smf_inst_t inst = SMF__INST_NONE; + smf_jsaproj_t proj; /* Specific JSA projection to use */ smf_subinst_t subinst; /* Initialise the returned values. */ @@ -193,9 +193,11 @@ void smf_getrefwcs( const char *param, Grp *igrp, AstFrameSet **specwcs, if( *status == PAR__NULL ) { errAnnul( status ); -/* If it is "JSA", we return WCS that describes the JSA all-sky pixel grid. */ +/* If it is "JSA", or one of the JSA projection codes, we return WCS that + describes one of the the JSA all-sky pixel grids. */ } else if( *status == SAI__OK ) { - if( astChrMatchN( text, "JSA", 3 ) ) { + proj = smf_jsaproj_fromstr( text, 0, status ); + if( astChrMatch( text, "JSA" ) || proj != SMF__JSA_NULL ) { *isjsa = 1; /* Report an error if the instrument cannot be determined. */ @@ -239,9 +241,6 @@ void smf_getrefwcs( const char *param, Grp *igrp, AstFrameSet **specwcs, instrument. */ smf_jsatiling( inst, &skytiling, status ); -/* Assume the HPX projection is to be used. */ - usexph = 0; - /* For "JSA" - choose the best projection. */ if( astChrMatch( text, "JSA" ) ) { @@ -253,88 +252,42 @@ void smf_getrefwcs( const char *param, Grp *igrp, AstFrameSet **specwcs, /* Convert the circle to ICRS (as used by the JSA all-sky grid). */ astSetC( circle, "System", "ICRS" ); -/* Get the centre and radius of this circle. */ - astCirclePars( circle, centre, &radius, NULL ); - if( ( centre[ 0 ] == AST__BAD || centre[ 1 ] == AST__BAD || - radius == AST__BAD ) && *status == SAI__OK ) { - *status = SAI__ERROR; - errRep( "", "smf_getrefwcs: the centre and/or radius of " - "the map is undefined.", status ); - } - -/* See if the observation may straddle the gap between two polar cusps of - the standard JSA HPX-projected all-sky grid. If it does, we need to - swap to use an XPH (polar-HEALPix) projection instead since otherwise - the map will probably be too big (in pixels) to create. The gaps are - defined by the sections of meridians at longitude=0, 90, 180, 270 that - have absolute latitude greater than 41.8103 degrees (the latitude of - the transition between the equatorial and polar regions of the HPX - projection). If the offset in longitude between the circle centre and - any of these meridians is less than the radius, then we may have an - intersection. Check each meridian in turn. */ - usexph = 0; - for( i = 0; i < 4; i++ ) { - -/* Get the coords of the point on the meridian which is at the same - latitude as the circle centre. */ - p0[ 0 ] = AST__DD2R*hpxlat[ i ]; - p0[ 1 ] = centre[ 1 ]; - -/* If the arc-distance between this point and the circle centre is less - than the radius, the circle intersects the meridian. Use twice the - radius to allow some tolerance (there's no real harm in using XPH - rather than HPX in the polar regions so it's better to be safe). */ - if( fabs( astDistance( circle, centre, p0 ) <= 2*radius ) ) { - -/* If the circle centre is above the northern transitional latitude, we - need to use the XPH projection centred on the north pole. */ - if( centre[ 1 ] > AST__DD2R*SMF__HPX_TRANS ) { - msgOutif( MSG__VERB, "", "The Map will be created " - "using an XPH projection centred on the " - "north pole.", status ); - usexph = 1; - break; - -/* If the circle centre is below the southern transitional latitude, we - need to use the XPH projection centred on the south pole. */ - } else if( centre[ 1 ] < -AST__DD2R*SMF__HPX_TRANS ) { - msgOutif( MSG__VERB, "", "The Map will be created " - "using an XPH projection centred on the " - "south pole.", status ); - usexph = -1; - break; - } - } - } - -/* If a projection was specified, use it. */ - } else if( astChrMatch( text, "JSA-HPX" ) ) { - usexph = 0; +/* Get a list of the tiles that touch this circle. */ + tiles = smf_jsatiles_region( circle, &skytiling, + &ntile, status ); - } else if( astChrMatch( text, "JSA-XPHN" ) ) { - usexph = 1; +/* Choose the best projection (i.e. the projection that puts the circle + furthest away from any singularities). */ + proj = smf_jsaproj( ntile, tiles, &skytiling, status); - } else if( astChrMatch( text, "JSA-XPHS" ) ) { - usexph = -1; +/* Free resources. */ + tiles = astFree( tiles ); + circle = astAnnul( circle ); - } else if( *status == SAI__OK ) { +/* If a good projection was specified, use it. Otherwise report an error. */ + } else if( proj == SMF__JSA_NULL && *status == SAI__OK ) { *status = SAI__ERROR; errRepf( "", "Bad value '%s' supplied for parameter %s.", status, text, param ); } -/* Get the WCS FrameSet for what was the central tile in the old - raster-based indexing scheme - since we do not use the "local-origin" - option, the WCS for every tile is identical. The base Frame will be +/* Report the projection type. */ + msgOutf( " ", "The %s will be created on the JSA %s " + "pixel grid.", status, + (data->hdr->instrument==INST__ACSIS)?"cube":"map", + smf_jsaproj_tostr( proj, status ) ); + +/* All tiles within the same JSA projection use the same WCS, so we get + the WCS FrameSet for an arbitrary central tile, and use it for the + full map. The exception is that tiles within the HPX facet that is + split between bottom-left and top-right, use a different WCS (they + have different reference points). But our choice of projection should + mean that the map never falls in that facet. The base Frame will be GRID coords within the tile, and the current Frame will be ICRS - (RA,Dec). This used to be the central tile in numerical order, not - in spatial position. In other words, it was the lower of the two middle - tiles in numerical order. This tile is in the north west corner of - HPX facet 0, so in the new nested scheme, it has number 0 * ntpf^2 + all - the odd bits of the index within the tile. */ + (RA,Dec). */ smf_jsatile( ((skytiling.ntpf * skytiling.ntpf - 1) * 2) / 3, - &skytiling, 0, usexph, - NULL, spacewcs, NULL, lbnd, ubnd, status ); + &skytiling, 0, proj, NULL, spacewcs, NULL, lbnd, + ubnd, status ); /* Change the base Frame to be PIXEL. */ for( i = 1; i <= astGetI( *spacewcs, "NFrame" ); i++ ) { diff --git a/applications/smurf/libsmf/smf_jsadicer.c b/applications/smurf/libsmf/smf_jsadicer.c index 25103f3b152..f81155ea1dd 100644 --- a/applications/smurf/libsmf/smf_jsadicer.c +++ b/applications/smurf/libsmf/smf_jsadicer.c @@ -15,15 +15,16 @@ * Invocation: * void smf_jsadicer( int indf, const char *base, int trim, -* smf_inst_t instrument, int usexph, size_t *ntile, -* Grp *grp, int *status ) +* smf_inst_t instrument, smf_jsaproj_t proj, +* size_t *ntile, Grp *grp, int *status ) * Arguments: * indf = int (Given) * An identifier for the NDF to be diced. This may be 2D or 3D. The -* NDF is assumed to be gridded on the JSA all-sky pixel grid (either -* HPX or XPH), and the current Frame of the NDF's WCS FrameSet must -* contain an ICRS SkyFrame (but they need not be axes 1 and 2). +* NDF is assumed to be gridded on one of the supported JSA all-sky +* pixel grids (some flavour of HPX or XPH projection), and the +* current Frame of the NDF's WCS FrameSet must contain an ICRS +* SkyFrame (but they need not be axes 1 and 2). * base = const char * (Given) * The base path for the output NDFs. Each tile index, preceeded by * and underscore, will be appended to this base name to create the @@ -36,11 +37,9 @@ * remove any blank borders. * instrument = smf_inst_t (Given) * The instrument that created the supplied NDF. -* usexph = int (Given) -* Specified the projection to use for the created tiles. A value -* of zero means use the normal equatorial HPX projection. If greater -* than zero, a north polar HEALPix (XPH) projection is used. If -* less than zero, a south polar HEALPix (XPH) projection is used. +* proj = smf_jsaproj_t (Given) +* Specified the projection to use for the created tiles. Should +* always be SMF__JSA_HPX, except for debugging or experiments. * ntile = * size_t (Returned) * The number of tiles created. * grp = * Grp (Returned) @@ -56,9 +55,9 @@ * the JSA all-sky pixel grids (either HPX or XPH). * * A new output NDF is generated for each tile touched by the supplied -* NDF. Each output NDF uses the JSA standard HPX pixel grid. An STC-S -* polygon is created describing the spatial outline of the good data -* values in the NDF, and stored in NDF extension OUTLINE. +* NDF. Each output NDF uses the projection requested by "proj". An +* STC-S polygon is created describing the spatial outline of the good +* data values in the NDF, and stored in NDF extension OUTLINE. * * The zero-based indicies of the created tiles are written to an output * paramater called "JSATILELIST". @@ -89,7 +88,7 @@ * 19-JUN-2014 (DSB): * Major changes to allow the input NDF to be in XPH projection. * 25-JUN-2014 (DSB): -* Added argument "usexph"m to allow the output projection to be +* Added argument "usexph" to allow the output projection to be * chosen. * 7-JUL-2014 (DSB): * Ensure the output NDFs inherited the Epoch value of the input NDF. @@ -102,9 +101,11 @@ * avoid tailes that span RA=12h being wrapped round to the far * side of the projection, thus producing a huge box. * 30-SEP-2014 (DSB): -* Only disable lon/lat wrapping for tiles that span RA=12h. The -* other tiles in the split HPX facet require lon/lat wrapping to +* Only disable lon/lat wrapping for tiles that span RA=12h. The +* other tiles in the split HPX facet require lon/lat wrapping to * be on, in order to work properly. +* 1-OCT-2014 (DSB): +* Add support for HPX projections centred on RA=12h. * {enter_further_changes_here} * Copyright: @@ -155,7 +156,7 @@ static void smf1_jsadicer( int indfo, int *olbnd, int *oubnd, /* Main entry */ void smf_jsadicer( int indf, const char *base, int trim, smf_inst_t instrument, - int usexph, size_t *ntile, Grp *grp, int *status ){ + smf_jsaproj_t proj, size_t *ntile, Grp *grp, int *status ){ /* Local Variables: */ AstBox *box; @@ -276,9 +277,9 @@ void smf_jsadicer( int indf, const char *base, int trim, smf_inst_t instrument, } /* Get the bounds of the NDF in pixel indices and the the corresponding - double precision GRID bounds (reduce the size of the grid by a amslla - mount to avoid problems with tiles that are on the edge of the valid sky - regions - astMapRegion can report na error for such tiles). Also store + double precision GRID bounds (reduce the size of the grid by a small + amount to avoid problems with tiles that are on the edge of the valid sky + regions - astMapRegion can report an error for such tiles). Also store the GRID coords of the centre. Also count the number of significant pixel axes. */ ndfBound( indf, 3, lbnd, ubnd, &ndim, status ); @@ -388,14 +389,14 @@ void smf_jsadicer( int indf, const char *base, int trim, smf_inst_t instrument, for( itile = 0; itile < ntiles && *status == SAI__OK; itile++ ) { tile_index = tiles[ itile ]; -/* Get the spatial pixel bounds of the current tile within the JSA all-sky - pixel grid. Also get the (2D) WCS FrameSet for the tile. */ - smf_jsatile( tile_index, &tiling, 0, usexph, NULL, &tile_wcs, NULL, +/* Get the spatial pixel bounds of the current tile within the requested + JSA all-sky projection. Also get the (2D) WCS FrameSet for the tile. */ + smf_jsatile( tile_index, &tiling, 0, proj, NULL, &tile_wcs, NULL, tile_lbnd, tile_ubnd, status ); /* We need the mapping from the N-dimensional input NDF pixel coord. system to the N-dimensional output NDF pixel coord. system. This will be the - same for all tiles, so only do it once. */ + same for all tiles within the requested projection, so only do it once. */ if( !p2pmap ){ /* Extract the tile pixel->WCS mapping and WCS Frame. We know the indices @@ -501,10 +502,14 @@ void smf_jsadicer( int indf, const char *base, int trim, smf_inst_t instrument, lbnd_out + 2, ubnd_out + 2, NULL, NULL ); -/* Tiles that straddle RA=12h will produce very big bounding boxes - because half of the tile will be wrapped round to the other side of the - all-sky grid. Test for this, and if found, re-calculate the bounding - boxes without wrapping WCS values within the WcsMap class. */ +/* Tiles that straddle RA=12h (for SMF__JSA_HPX) or RA=0h (for + SMF__JSA_HPX12) will produce very big bounding boxes because half + of the tile will be wrapped round to the other side of the all-sky grid. + Test for this, and if found, re-calculate the bounding boxes without + wrapping WCS values within the WcsMap class. NOTE - we should never + find any such tiles because the projection for the input NDF should + have been chosen to put the valid data well away from the above RA + values). */ if( ubnd_out[0] - lbnd_out[0] > 10000 || ubnd_out[1] - lbnd_out[1] > 10000 ) { old_wrap = astGetWcsWrap; @@ -794,17 +799,14 @@ static void smf1_jsadicer( int indfo, int *olbnd, int *oubnd, * The mapping from pixel coords in the input NDF to pixel coords in * the output NDF. * ipd = void * (Given) -* Pointer to the start of the input data array. It should have -* bounds given by "lbnd_tile" and "ubnd_tile". If this is NULL, +* Pointer to the start of the input data array. If this is NULL, * the existing contents of the NDF are used as input. * ipv = void * (Given) -* Pointer to the start of the input variance array. It should have -* bounds given by "lbnd_tile" and "ubnd_tile". Should be NULL if -* no variances are available. +* Pointer to the start of the input variance array. Should be NULL +* if no variances are available. * ipq = unsigned char * (Given) -* Pointer to the start of the input quality array. It should have -* bounds given by "lbnd_tile" and "ubnd_tile". Should be NULL if -* no quality is available. +* Pointer to the start of the input quality array. Should be NULL +* if no quality is available. * status = int * (Given) * Pointer to the inherited status variable. */ diff --git a/applications/smurf/libsmf/smf_jsaproj.c b/applications/smurf/libsmf/smf_jsaproj.c new file mode 100644 index 00000000000..43cf5393721 --- /dev/null +++ b/applications/smurf/libsmf/smf_jsaproj.c @@ -0,0 +1,142 @@ +/* +*+ +* Name: +* smf_jsaproj + +* Purpose: +* Choose a JSA projection to map a given set of tiles. + +* Language: +* Starlink ANSI C + +* Type of Module: +* C function + +* Invocation: +* smf_jsaproj_t proj = smf_jsaproj( int ntile, const int *tiles, +* smfJSATiling *skytiling, int *status ) + +* Arguments: +* ntile = int (Given) +* The number of tiles supplied in "tiles[]". +* tiles = const int * (Given) +* A list of tile indices. +* skytiling = smfJSATiling * (Given) +* Pointer to a structure holding parameters describing the tiling +* scheme used for the required JCMT instrument, as returned by +* function smf_jsatiling. +* status = int * (Given) +* Pointer to the inherited status variable. + +* Returned Value: +* The type of JSA projection to use. + +* Description: +* This function determines the type of JSA projection to use for a +* map that coveres a given set of tiles. The projection that produces +* the smallest map is chosenb. + +* Authors: +* DSB: David S Berry (JAC, UCLan) +* {enter_new_authors_here} + +* History: +* 1-OCT-2014 (DSB): +* Initial version. +* {enter_further_changes_here} + +* Copyright: +* Copyright (C) 2014 Science & Technology Facilities Council. +* All Rights Reserved. + +* Licence: +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 3 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be +* useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public +* License along with this program; if not, write to the Free +* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +* MA 02111-1307, USA + +* Bugs: +* {note_any_bugs_here} +*- +*/ + +/* Starlink includes */ +#include "sae_par.h" +#include "ast.h" +#include "mers.h" + +/* SMURF includes */ +#include "libsmf/smf.h" +#include "libsmf/jsatiles.h" + +smf_jsaproj_t smf_jsaproj( int ntile, const int *tiles, + smfJSATiling *skytiling, int *status ){ + +/* Local Variables: */ + smf_jsaproj_t result; + smf_jsaproj_t proj[ 4 ] = { SMF__JSA_HPX, SMF__JSA_HPX12, + SMF__JSA_XPHN, SMF__JSA_XPHS }; + int iproj; + int itile; + int lbnd[2]; + int ubnd[2]; + int box_lbnd[2]; + int box_ubnd[2]; + size_t box_nel; + size_t minnel = 0; + +/* Initialise the returned value. */ + result = SMF__JSA_HPX; + +/* Check inherited status */ + if( *status != SAI__OK ) return result; + +/* Try all four JSA projections. */ + for( iproj = 0; iproj < 4; iproj++ ) { + +/* Initialise the bounding box. */ + box_lbnd[ 0 ] = INT_MAX; + box_lbnd[ 1 ] = INT_MAX; + box_ubnd[ 0 ] = -INT_MAX; + box_ubnd[ 1 ] = -INT_MAX; + +/* Loop over all the supplied tiles. */ + for( itile = 0; itile < ntile; itile++ ) { + +/* Get the bounds of the current tile using the current projection. */ + smf_jsatile( tiles[ itile ], skytiling, 0, proj[ iproj ], + NULL, NULL, NULL, lbnd, ubnd, status ); + +/* Extend the bounding box to include the current tile. */ + if( lbnd[ 0 ] < box_lbnd[ 0 ] ) box_lbnd[ 0 ] = lbnd[ 0 ]; + if( lbnd[ 1 ] < box_lbnd[ 1 ] ) box_lbnd[ 1 ] = lbnd[ 1 ]; + if( ubnd[ 0 ] > box_ubnd[ 0 ] ) box_ubnd[ 0 ] = ubnd[ 0 ]; + if( ubnd[ 1 ] > box_ubnd[ 1 ] ) box_ubnd[ 1 ] = ubnd[ 1 ]; + } + +/* Get the number of pixels in the bounding box. */ + box_nel = ( box_ubnd[ 0 ] - box_lbnd[ 0 ] + 1 )*( box_ubnd[ 1 ] - box_lbnd[ 1 ] + 1 ); + +/* If this is smaller than all previous projections, record the current + projection as the best projection. */ + if( iproj == 0 || box_nel < minnel ) { + minnel = box_nel; + result = proj[ iproj ]; + } + } + + return result; +} + + + diff --git a/applications/smurf/libsmf/smf_jsaproj_fromstr.c b/applications/smurf/libsmf/smf_jsaproj_fromstr.c new file mode 100644 index 00000000000..625589c293b --- /dev/null +++ b/applications/smurf/libsmf/smf_jsaproj_fromstr.c @@ -0,0 +1,112 @@ +/* +*+ +* Name: +* smf_jsaproj_fromstr + +* Purpose: +* Convert a string to a JSA projection type. + +* Language: +* Starlink ANSI C + +* Type of Module: +* C function + +* Invocation: +* smf_jsaproj_t smf_jsaproj_fromstr( const char *str, int rep, int *status ) + +* Arguments: +* str = const char * (Given) +* The string - should be one of "HPX", "HPX12", "XPHN" or "XPHS" +* (case insensitive). +* rep = int (Given) +* If none-zero, report an error if the supplied string is not +* recognised. +* status = int * (Given) +* Pointer to the inherited status variable. + +* Returned Value: +* The JSA projection identifier. SMF__JSA_NULL is returned if the +* supplied string is unknown, or if an error has already occurred. + +* Description: +* This function returns an identifier for the type of JSA projection +* specified by the supplied string. + +* Authors: +* DSB: David S Berry (JAC, UCLan) +* {enter_new_authors_here} + +* History: +* 2-OCT-2014 (DSB): +* Initial version. +* {enter_further_changes_here} + +* Copyright: +* Copyright (C) 2014 Science & Technology Facilities Council. +* All Rights Reserved. + +* Licence: +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 3 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be +* useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public +* License along with this program; if not, write to the Free +* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +* MA 02111-1307, USA + +* Bugs: +* {note_any_bugs_here} +*- +*/ + +/* Starlink includes */ +#include "sae_par.h" +#include "mers.h" +#include "ast.h" + +/* SMURF includes */ +#include "libsmf/smf.h" +#include "libsmf/jsatiles.h" + +smf_jsaproj_t smf_jsaproj_fromstr( const char *str, int rep, int *status ){ + +/* Local Variables: */ + smf_jsaproj_t result; + +/* Initialise the returned value. */ + result = SMF__JSA_NULL; + +/* Check inherited status */ + if( *status != SAI__OK ) return result; + +/* Do it. */ + if( astChrMatch( str, "HPX" ) ){ + result = SMF__JSA_HPX; + + } else if( astChrMatch( str, "HPX12" ) ){ + result = SMF__JSA_HPX12; + + } else if( astChrMatch( str, "XPHN" ) ){ + result = SMF__JSA_XPHN; + + } else if( astChrMatch( str, "XPHS" ) ){ + result = SMF__JSA_XPHS; + + } else if( rep ){ + *status = SAI__ERROR; + errRepf( " ", "Bad JSA projection type '%s' supplied.", status, str ); + } + + return result; +} + + + diff --git a/applications/smurf/libsmf/smf_jsaproj_tostr.c b/applications/smurf/libsmf/smf_jsaproj_tostr.c new file mode 100644 index 00000000000..69f8274f108 --- /dev/null +++ b/applications/smurf/libsmf/smf_jsaproj_tostr.c @@ -0,0 +1,108 @@ +/* +*+ +* Name: +* smf_jsaproj_tostr + +* Purpose: +* Convert JSA projection type to a string. + +* Language: +* Starlink ANSI C + +* Type of Module: +* C function + +* Invocation: +* const char *smf_jsaproj_tostr( smf_jsaproj_t proj, int *status ) + +* Arguments: +* proj = smf_jsaproj_t (Given) +* The JSA projection identifier. +* status = int * (Given) +* Pointer to the inherited status variable. + +* Returned Value: +* The corresponding string - one of "HPX", "HPX12", "XPHN" or "XPHS". + +* Description: +* This function returns a pointer to a string describing a supplied +* JSA projection type. + +* Authors: +* DSB: David S Berry (JAC, UCLan) +* {enter_new_authors_here} + +* History: +* 2-OCT-2014 (DSB): +* Initial version. +* {enter_further_changes_here} + +* Copyright: +* Copyright (C) 2014 Science & Technology Facilities Council. +* All Rights Reserved. + +* Licence: +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 3 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be +* useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public +* License along with this program; if not, write to the Free +* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +* MA 02111-1307, USA + +* Bugs: +* {note_any_bugs_here} +*- +*/ + +/* Starlink includes */ +#include "sae_par.h" +#include "ast.h" +#include "mers.h" + +/* SMURF includes */ +#include "libsmf/smf.h" +#include "libsmf/jsatiles.h" + +const char *smf_jsaproj_tostr( smf_jsaproj_t proj, int *status ){ + +/* Local Variables: */ + const char *result; + +/* Initialise the returned value. */ + result = "HPX"; + +/* Check inherited status */ + if( *status != SAI__OK ) return result; + +/* Do it. */ + if( proj == SMF__JSA_HPX ) { + result = "HPX"; + + } else if( proj == SMF__JSA_HPX12 ) { + result = "HPX12"; + + } else if( proj == SMF__JSA_XPHN ) { + result = "XPHN"; + + } else if( proj == SMF__JSA_XPHS ) { + result = "XPHS"; + + } else { + *status = SAI__ERROR; + errRepf( " ", "smf_jsaproj_tostr: Unsupported JSA projection type " + "(%d) supplied.", status, proj ); + } + + return result; +} + + + diff --git a/applications/smurf/libsmf/smf_jsatile.c b/applications/smurf/libsmf/smf_jsatile.c index 9fc00555b38..5b158725bed 100644 --- a/applications/smurf/libsmf/smf_jsatile.c +++ b/applications/smurf/libsmf/smf_jsatile.c @@ -14,7 +14,7 @@ * Invocation: * void smf_jsatile( int itile, smfJSATiling *skytiling, int local_origin, -* int usexph, AstFitsChan **fc, AstFrameSet **fs, +* smf_jsaproj_t proj, AstFitsChan **fc, AstFrameSet **fs, * AstRegion **region, int lbnd[2], int ubnd[2], int *status ) * Arguments: @@ -31,13 +31,13 @@ * projection parameters PVi_1 and PVi_2 that causes the origin of * grid coordinates to be moved to the centre of the tile. If zero, * the origin of pixel coordinates will be at RA=0, Dec=0. -* usexph = int (Given) -* If zero, the tile is projected into pixel space using the standard -* HPX projection. If greater than zero, it is projected using an -* XPH projection centred on the north pole. If less than zero, it is -* projected using an XPH projection centred on the south pole. The -* choice of projection changes all the returned values, except for -* "region". +* proj = smf_jsaproj_t (Given) +* The projection to use. This can be an HPX projection centred +* either on RA=0 or RA=12h, or an XPH projection centred either +* on the north pole or the south pole. When creating an individual +* JSA tile, SMF__JSA_HPX (HPX centred on RA=0) should always be +* used. When creating a mosaic of JSA tiles, the projection should +* be chosen so that no discontinuities cross the mosaic. * fc = AstFitsChan ** (Returned) * Address at which to return a pointer to a FitsChan containing * the FITS headers for the tile. May be NULL. @@ -90,8 +90,10 @@ * 12-JUN-2014 (DSB): * Added argument "usexph". * 30-SEP-2014 (DSB): -* Set up correct properties for the JSA_PIXEL Frame, returned within +* Set up correct properties for the JSA_PIXEL Frame, returned within * the all-sky WCS. +* 1-OCT-2014 (DSB): +* Allow an HPX projection centred on RA=12 to be used. * {enter_further_changes_here} * Copyright: @@ -131,9 +133,9 @@ /* Local constants */ #define DELTA 0.05 /* Pixel offset to avoid edges */ -void smf_jsatile( int itile, smfJSATiling *skytiling, int local_origin, int usexph, - AstFitsChan **fc, AstFrameSet **fs, AstRegion **region, - int lbnd[2], int ubnd[2], int *status ) { +void smf_jsatile( int itile, smfJSATiling *skytiling, int local_origin, + smf_jsaproj_t proj, AstFitsChan **fc, AstFrameSet **fs, + AstRegion **region, int lbnd[2], int ubnd[2], int *status ) { /* Local Variables: */ AstFitsChan *lfc = NULL; @@ -166,7 +168,8 @@ void smf_jsatile( int itile, smfJSATiling *skytiling, int local_origin, int usex /* Get a FitsChan holding the FITS headers defining the tile WCS and extent. */ - lfc = smf_jsatileheader( itile, skytiling, local_origin, usexph, &move, status ); + lfc = smf_jsatileheader( itile, skytiling, local_origin, proj, &move, + status ); /* Store the upper bounds of the tile in GRID coords (later changed to PIXEL coords). */ @@ -216,9 +219,10 @@ void smf_jsatile( int itile, smfJSATiling *skytiling, int local_origin, int usex astSetD( lfs, "SkyRef(2)", point2[ 1 ] ); /* If an allsky grid was created above, it may contain a Frame - representing the all-sky JSA HPX pixel grid. This Frame will have - Domain "XJSA-YJSA". Change its Frame attributes to more useful values. */ - if( itile == -1 && !usexph ) { + representing the all-sky JSA HPX (SMF__JSA_HPX) pixel grid. This Frame + will have Domain "XJSA-YJSA". Change its Frame attributes to more useful + values. */ + if( itile == -1 && proj == SMF__JSA_HPX ) { isky = astGetI( lfs, "Current" ); astSetC( lfs, "Current", "XJSA-YJSA" ); astSetC( lfs, "Domain", "JSA_PIXEL" ); @@ -250,7 +254,7 @@ void smf_jsatile( int itile, smfJSATiling *skytiling, int local_origin, int usex /* Get the integer GRID index that contains the FITS reference point. This is basically just the nearest integer to CRPIX, except that midway values (i.e. xxx.5) are always rounded in the positive - direction, reradgless of whether CRPIX is positive or negative. */ + direction, regardless of whether CRPIX is positive or negative. */ if( crpix1 >= 0.0 ) { icrpix1 = (int)( crpix1 + 0.5 ); } else { @@ -274,19 +278,19 @@ void smf_jsatile( int itile, smfJSATiling *skytiling, int local_origin, int usex lbnd[ 0 ] = 1 - icrpix1; lbnd[ 1 ] = 1 - icrpix2; -/* Now correct the above bounds if the tile is in a facet that uses RA=12H - as the reference (there is only one such facet - the first facet, - which is split bottm left and top right of the all-sky map). */ - if( fabs( crval1 ) > 0.1 ) { +/* Now correct the above bounds if the tile is in the lower left facet of + an HPX projection, which uses a different reference point on the sky. */ + if( ( proj == SMF__JSA_HPX && fabs( crval1 ) > 0.1 ) || + ( proj == SMF__JSA_HPX12 && fabs( crval1 ) < 0.1 ) ) { /* The required shift is the same on both pixel axes, and is the number of pixels across two facets. */ offset = 2*skytiling->ntpf*skytiling->ppt; -/* For tiles in the top right half-facet of the all sky map, the current - lbnd values are with repect to a pixel origin at the middle of the top - right diagonal edge of the all-sky map. Shift them to refer to the - centre of the all sky map. */ +/* For tiles that should be in the top right half-facet of the all sky map, + the current lbnd values are with repect to a pixel origin at the middle + of the top right diagonal edge of the all-sky map. Shift them to refer to + the centre of the all sky map. */ if( move ) { lbnd[ 0 ] += offset; lbnd[ 1 ] += offset; diff --git a/applications/smurf/libsmf/smf_jsatileheader.c b/applications/smurf/libsmf/smf_jsatileheader.c index 3ac5cf34e7c..3b37976ba55 100644 --- a/applications/smurf/libsmf/smf_jsatileheader.c +++ b/applications/smurf/libsmf/smf_jsatileheader.c @@ -14,8 +14,8 @@ * Invocation: * AstFitsChan *smf_jsatileheader( int itile, smfJSATiling *skytiling, -* int local_origin, int usexph, int *move, -* int *status ) +* int local_origin, smf_jsaproj_t proj, +* int *move, int *status ) * Arguments: * itile = int (Given) @@ -29,17 +29,20 @@ * projection parameters PVi_1 and PVi_2 that causes the origin of * grid coordinates to be moved to the centre of the tile. If zero, * the origin of pixel coordinates will be at RA=0, Dec=0. -* usexph = int (Given) -* If zero, the tile is projected into pixel space using the standard -* HPX projection. If greater than zero, it is projected using an -* XPH projection centred on the north pole. If less than zero, it is -* projected using an XPH projection centred on the south pole. +* proj = smf_jsaproj_t (Given) +* The projection to use. This can be an HPX projection centred +* either on RA=0 or RA=12h, or an XPH projection centred either +* on the north pole or the south pole. When creating an individual +* JSA tile, SMF__JSA_HPX (HPX centred on RA=0) should always be +* used. When creating a mosaic of JSA tiles, the projection should +* be chosen so that no discontinuities cross the mosaic. * move = int * (Returned) * Pointer to an int which is returned non-zero if the tile is in -* the bottom left part of the bottom left HPX tile (the one that -* is truncated by RA=12 hours). Such tiles should be moved up to -* the top right corner of the all-sky grid in pixel coords. May -* be NULL. Returned equal to zero if "usexph" is non-zero. +* the bottom left part of the bottom left tile of an HPX projection +* (truncated by RA=12 hours (SMF__JSA_HPX) or RA=0 hours +* (SMF__JSA_HPX12) ). Such tiles should be moved up to the top right +* corner of the all-sky grid in pixel coords. May be NULL. Returned +* equal to zero if "proj" is SMF__JSA_XPHN or SMF__XHPS * status = int * (Given) * Pointer to the inherited status variable. @@ -48,16 +51,66 @@ * holding data from a specified JCMT instrument (or, if "itile" is * -1, a FITS header describing the whole collection of tiles). * -* The whole sky is covered by an HPX (HEALPix) projection containing -* 12 basic facets,the reference point (native lon.=0, native lat.=0) -* of the projection is put at (RA,Dec)=(0,0) [except for facet six -* which has a reference point of (12h,0)], so that native coords -* are equivalent to celestial coords. The projection plane is rotated -* by 45 degrees so that the edges of each facet are parallel to X and -* Y (as in Fig.3 of the A&A paper "Mapping on the HEALPix grid" by -* Calabretta and Roukema). Each facet is then divided up into NxN -* tiles, where N is given by "skytiling->ntpf". Each tile is then -* divided into PxP pixels, where P is given by "skytiling->ppt". +* The whole sky is divided into 12 basic HEALPix facets. Each +* facet is then divided up into NxN tiles, where N is given by +* "skytiling->ntpf". Each tile is then divided into PxP pixels, +* where P is given by "skytiling->ppt". +* +* HEALPix facets are numbered from 0 to 11 as defined in the HEALPix +* paper (Gorsky et. al. 2005 ApJ 622, 759). Facet zero contains tiles +* zero to N*N-1, facet one contains tiles N*N to 2*N*N-1, etc. Within +* a facet tiles are indexed using the "nested" scheme described in +* the HEALPix paper. This starts with the lowest tile number in the +* southern corner of the facet. The even bits number the position in +* the north-east direction and the odd bits number the position in +* the north-west direction. +* +* Four flavours of HEALPix projection can be used to map these tiles +* onto a pixel grid. Two are based on the HPX projection (see the A&A +* paper "Mapping on the HEALPix grid" by Calabretta and Roukema), and +* two on the XPH projection ( see the PASA paper "Representing the +* ‘Butterfly’ Projection in FITS—Projection Co" by Calabretta +* and Lowe). Transforming a tile between any pair of these four +* projections just involves a shift and a rotation within pixel +* coordinates. The rotation is always a multiple of 90 degrees, and +* so the transformation can be performed without degradation using +* nearest neighbour resampling or rebinning. +* +* The SMF__JSA_HPX projection is an HPX projection in which the +* reference point is at RA=0 Dec=0. The SMF__JSA_HPX12 projection is +* an HPX projection in which the reference point is at RA=12h Dec=0. +* The SMF__JSA_XPHN projection is an XPH projection in which the +* reference point is at the north pole. The SMF__JSA_XPHS projection +* is an XPH projection in which the reference point is at the south +* pole. +* +* Each of these projections include discontinuities, but these +* discontinuities will be at different places on the sky for each +* one. When creating a header to describe a large area of the sky +* (i.e. larger than one tile), the projection should be chosen to +* ensure that the mapped area does not include any discontinuities. +* For instance, areas close to the north pole should use SMF__JSA_XPHN, +* areas close to the south pole should use SMF__JSA_XPHS, areas close +* to RA=0 should use SMF__JSA_HPX, areas close to RA=12h should use +* SMF__JSA_HPX12, etc. +* +* Note, in all four projections, the discontinuities run between +* tiles, never across tiles. When creating a header for a single +* tile, the SMF__JSA_HPX projection should always be used. +* +* The reference point (native lon.=0, native lat.=0) of the +* SMF__JSA_HPX projection is put at (RA,Dec)=(0,0) [except for facet +* six which has a reference point of (12h,0)], so that native coords +* are equivalent to celestial coords. Note, facet six occupies the +* bottom left corner of the SMF__JSA_HPX projection plane and covers +* an RA range of 9h to 15h - the top right corner of the projection +* covers the same area on the sky but has no corresponding tile. +* The projection plane is rotated by 45 degrees so that the edges +* of each facet are parallel to X and Y (as in Fig.3 of the +* Calabretta and Roukema paper). +* +* The bottom left facet of the SMF__JSA_HPX12 projection is split by +* the RA=0h line in a similar way. * * The projection reference point is at the origin of native longitude * and latitude, which corresponds to the origin of (RA,Dec). However, @@ -71,18 +124,6 @@ * the celestial and pixel coords of an arbitrary point (specified by * projection parameters PVi_1 and PVi_2 for longitude axis "i"). The * point actually used is the centre centre of the requested tile. -* -* HEALPix facets are numbered from 0 to 11 as defined in the HEALPix -* paper (Gorsky et. al. 2005 ApJ 622, 759) (note, facet six -* occupies the bottom left corner of the projection plane and covers -* an RA range of 9h to 15h - the top right corner of the projection -* covers the same area on the sky but has no corresponding tile). Facet -* zero contains tiles zero to N*N-1, facet one contains tiles N*N to -* 2*N*N-1, etc. Within a facet tiles are indexed using the "nested" -* scheme described in the HEALPix paper. This starts with pixel -* zero in the southern corner of the facet. The even bits number -* the position in the north-east direction and the odd bits number -* the position in the north-west direction. * Authors: * DSB: David S Berry (JAC, UCLan) @@ -109,6 +150,8 @@ * 30-SEP-2014 (DSB): * Include a Frame representing JSA all-sky HPX pixel coordinates * within the all-sky WCS. +* 1-OCT-2014 (DSB): +* Allow an HPX projection centred on RA=12 to be used. * {enter_further_changes_here} * Copyright: @@ -147,7 +190,7 @@ #include "libsmf/smf.h" -#include "libsmf/jsatiles.h" /* Move this to smf_typ.h and smf.h when done */ +#include "libsmf/jsatiles.h" /* Prototypes for private functions. */ static AstFitsChan *smfMakeFC( int nx, int ny, int n, int p, double crpix1, @@ -155,8 +198,8 @@ static AstFitsChan *smfMakeFC( int nx, int ny, int n, int p, double crpix1, int usexph, int *status ); AstFitsChan *smf_jsatileheader( int itile, smfJSATiling *skytiling, - int local_origin, int usexph, int *move, - int *status ){ + int local_origin, smf_jsaproj_t proj, + int *move, int *status ){ /* Local Variables: */ AstFitsChan *fc = NULL; @@ -173,6 +216,7 @@ AstFitsChan *smf_jsatileheader( int itile, smfJSATiling *skytiling, int fi; /* Zero-based facet index in range [0,11] */ int m; /* The number of pixels along one edge of a facet */ int ng; /* The number of tile along one edge of the FITS grid */ + int usexph; /* Use an XPH projection? */ int xt; /* X offset to the requested tile */ int yt; /* Y offset to the requested tile */ @@ -182,29 +226,48 @@ AstFitsChan *smf_jsatileheader( int itile, smfJSATiling *skytiling, /* Check inherited status */ if( *status != SAI__OK ) return fc; +/* Initialise things for a SMF__JSA_HPX projection. */ + usexph = 0; + ra_ref = 0.0; + dec_ref = 0.0; + gx_ref = 0.0; + gy_ref = 0.0; + /* If the tile index is -1, produce a header for the whole sky (one pixel per tile). */ if( itile == -1 ) { - if( usexph > 0 ) { + if( proj == SMF__JSA_HPX ) { + ng = 5*skytiling->ntpf; + + } else if( proj == SMF__JSA_HPX12 ) { + ng = 5*skytiling->ntpf; + ra_ref = AST__DPI; + + } else if( proj == SMF__JSA_XPHN ) { ng = 4*skytiling->ntpf; dec_ref = AST__DPIBY2; - } else if( usexph < 0 ) { + usexph = 1; + + } else if( proj == SMF__JSA_XPHS ) { ng = 4*skytiling->ntpf; dec_ref = -AST__DPIBY2; - } else { - ng = 5*skytiling->ntpf; - dec_ref = 0.0; + usexph = 1; + + } else if( *status == SAI__OK ){ + ng = 0; + *status = SAI__ERROR; + errRepf( "", "smf_jsatileheader: Unsupported projection '%d' " + "requested.", status, proj ); } - gx_ref = gy_ref = 0.5*( ng + 1); - ra_ref = 0.0; + gx_ref = gy_ref = 0.5*( ng + 1 ); fc = smfMakeFC( ng, ng, skytiling->ntpf, 1, gx_ref, gy_ref, ra_ref, dec_ref, usexph, status ); -/* For HPX, add in an alternate axis descriptions describing the JSA pixel (x,y) - coordinate grid. */ - if( ! usexph ) { +/* For SMF__JSA_HPX, add in an alternate axis descriptions describing the + JSA pixel (x,y) coordinate grid. */ + if( proj == SMF__JSA_HPX ) { astPutFits( fc, "CTYPE1A = 'XJSA'", 1 ); astPutFits( fc, "CTYPE2A = 'YJSA'", 1 ); astPutFits( fc, "CRVAL1A = -1.0", 1 ); @@ -225,37 +288,45 @@ AstFitsChan *smf_jsatileheader( int itile, smfJSATiling *skytiling, /* Convert the supplied tile index into a pair of X and Y offsets that give the gaps along the X and Y axes, in tiles, between the bottom left - tile in the HPX projection plane and the required tile. This function - includes a check that the tile number is valid. */ + tile in the SMF__JSA_HPX projection plane and the required tile. This + function includes a check that the tile number is valid. It also + returns the index of the HEALPix facet containing the tile. It does + *not* flip the bottom left half-facet up to the top right. */ smf_jsatilei2xy( itile, skytiling, &xt, &yt, &fi, status ); if( *status != SAI__OK ) return fc; +/* Convert the (x,y) offsets of the tile within the SMF__JSA_HPX grid to + the corresponding offsets in the requested projection. Note, tile + (x,y) indices are currently in the "raw" mode, in which the lower left + facet is *not* split (i.e. (0,0) is a valid tile). */ + smf_jsatilexyconv( skytiling, proj, xt, yt, 1, &xt, &yt, status ); + if( ( xt == VAL__BADI || yt == VAL__BADI ) && *status == SAI__OK ) { + *status = SAI__ERROR; + errRep( " ", "smf_jsatileheader: converted tile index is bad " + "(programming error).", status ); + return fc; + } + /* Choose the sky and pixel coords at the reference point. First deal with - XPH projections. The entire XPH projection plane is spanned by four - facets along each edge.*/ - if( usexph ) { + XPH projections. */ + if( proj == SMF__JSA_XPHN || proj == SMF__JSA_XPHS ) { + usexph = 1; /* The reference point is the north or south pole. */ - ra_ref = 0.0; - dec_ref = ( usexph > 0 ) ? AST__DPIBY2 : -AST__DPIBY2; - -/* Convert the (x,y) offsets of the tile within the HPX all-sky grid to - the corresponding offsets in the XPH all-sky grid. */ - smf_jsatilexyconv( skytiling, usexph, xt, yt, &xt, &yt, status ); + dec_ref = ( proj == SMF__JSA_XPHN ) ? AST__DPIBY2 : -AST__DPIBY2; -/* Get the grid coordinates (within the grid frame of the current tile), +/* Get the grid coordinates (within the grid frame of the requested tile), of the projection reference point. The entire XPH projection plane is spanned by four facets along each edge. */ gx_ref = 0.5*( 4.0*m + 1.0 ) - xt*skytiling->ppt; gy_ref = 0.5*( 4.0*m + 1.0 ) - yt*skytiling->ppt; -/* Now deal with HPX projections. */ - } else { +/* Now deal with SMF_JSA_HPX projections. */ + } else if( proj == SMF__JSA_HPX ) { -/* Note the RA at the reference point. This is 0 hours except for tiles - within facet six. */ +/* Note the RA at the reference point. For SMF__JSA_HPX projections, this + is 0 hours except for tiles within facet six. */ if( fi != 6 ) { - ra_ref = 0.0; /* Get the grid coordinates (within the grid frame of the current tile), of the projection reference point. The entire HPX projection plane is @@ -263,12 +334,12 @@ AstFitsChan *smf_jsatileheader( int itile, smfJSATiling *skytiling, gx_ref = 0.5*( 5.0*m + 1.0) - xt*skytiling->ppt; gy_ref = 0.5*( 5.0*m + 1.0) - yt*skytiling->ppt; -/* The seventh facet (i.e bottom right, fi==6) in the projection plane is a - problem because it is split by the ra = 12hours line into two halfs. - When a WcsMap is used transform (x,y) points in the lower left half of - this facet, the resulting RA an Dec values will be AST__BAD. To avoid - this, we use (ra,dec)=(12h,0) as the reference point for the seventh - facet. Note the RA at the reference point. */ +/* The seventh facet (i.e bottom right, fi==6) in the SMF__JSA_HPX + projection plane is a problem because it is split by the ra = 12 hours + line into two halfs. When a WcsMap is used transform (x,y) points in + the lower left half of this facet, the resulting RA an Dec values will + be AST__BAD. To avoid this, we use (ra,dec)=(12h,0) as the reference + point for the seventh facet. Note the RA at the reference point. */ } else { ra_ref = AST__DPI; @@ -283,8 +354,44 @@ AstFitsChan *smf_jsatileheader( int itile, smfJSATiling *skytiling, if( move ) *move = yt < skytiling->ntpf - 1 && xt < skytiling->ntpf - 1 - yt; } -/* The Declination at the reference point is zero for all tiles. */ - dec_ref = 0.0; +/* Now deal with SMF_JSA_HPX12 projections. */ + } else if( proj == SMF__JSA_HPX12 ) { + +/* Note the RA at the reference point. For SMF__JSA_HPX12 projections, this + is 12 hours except for tiles within facet six. */ + if( fi != 6 ) { + ra_ref = AST__DPI; + +/* Get the grid coordinates (within the grid frame of the current tile), + of the projection reference point. The entire HPX projection plane is + spanned by five facets along each edge. */ + gx_ref = 0.5*( 5.0*m + 1.0) - xt*skytiling->ppt; + gy_ref = 0.5*( 5.0*m + 1.0) - yt*skytiling->ppt; + +/* The seventh facet (i.e bottom right, fi==6) in the SMF__JSA_HPX12 + projection plane is a problem because it is split by the ra = 0 hours + line into two halfs. When a WcsMap is used transform (x,y) points in + the lower left half of this facet, the resulting RA an Dec values will + be AST__BAD. To avoid this, we use (ra,dec)=(0h,0) as the reference + point for the seventh facet. Note the RA at the reference point. */ + } else { + +/* Get the grid coordinates (within the grid frame of the current tile), + of the projection reference point (which is at the centre of the first + facet in this case). */ + gx_ref = 0.5*( m + 1.0) - xt*skytiling->ppt; + gy_ref = 0.5*( m + 1.0) - yt*skytiling->ppt; + +/* Indicate if the tile is in the lower left section (the section that + needs to be moved up to the top right in pixel coords). */ + if( move ) *move = yt < skytiling->ntpf - 1 && xt < skytiling->ntpf - 1 - yt; + } + +/* Report an error for an unknown projection. */ + } else if( *status == SAI__OK ){ + *status = SAI__ERROR; + errRepf( "", "smf_jsatileheader: Unsupported projection '%d' " + "requested.", status, proj ); } /* Put the basic header into a FitsChan. */ diff --git a/applications/smurf/libsmf/smf_jsatiles_data.c b/applications/smurf/libsmf/smf_jsatiles_data.c index 4ac644eb323..b23e1be1570 100644 --- a/applications/smurf/libsmf/smf_jsatiles_data.c +++ b/applications/smurf/libsmf/smf_jsatiles_data.c @@ -166,10 +166,12 @@ int *smf_jsatiles_data( ThrWorkForce *wf, Grp *igrp, size_t size, tiling, status ); /* Create a FrameSet describing the whole sky in which each pixel - corresponds to a single tile. The current Frame is ICRS (RA,Dec) and - the base Frame is grid coords in which each grid pixel corresponds to - a single tile. Then invert it so that the current Frame is GRID. */ - smf_jsatile( -1, tiling, 0, 0, NULL, &fs, NULL, lbnd, ubnd, status ); + corresponds to a single tile IN smf__jsa_hpx PROJECTION. The current + Frame is ICRS (RA,Dec) and the base Frame is grid coords in which each + grid pixel corresponds to a single tile. Then invert it so that the + current Frame is GRID. */ + smf_jsatile( -1, tiling, 0, SMF__JSA_HPX, NULL, &fs, NULL, lbnd, + ubnd, status ); astInvert( fs ); /* Unlock the FrameSet pointer so that it can be locked by the worker diff --git a/applications/smurf/libsmf/smf_jsatiles_region.c b/applications/smurf/libsmf/smf_jsatiles_region.c index 9ad685deb44..e9583ee465e 100644 --- a/applications/smurf/libsmf/smf_jsatiles_region.c +++ b/applications/smurf/libsmf/smf_jsatiles_region.c @@ -165,10 +165,11 @@ int *smf_jsatiles_region( AstRegion *region, smfJSATiling *skytiling, } /* Create a FrameSet describing the whole sky in which each pixel - corresponds to a single tile. The current Frame is ICRS (RA,Dec) and - the base Frame is grid coords in which each grid pixel corresponds to - a single tile. */ - smf_jsatile( -1, skytiling, 0, 0, NULL, &fs, NULL, lbnd, ubnd, status ); + corresponds to a single tile in SMF__JSA_HPX projection. The current + Frame is ICRS (RA,Dec) and the base Frame is grid coords in which each + grid pixel corresponds to a single tile. */ + smf_jsatile( -1, skytiling, 0, SMF__JSA_HPX, NULL, &fs, NULL, lbnd, ubnd, + status ); /* Map the Region using the FrameSet obtained above so that the new Region describes offsets in tiles from the lower left tile. If "space_region" @@ -252,8 +253,8 @@ int *smf_jsatiles_region( AstRegion *region, smfJSATiling *skytiling, if( value == -1 ) { /* Get a Region covering the tile. */ - smf_jsatile( itile, skytiling, 0, 0, NULL, NULL, &tregion, lbnd, ubnd, - status ); + smf_jsatile( itile, skytiling, 0, SMF__JSA_HPX, NULL, NULL, &tregion, + lbnd, ubnd, status ); /* See if this Region overlaps the user supplied region. Set the value of the KeyMap entry to +1 or 0 accordingly. */ diff --git a/applications/smurf/libsmf/smf_jsatilexyconv.c b/applications/smurf/libsmf/smf_jsatilexyconv.c index bb775710776..3a39e34223a 100644 --- a/applications/smurf/libsmf/smf_jsatilexyconv.c +++ b/applications/smurf/libsmf/smf_jsatilexyconv.c @@ -4,7 +4,7 @@ * smf_jsatilexyconv * Purpose: -* Convert (x,y) indices of a tile from HPX to XPH +* Convert tile (x,y) indices from SMF__JSA_HPX to a requested JSA projection. * Language: * Starlink ANSI C @@ -13,8 +13,8 @@ * C function * Invocation: -* void smf_jsatilexyconv( smfJSATiling *skytiling, int usexph, -* int xt_hpx, int yt_hpx, int *xt_out, +* void smf_jsatilexyconv( smfJSATiling *skytiling, smf_jsaproj_t proj, +* int xt_hpx, int yt_hpx, int raw, int *xt_out, * int *yt_out, int *status ) * Arguments: @@ -22,31 +22,34 @@ * Pointer to a structure holding parameters describing the tiling * scheme used for the required JCMT instrument, as returned by * function smf_jsatiling. -* usexph = int (Given) -* Indicates the projection into which the supplied HPX tile indices -* should be converted: negative means north pole XPH, 0 means HPX -* (i.e. no change), positive means south pole XPH. +* proj = smf_jsaproj_t (Given) +* The required projection. * xt_hpx = int (Giveb) * The zero-based index of a tile in the X (RA) direction, within -* the HPX projection. +* the SMF__JSA_HPX projection. * yt_hpx = int (given) * The zero-based index of the tile in the Y (Dec) direction, within -* the HPX projection. +* the SMF__JSA_HPX projection. +* raw = int (given) +* If non-zero, then the whole of the bottom left facet contains +* tiles, and the top right facet contains no tiles. If zero, then +* the only the top right half of the bottom left facet, and the +* bottom left half of the top right facet contains tiles. * xt_out = int * (Returned) * Address of the integer in which to store the zero-based index -* of the tile in the X (RA) direction, within the projection -* requested by "usexph". This can point to "xt_hpx" if required. +* of the tile in the X (RA) direction, within the requested +* projection. This can point to "xt_hpx" if required. * yt_out = int * (Returned) * Address of the integer in which to store the zero-based index -* of the tile in the Y (Dec) direction, within the projection -* requested by "usexph". This can point to "yt_hpx" if required. +* of the tile in the Y (Dec) direction, within the requested +* projection. This can point to "yt_hpx" if required. * status = int * (Given) * Pointer to the inherited status variable. * Description: -* This function takes the (x,y) indices of a tile in the HPX +* This function takes the (x,y) indices of a tile in the SMF__JSA_HPX * projection, and returns the indices of the same tile within -* the projection specified by "usexph". The indices of a tile in any +* the projection specified by "proj". The indices of a tile in any * projection are the offsets of the tile (in units of whole tiles) * from the bottom left corner of the whole sky grid to the bottom left * corner of the tile. @@ -61,6 +64,8 @@ * History: * 16-JUN-2014 (DSB): * Initial version. +* 1-OCT-2014 (DSB): +* CHanged to support SMF__JSA_HPX12 projections. * {enter_further_changes_here} * Copyright: @@ -96,8 +101,9 @@ #include "libsmf/smf.h" #include "libsmf/jsatiles.h" -void smf_jsatilexyconv( smfJSATiling *skytiling, int usexph, int xt_hpx, - int yt_hpx, int *xt_out, int *yt_out, int *status ){ +void smf_jsatilexyconv( smfJSATiling *skytiling, smf_jsaproj_t proj, + int xt_hpx, int yt_hpx, int raw, int *xt_out, + int *yt_out, int *status ){ /* Local Variables: */ int dx; @@ -136,73 +142,119 @@ void smf_jsatilexyconv( smfJSATiling *skytiling, int usexph, int xt_hpx, /* Check inherited status */ if( *status != SAI__OK ) return; -/* Find the (x,y) offsets (in facets) of the facet containing the tile. */ +/* Find the (x,y) offsets (in facets within the SMF__JSA_HPX projection) + of the facet containing the tile. */ xf = xt_hpx / skytiling->ntpf; yf = yt_hpx / skytiling->ntpf; /* Return bad (x,y) values for positions that are not on one of the 12 HPX - facets. Also reject the half facets at bottom left and top right that - are not used in JSA all-sky grid. */ - xpy = xt_hpx + yt_hpx; - if( yf <= xf + 1 && yf >= xf - 1 && - xpy >= skytiling->ntpf - 1 && xpy < 9*skytiling->ntpf - 1) { + facets. */ + if( yf <= xf + 1 && yf >= xf - 1 ) { + +/* If required, return bad (x,y) values for positions that are within + the half facets at bottom left and top right that are not used in + the SMF__JSA_HPX projection. */ + xpy = xt_hpx + yt_hpx; + if( raw || ( xpy >= skytiling->ntpf - 1 && + xpy < 9*skytiling->ntpf - 1 ) ) { /* First do XPH projections. */ - if( usexph ) { + if( proj == SMF__JSA_XPHN || proj == SMF__JSA_XPHS ) { /* Find the zero-based index of the gore containing the tile. */ - igore = ( xpy - skytiling->ntpf + 1 )/( 2*skytiling->ntpf ); + igore = ( xpy - skytiling->ntpf + 1 )/( 2*skytiling->ntpf ); /* Find the (x,y) offsets of the tile away from the bottom left corner of the square enclosing the gore within the HPX projection. */ - off = igore*skytiling->ntpf; - dx = xt_hpx - off; - dy = yt_hpx - off; + off = igore*skytiling->ntpf; + dx = xt_hpx - off; + dy = yt_hpx - off; /* Find the rotation and translation necessary to transform the gore from HPX into XPH. */ - if( usexph > 0 ) { - rot = rot_north[ igore ]; - xtr = xtr_north[ igore ]; - ytr = ytr_north[ igore ]; - } else { - rot = rot_south[ igore ]; - xtr = xtr_south[ igore ]; - ytr = ytr_south[ igore ]; - } + if( proj == SMF__JSA_XPHN ) { + rot = rot_north[ igore ]; + xtr = xtr_north[ igore ]; + ytr = ytr_north[ igore ]; + } else { + rot = rot_south[ igore ]; + xtr = xtr_south[ igore ]; + ytr = ytr_south[ igore ]; + } /* Rotate the offsets of the tile within the gore bounding-box, so that they refer to the required XPH projection. */ - if( rot == 0 ) { /* No rotation */ - *xt_out = dx; - *yt_out = dy; - } else if( rot == 1 ) { /* 90 degs ACW rotation */ - *xt_out = 2*skytiling->ntpf - 1 - dy; - *yt_out = dx; - } else if( rot == 2 ) { /* 180 degs ACW rotation */ - *xt_out = 2*skytiling->ntpf - 1 - dx; - *yt_out = 2*skytiling->ntpf - 1 - dy; - } else { /* 270 degs ACW rotation */ - *xt_out = dy; - *yt_out = 2*skytiling->ntpf - 1 - dx; - } + if( rot == 0 ) { /* No rotation */ + *xt_out = dx; + *yt_out = dy; + } else if( rot == 1 ) { /* 90 degs ACW rotation */ + *xt_out = 2*skytiling->ntpf - 1 - dy; + *yt_out = dx; + } else if( rot == 2 ) { /* 180 degs ACW rotation */ + *xt_out = 2*skytiling->ntpf - 1 - dx; + *yt_out = 2*skytiling->ntpf - 1 - dy; + } else { /* 270 degs ACW rotation */ + *xt_out = dy; + *yt_out = 2*skytiling->ntpf - 1 - dx; + } /* Add on the HPX offsets to the lower left corner of the bounding box. The results of this are the offsets of the tile if you were just to rotate the gore about its centre without translating it. */ - *xt_out += off; - *yt_out += off; + *xt_out += off; + *yt_out += off; /* Add on the translation that moves the (now rotated) gore from its - position with HPX projection to its position within the XPH - projection. */ - *xt_out += xtr*skytiling->ntpf; - *yt_out += ytr*skytiling->ntpf; - -/* Now do HPX projections. Just return the supplied HPX tile offsets. */ - } else { - *xt_out = xt_hpx; - *yt_out = yt_hpx; + position within the SMF__JSA_HPX projection to its position within + the requested XPH projection. */ + *xt_out += xtr*skytiling->ntpf; + *yt_out += ytr*skytiling->ntpf; + +/* Now do SMF__JSA_HPX12 projections. */ + } else if( proj == SMF__JSA_HPX12 ) { + +/* Moving from SMF__JSA_HPX to SMF__JSA_HPX12 involves moving each facet + by two facets to the upper right, so that facet 6 moves to the + position of facet 1, facet 9 moves to the position of facet 11, etc. */ + *xt_out = xt_hpx + 2*skytiling->ntpf; + *yt_out = yt_hpx + 2*skytiling->ntpf; + +/* Facets that have been moved beyond the upper right corner of the + projection plane now need to be wrapped-round to the bottom left corner. */ + if( *xt_out >= 5*skytiling->ntpf || *yt_out >= 5*skytiling->ntpf ) { + *xt_out -= 4*skytiling->ntpf; + *yt_out -= 4*skytiling->ntpf; + +/* In addition, the top right "facet" (which corresponds to the same + area of the sky as the bottom left facet) also need to be wrapped-round + to the bottom left corner. */ + } else if( *xt_out >= 4*skytiling->ntpf && + *yt_out >= 4*skytiling->ntpf ) { + *xt_out -= 4*skytiling->ntpf; + *yt_out -= 4*skytiling->ntpf; + } + +/* Tiles that are now in the lower left half of the lower left facet + (i.e. off the edge of the valid part of the projection) need + to be moved up to fill the half-facet hole left at the top right. + Only do this if requested. */ + if( !raw && *yt_out < skytiling->ntpf - 1 && + *xt_out < skytiling->ntpf - 1 - *yt_out ) { + *xt_out += 4*skytiling->ntpf; + *yt_out += 4*skytiling->ntpf; + } + +/* Now do SMF__JSA_HPX projections. Just return the supplied tile offsets. */ + } else if( proj == SMF__JSA_HPX ) { + *xt_out = xt_hpx; + *yt_out = yt_hpx; + +/* Report an error for an unknown projection. */ + } else if( *status == SAI__OK ){ + *status = SAI__ERROR; + errRepf( "", "smf_jsatilexyconv: Unsupported projection '%d' " + "requested.", status, proj ); + } } } } diff --git a/applications/smurf/libsmurf/smurf_jsadicer.c b/applications/smurf/libsmurf/smurf_jsadicer.c index 4ae6be4d006..f368e072ddf 100644 --- a/applications/smurf/libsmurf/smurf_jsadicer.c +++ b/applications/smurf/libsmurf/smurf_jsadicer.c @@ -56,19 +56,18 @@ * all the output NDFs created by this application via parameter * OUT (one per line). If a null (!) value is supplied no file is * created. [!] +* PROJ = LITERAL (Read) +* Determines the projection used by the output NDFs. The allowed +* values are "HPX" (HPX projection centred on RA=0h), "HPX12" (HPX +* projection centred on RA=12h), "XPHN" (XPH projection centred on +* the north pole) and "XPHS" (XPH projection centred on the south +* pole). A null (!) value causes "HPX" to be used. ["HPX"] * TRIM = _INTEGER (Read) * A zero or negative value results in each output NDF covering the * full area of the corresponding JSAtile. A value of one results in * each output NDF being cropped to the bounds of the supplied NDF. A * value of two or more results in each output NDF being cropped to * remove any blank borders. [2] -* USEXPH = LITERAL (Read) -* Determines the projection used by the output NDFs. The allowed -* values are "North", "South" or "None". A value of "None" causes -* the standard JSA equatorial HPX projection to be used. The other -* two values cause an XPH (polar HEALPix) projection centred on -* the north or south pole to be used. A null (!) value causes "NONE" -* to be used. ["None"] * Authors: * DSB: David Berry (JAC, Hawaii) @@ -85,6 +84,8 @@ * 8-JUL-2014 (DSB): * Change USEXPH to accept "North", "South" or "None" instead of 1, * -1 and 0. +* 1-OCT-2014 (DSB): +* Change USEXPH to PROJ. * Copyright: * Copyright (C) 2013-2014 Science and Technology Facilities Council. @@ -152,10 +153,10 @@ void smurf_jsadicer( int *status ) { char text[ 255 ]; int indf; int trim; - int usexph; size_t ntile; size_t size; smfJSATiling tiling; + smf_jsaproj_t proj; /* Check inherited status */ if (*status != SAI__OK) return; @@ -181,15 +182,10 @@ void smurf_jsadicer( int *status ) { /* See how the output NDFs are to be trimmed. */ parGet0i( "TRIM", &trim, status ); -/* Decide what sort of projection (HPX or XPH) to use. */ - parChoic( "USEXPH", "NONE", "NONE,NORTH,SOUTH", 1, text, sizeof(text), status ); - if( !strcmp( text, "NORTH" ) ) { - usexph = 1; - } else if( !strcmp( text, "SOUTH" ) ) { - usexph = -1; - } else { - usexph = 0; - } +/* Decide what sort of projection to use. */ + parChoic( "PROJ", "HPX", "HPX,HPX12,XPHN,XPHS", 1, text, sizeof(text), + status ); + proj = smf_jsaproj_fromstr( text, 1, status ); /* Get a FitsChan holding the contents of the FITS extension from the input NDF. Annul the error if the NDF has no FITS extension. */ @@ -212,7 +208,7 @@ void smurf_jsadicer( int *status ) { ogrp = grpNew( "", status ); /* Dice the map into output NDFs. */ - smf_jsadicer( indf, basename, trim, tiling.instrument, usexph, &ntile, + smf_jsadicer( indf, basename, trim, tiling.instrument, proj, &ntile, ogrp, status ); /* Write out the list of output NDF names, annulling the error if a null diff --git a/applications/smurf/libsmurf/smurf_jsapaster.c b/applications/smurf/libsmurf/smurf_jsapaster.c index 40cf2be4ccf..cd11bfb07a1 100644 --- a/applications/smurf/libsmurf/smurf_jsapaster.c +++ b/applications/smurf/libsmurf/smurf_jsapaster.c @@ -122,6 +122,7 @@ void smurf_jsapaster( int *status ) { AstFrameSet *iwcs; AstFrameSet *refwcs; AstFrameSet *refwcs_hpx; + AstFrameSet *refwcs_hpx12; AstFrameSet *refwcs_xphs; AstFrameSet *refwcs_xphn; AstKeyMap *km; @@ -147,6 +148,7 @@ void smurf_jsapaster( int *status ) { int indf; int isky; int lbnd_hpx[ NDF__MXDIM ]; + int lbnd_hpx12[ NDF__MXDIM ]; int lbnd_ref[ 2 ]; int lbnd_xphn[ NDF__MXDIM ]; int lbnd_xphs[ NDF__MXDIM ]; @@ -156,14 +158,16 @@ void smurf_jsapaster( int *status ) { int place; int ref_tile; int there; + int ubnd_hpx12[ NDF__MXDIM ]; int ubnd_hpx[ NDF__MXDIM ]; int ubnd_ref[ 2 ]; int ubnd_xphn[ NDF__MXDIM ]; int ubnd_xphs[ NDF__MXDIM ]; - int use_xph; + smf_jsaproj_t proj; size_t index; size_t npix; size_t npix_hpx; + size_t npix_hpx12; size_t npix_xphn; size_t npix_xphs; size_t size; @@ -228,8 +232,8 @@ void smurf_jsapaster( int *status ) { status ); /* Get the spatial WCS for the reference tile in HPX projection. */ - smf_jsatile( ref_tile, &tiling, 0, 0, NULL, &refwcs_hpx, NULL, lbnd_ref, - ubnd_ref, status ); + smf_jsatile( ref_tile, &tiling, 0, SMF__JSA_HPX, NULL, &refwcs_hpx, + NULL, lbnd_ref, ubnd_ref, status ); /* Make the PIXEL Frame the base Frame. */ astSetC( refwcs_hpx, "Base", "PIXEL" ); @@ -242,31 +246,47 @@ void smurf_jsapaster( int *status ) { npix_hpx = 1; for( idim = 0; idim < ndim; idim++ ) npix_hpx *= dims[ idim ]; +/* Now do the same for HPX12 projection (like HPX but centred on RA=12h). */ + smf_jsatile( ref_tile, &tiling, 0, SMF__JSA_HPX12, NULL, &refwcs_hpx12, + NULL, lbnd_ref, ubnd_ref, status ); + astSetC( refwcs_hpx12, "Base", "PIXEL" ); + smf_projbox( igrp, refwcs_hpx12, lbnd_hpx12, ubnd_hpx12, dims, status ); + npix_hpx12 = 1; + for( idim = 0; idim < ndim; idim++ ) npix_hpx12 *= dims[ idim ]; + /* Now do the same for XPH (north) projection. */ - smf_jsatile( ref_tile, &tiling, 0, 1, NULL, &refwcs_xphn, NULL, lbnd_ref, - ubnd_ref, status ); + smf_jsatile( ref_tile, &tiling, 0, SMF__JSA_XPHN, NULL, &refwcs_xphn, + NULL, lbnd_ref, ubnd_ref, status ); astSetC( refwcs_xphn, "Base", "PIXEL" ); smf_projbox( igrp, refwcs_xphn, lbnd_xphn, ubnd_xphn, dims, status ); npix_xphn = 1; for( idim = 0; idim < ndim; idim++ ) npix_xphn *= dims[ idim ]; /* Now do the same for XPH (south) projection. */ - smf_jsatile( ref_tile, &tiling, 0, -1, NULL, &refwcs_xphs, NULL, lbnd_ref, - ubnd_ref, status ); + smf_jsatile( ref_tile, &tiling, 0, SMF__JSA_XPHS, NULL, &refwcs_xphs, + NULL, lbnd_ref, ubnd_ref, status ); astSetC( refwcs_xphs, "Base", "PIXEL" ); smf_projbox( igrp, refwcs_xphs, lbnd_xphs, ubnd_xphs, dims, status ); npix_xphs = 1; for( idim = 0; idim < ndim; idim++ ) npix_xphs *= dims[ idim ]; /* Now find the projection which gives the smallest mosaic. */ - use_xph = 0; + proj = SMF__JSA_HPX; npix = npix_hpx; lbnd = lbnd_hpx; ubnd = ubnd_hpx; refwcs = refwcs_hpx; + if( npix_hpx12 < npix ) { + proj = SMF__JSA_HPX12; + npix = npix_hpx12; + lbnd = lbnd_hpx12; + ubnd = ubnd_hpx12; + refwcs = refwcs_hpx12; + } + if( npix_xphn < npix ) { - use_xph = 1; + proj = SMF__JSA_XPHN; npix = npix_xphn; lbnd = lbnd_xphn; ubnd = ubnd_xphn; @@ -274,7 +294,7 @@ void smurf_jsapaster( int *status ) { } if( npix_xphs < npix ) { - use_xph = -1; + proj = SMF__JSA_XPHS; npix = npix_xphs; lbnd = lbnd_xphs; ubnd = ubnd_xphs; @@ -282,10 +302,15 @@ void smurf_jsapaster( int *status ) { } /* Warn the user if the output will use an XPH projection. */ - if( use_xph ) { - msgOutf( "", " The output mosaic will use an XPH projection " - "centred on the %s pole.", status, - ( use_xph > 0 ) ? "north" : "south" ); + if( proj != SMF__JSA_HPX ) { + if( proj != SMF__JSA_HPX12 ) { + msgOutf( "", " The output mosaic will use an HPX projection " + "centred on RA = 12h.", status ); + } else { + msgOutf( "", " The output mosaic will use an XPH projection " + "centred on the %s pole..", status, + ( proj == SMF__JSA_XPHN ) ? "north" : "south" ); + } } /* Make GRID coords the base Frame in the reference WCS. */ diff --git a/applications/smurf/libsmurf/smurf_jsatileinfo.c b/applications/smurf/libsmurf/smurf_jsatileinfo.c index 8b8be2932ef..3cf47ffc864 100644 --- a/applications/smurf/libsmurf/smurf_jsatileinfo.c +++ b/applications/smurf/libsmurf/smurf_jsatileinfo.c @@ -88,6 +88,12 @@ * MAXTILE = _INTEGER (Write) * An output parameter to which is written the largest tile index * associated with the instrument specified by parameter INSTRUMENT. +* PROJ = LITERAL (Read) +* Determines the JSA projection to use. The allowed values are +* "HPX" (HPX projection centred on RA=0h), "HPX12" (HPX projection +* centred on RA=12h), "XPHN" (XPH projection centred on the north +* pole) and "XPHS" (XPH projection centred on the south pole). A +* null (!) value causes "HPX" to be used. ["HPX"] * RACEN = LITERAL (Write) * An output parameter to which is written the ICRS Right Ascension * of the tile centre, in radians. @@ -123,13 +129,6 @@ * UBND( 2 ) = _INTEGER (Write) * An output parameter to which are written the upper pixel bounds * of the NDF containing the co-added data for the tile. -* USEXPH = LITERAL (Read) -* Determines the projection used by the output NDFs. The allowed -* values are "North", "South" or "None". A value of "None" causes -* the standard JSA equatorial HPX projection to be used. The other -* two values cause an XPH (polar HEALPix) projection centred on -* the north or south pole to be used. A null (!) value causes "NONE" -* to be used. ["None"] * Related Applications: * SMURF: MAKECUBE, MAKEMAP, TILELIST. @@ -160,6 +159,8 @@ * 8-JUL-2014 (DSB): * Change USEXPH to accept "North", "South" or "None" instead of 1, * -1 and 0. +* 1-OCT-2014 (DSB): +* Change USEXPH to PROJ. * Copyright: * Copyright (C) 2011-2014 Science and Technology Facilities Council. @@ -254,7 +255,6 @@ void smurf_jsatileinfo( int *status ) { int indf3; int itile; int iv; - int j; int jtile; int lbnd[ 2 ]; int local_origin; @@ -263,7 +263,7 @@ void smurf_jsatileinfo( int *status ) { int tlbnd[ 2 ]; int tubnd[ 2 ]; int ubnd[ 2 ]; - int usexph; + smf_jsaproj_t proj; int xt; int yt; smfJSATiling skytiling; @@ -286,15 +286,10 @@ void smurf_jsatileinfo( int *status ) { /* Abort if an error has occurred. */ if( *status != SAI__OK ) goto L999; -/* Decide what sort of projection (HPX or XPH) to use. */ - parChoic( "USEXPH", "NONE", "NONE,NORTH,SOUTH", 1, text, sizeof(text), status ); - if( !strcmp( text, "NORTH" ) ) { - usexph = 1; - } else if( !strcmp( text, "SOUTH" ) ) { - usexph = -1; - } else { - usexph = 0; - } +/* Decide what sort of projection to use. */ + parChoic( "PROJ", "HPX", "HPX,HPX12,XPHN,XPHS", 1, text, sizeof(text), + status ); + proj = smf_jsaproj_fromstr( text, 1, status ); /* If required, create an all-sky NDF in which each pixel covers the area of a single tile, and holds the integer tile index. The NDF has an @@ -310,7 +305,7 @@ void smurf_jsatileinfo( int *status ) { /* Otherwise, create a FrameSet describing the whole sky in which each pixel corresponds to a single tile. */ } else { - smf_jsatile( -1, &skytiling, 0, usexph, NULL, &fs, NULL, lbnd, ubnd, + smf_jsatile( -1, &skytiling, 0, proj, NULL, &fs, NULL, lbnd, ubnd, status ); /* Change the bounds of the output NDF. */ @@ -324,20 +319,27 @@ void smurf_jsatileinfo( int *status ) { status ); /* Create all-sky map using XPH projection. */ - if( usexph && *status == SAI__OK ) { + if( *status == SAI__OK ) { /* Loop round every tile index. */ for( jtile = 0; jtile < skytiling.ntiles; jtile++ ) { -/* Get the zero-based (x,y) indices of the tile within an HPX projection. */ +/* Get the zero-based (x,y) indices of the tile within an HPX projection. + This flips the bottom left half-facet up to the top right. */ smf_jsatilei2xy( jtile, &skytiling, &xt, &yt, NULL, status ); /* Convert these HPX indices to the corresponding indices within the - required XPH projection. */ - smf_jsatilexyconv( &skytiling, usexph, xt, yt, &xt, &yt, status ); - -/* Get the vector index of the correspsonding element of the all-sky NDF. */ - iv = xt + 4*skytiling.ntpf*yt; + required projection. Note, the lower left facet is split by the above + call to smf_jsatilei2xy tile (i.e. (xt,yt) indices are *not* in the + "raw" mode). For instance, (0,0) is not a valid tile. */ + smf_jsatilexyconv( &skytiling, proj, xt, yt, 0, &xt, &yt, status ); + +/* Get the vector index of the corresponding element of the all-sky NDF. */ + if( proj == SMF__JSA_HPX || proj == SMF__JSA_HPX12 ) { + iv = xt + 5*skytiling.ntpf*yt; + } else { + iv = xt + 4*skytiling.ntpf*yt; + } /* Report an error if this element has already been assigned a tile index. Otherwise, store the tile index. */ @@ -345,23 +347,11 @@ void smurf_jsatileinfo( int *status ) { ipntr[ iv ] = jtile; } else if( *status == SAI__OK ) { *status = SAI__ERROR; - errRepf( "", "All-sky XPH projection assigns multiple " - "tiles to pixel (%d,%d).", status, xt, yt ); + errRepf( "", "%s projection assigns multiple tiles to " + "pixel (%d,%d).", status, text, xt, yt ); break; } } - -/* Create all-sky map using HPX projection. */ - } else if( *status == SAI__OK ){ - -/* Loop round every row and column */ - for( j = 0; j < ubnd[ 1 ] - lbnd[ 1 ] + 1; j++ ) { - for( i = 0; i < ubnd[ 0 ] - lbnd[ 0 ] + 1; i++ ) { - -/* Store the tile index at this pixel. */ - *(ipntr++) = smf_jsatilexy2i( i, j, &skytiling, status ); - } - } } /* Store NDF title. */ @@ -399,7 +389,7 @@ void smurf_jsatileinfo( int *status ) { /* Get the FITS header, FrameSet and Region defining the tile, and the tile bounds in pixel indices. */ - smf_jsatile( itile, &skytiling, local_origin, usexph, &fc, &fs, ®ion, + smf_jsatile( itile, &skytiling, local_origin, proj, &fc, &fs, ®ion, lbnd, ubnd, status ); /* Write the FITS headers out to a file, annulling the error if the diff --git a/applications/smurf/libsmurf/smurf_jsatilelist.c b/applications/smurf/libsmurf/smurf_jsatilelist.c index 13c00cbc042..a067c75827b 100644 --- a/applications/smurf/libsmurf/smurf_jsatilelist.c +++ b/applications/smurf/libsmurf/smurf_jsatilelist.c @@ -52,6 +52,12 @@ * done, or if a Region is supplied for parameter IN, then no dynamic * default is provided, and the user is prompted for a value if none * was supplied on the command line. [] +* PROJ = LITERAL (Write) +* The type of JSA projection that should be used to describe the +* area of sky covered by the returned lost of tiles. Will be one of +* "HPX", "HPX12", "XPHN" or "XPHS". The choice is made to minimise +* the possibility of a projection discontinuity falling within the +* sky area covered by the tiles. * TILES(*) = _INTEGER (Write) * An output parameter to which is written the list of integer tile * indices. @@ -113,6 +119,8 @@ * 9-MAY-2014 (DSB): * No need to check for science files before calling * smf_jsatiles_data. This speeds things up a lot. +* 2-OCT-2014 (DSB): +* Added PROJ parameter. * Copyright: * Copyright (C) 2011,2013,2014 Science and Technology Facilities Council. @@ -174,6 +182,7 @@ void smurf_jsatilelist( int *status ) { AstObject *obj; AstRegion *region; Grp *igrp = NULL; + ThrWorkForce *wf = NULL; double vertex_data[ 2*MAXVERT ]; int *tiles = NULL; int i; @@ -185,7 +194,7 @@ void smurf_jsatilelist( int *status ) { int ubnd[2]; size_t size; smfJSATiling tiling; - ThrWorkForce *wf = NULL; + smf_jsaproj_t proj; /* Check inherited status */ if( *status != SAI__OK ) return; @@ -285,8 +294,13 @@ void smurf_jsatilelist( int *status ) { if( igrp ) grpDelet( &igrp, status); } -/* Sort the list of overlapping tiles into ascending order. */ +/* If we got a list of tiles, see what JSA projection should be used to + describe the mosaic so that any discontinuities are avoided. */ if( tiles && *status == SAI__OK ) { + proj = smf_jsaproj( ntile, tiles, &tiling, status ); + parPut0c( "PROJ", smf_jsaproj_tostr( proj, status ), status ); + +/* Sort the list of overlapping tiles into ascending order. */ qsort( tiles, ntile, sizeof( *tiles ), jsatilelist_icomp ); /* Display the list of overlapping tiles. */ diff --git a/applications/smurf/libsmurf/smurf_makecube.c b/applications/smurf/libsmurf/smurf_makecube.c index b313ea855eb..8137e84430d 100644 --- a/applications/smurf/libsmurf/smurf_makecube.c +++ b/applications/smurf/libsmurf/smurf_makecube.c @@ -2126,8 +2126,8 @@ void smurf_makecube( int *status ) { if( jsatiles ) { parGet0l( "TRIMTILES", &trimtiles, status ); grpSetsz( igrp4, 0, status ); - smf_jsadicer( tndf, oname, trimtiles, SMF__INST_NONE, 0, &njsatile, - igrp4, status ); + smf_jsadicer( tndf, oname, trimtiles, SMF__INST_NONE, + SMF__JSA_HPX, &njsatile, igrp4, status ); delete = -1; } diff --git a/applications/smurf/libsmurf/smurf_makemap.c b/applications/smurf/libsmurf/smurf_makemap.c index ace256e95bc..76ccf83a1c1 100644 --- a/applications/smurf/libsmurf/smurf_makemap.c +++ b/applications/smurf/libsmurf/smurf_makemap.c @@ -1929,8 +1929,8 @@ void smurf_makemap( int *status ) { if( jsatiles ) { parGet0l( "TRIMTILES", &trimtiles, status ); grpSetsz( igrp4, 0, status ); - smf_jsadicer( tndf, oname, trimtiles, SMF__INST_NONE, 0, &njsatile, - igrp4, status ); + smf_jsadicer( tndf, oname, trimtiles, SMF__INST_NONE, SMF__JSA_HPX, + &njsatile, igrp4, status ); ndfDelet( &tndf, status ); } else { grpPut1( igrp4, oname, 0, status ); diff --git a/applications/smurf/scripts/jsajoin.py b/applications/smurf/scripts/jsajoin.py index 61e7594c9d5..ead77ca83e1 100755 --- a/applications/smurf/scripts/jsajoin.py +++ b/applications/smurf/scripts/jsajoin.py @@ -126,6 +126,8 @@ * 26-SEP-2014 (DSB): * Use smurf:jsapaster instead of kappa:paste to stick the tiles * together. +* 2-OCT-2014 (DSB): +* Resample the SMURF extension NDFs in the same way as the main NDF. *- ''' @@ -521,25 +523,37 @@ def cleanup(): method = "gauss" width = 0.8*pixsize_ref/pixsize_jsa -# Create the output NDF by resampling the combined NDF holding all -# tiles. Do 2D and 3D separately. +# Create a group of NDFs that need to be resampled. This is the +# combined NDF holding all tiles, plus any NDFs in its SMURF +# extension. + subndfs = NDG( "{0}.more.smurf".format(starutil.shell_quote(jsa_montage[0],True)) ) + ndfstoresample = NDG( [jsa_montage, subndfs ] ) + +# Get a corresponding group of output NDFs. if region: out = outdata else: out = NDG(1) + ndf_list = [] + for ndf in ndfstoresample: + ndf_list.append( ndf.replace( jsa_montage[0], out[0] ) ) + resampledndfs = NDG( ndf_list ) + +# Create the output NDF by resampling the combined NDF holding all +# tiles. Do 2D and 3D separately. if lz == None: invoke( "$KAPPA_DIR/wcsalign in={0} out={1} ref={2} lbnd=\[{3},{4}\] " "ubnd=\[{5},{6}\] method={7} params=\[0,{8}\]". - format(jsa_montage,out,ref,lx,ly,ux,uy,method,width) ) + format(ndfstoresample,resampledndfs,ref,lx,ly,ux,uy,method,width) ) else: invoke( "$KAPPA_DIR/wcsalign in={0} out={1} ref={2} lbnd=\[{3},{4},{5}\] " "ubnd=\[{6},{7},{8}\] method={9} params=\[0,{10}\]". - format(jsa_montage,out,ref,lx,ly,lz,ux,uy,uz,method,width) ) + format(ndfstoresample,resampledndfs,ref,lx,ly,lz,ux,uy,uz,method,width) ) # If using all input tiles, strip any bad border from the output. if region == None: - invoke( "$KAPPA_DIR/ndfcopy in={0} out={1} trimbad".format(out,outdata) ) + invoke( "$KAPPA_DIR/ndfcopy in={0} out={1} trimbad exten=yes".format(out,outdata) ) # Remove temporary files. cleanup() diff --git a/applications/smurf/scripts/jsasplit.py b/applications/smurf/scripts/jsasplit.py index 9f4a2ad066c..c5392b6461b 100755 --- a/applications/smurf/scripts/jsasplit.py +++ b/applications/smurf/scripts/jsasplit.py @@ -122,6 +122,10 @@ * 26-JUN-2014 (DSB): * Support input NDFs that straddle a discontinuity in the HPX * projection. +* 2-OCT-2014 (DSB): +* - Let jsatilelist determine the best projection to use for the JSA +* grid (HPX, HPX12, XPHN or XPHS). +* - Resample the SMURF extension NDFs in the same way as the main NDF. *- ''' @@ -245,59 +249,17 @@ def cleanup(): # JSADICER requires the input array to be gridded on the JSA all-sky # pixel grid. This is normally an HPX projection, but if the supplied # NDF straddles a discontinuity in the HPX projection then we need to -# use an XPH (polar HEALPix) projection instead. So now we see if this -# is the case. Initially, assume that we can use a normal HPX projection. - usexph = "None" - -# Now loop round all the tiles touched by the supplied NDF. - igore_first = -1 - for tile in tiles: - -# Get the RA and Dec at the centre of the tile, and convert to degrees. - invoke( "$SMURF_DIR/jsatileinfo itile={0} instrument={1} quiet".format(tile,instrument) ) - racen = math.degrees(float(starutil.get_task_par( "RACEN", "jsatileinfo" ))) - deccen = math.degrees(float(starutil.get_task_par( "DECCEN", "jsatileinfo" ))) - -# Ensure the RA is in the range 0 - 360. - if racen < 0.0: - racen += 360.0 - -# The HPX projection is made up of four "gores", each of which spans -# 90 degrees in RA. Find the zero-based integer index of the gore -# containing the current tile. - igore = int( racen / 90.0 ) - -# Discontinuities only affect tiles in the polar regions of the HPX -# projection, so pass on if the Dec is below the value defining the -# boundary between polar and equatorial regions. First deal with -# northern polar tiles. - if deccen > HPX_TRANS: - -# If this is the first polar tile, just record its gore index. - if igore_first == -1: - igore_first = igore - -# Otherwise, if the current polar tile is in a different gore to the first -# polar tile, the NDF straddles a northern HPX discontinuity, so use an -# XPH projection centred on the north pole. - elif igore != igore_first: - usexph = "North" - break - -# Now do the same for southern polar tiles. Set usexph to indicate -# a southern XPH projection should be used. - elif deccen < -HPX_TRANS: - if igore_first == -1: - igore_first = igore - elif igore != igore_first: - usexph = "South" - break; +# use a different flavour of HPX (either an HPX projection centred on +# RA=12h or am XPH (polar HEALPix) projection centred on the north or +# south pole). The above call to jsatileinfo will have determined the +# appropriate projection to use, so get it. + proj = starutil.get_task_par( "PROJ", "jsatilelist" ) # Create a file holding the FITS-WCS header for the first tile, using -# an HPX or XPH projection as determined above. +# the type of projection determined above. head = "{0}/header".format(NDG.tempdir) invoke( "$SMURF_DIR/jsatileinfo itile={0} instrument={1} header={2} " - "usexph={3} quiet".format(tiles[0],instrument,head,usexph) ) + "proj={3} quiet".format(tiles[0],instrument,head,proj) ) # Get the lower pixel index bounds of the first tile. lx = int( starutil.get_task_par( "LBND(1)", "jsatileinfo" ) ) @@ -336,11 +298,22 @@ def cleanup(): method = "gauss" width = 0.8*pixsize_tile/pixsize_in +# Create a group of NDFs that need to be split. This is the main +# supplied NDF, plus any NDFs in the SMURF extension of the main NDF. + subndfs = NDG( "{0}.more.smurf".format(starutil.shell_quote(inndf[0],True)) ) + ndfstosplit = NDG( [inndf, subndfs ] ) + +# Get a corresponding group of intermediate NDFs. + jsa_montage = NDG( 1 ) + ndf_list = [] + for ndf in ndfstosplit: + ndf_list.append( ndf.replace( inndf[0], jsa_montage[0] ) ) + splitndfs = NDG( ndf_list ) + # Create an intermediate NDF by resampling the supplied NDF onto the pixel -# grid of the first tile. Do 2D and 3D separately. - jsa_montage = NDG(1) +# grid of the first tile. Also resample any sub-NDFs. invoke( "$KAPPA_DIR/wcsalign in={0} out={1} ref={2} lbnd=! method={3} " - "params=\[0,{4}\]".format(inndf,jsa_montage,ref,method,width) ) + "params=\[0,{4}\]".format(ndfstosplit,splitndfs,ref,method,width) ) # Dice this resampled image up into parts corresponding to JSA tiles. print( invoke( "$SMURF_DIR/jsadicer in={0} out={1} instrument={2} trim={3}". diff --git a/applications/smurf/scripts/starutil.py b/applications/smurf/scripts/starutil.py index 7bd850e5d2e..dc9b4f6ff74 100755 --- a/applications/smurf/scripts/starutil.py +++ b/applications/smurf/scripts/starutil.py @@ -456,7 +456,7 @@ def get_task_par( parname, taskname, **kwargs ): return result -def shell_quote(text): +def shell_quote(text,remove=False): """ Put single quotes around a string (and escape any embedded single @@ -470,6 +470,9 @@ def shell_quote(text): Arguments: command = string The full command including directory and arguments. The + remove = boolean + If True, remove any existing shell quotes rather than + adding them. Returned Value: The quoted string. @@ -477,10 +480,19 @@ def shell_quote(text): """ if text != None: - if not re.search( "^\s*\'(.*)\'\s*$",text): - return "'" + text.replace("'", "'\\''") + "'" + + if remove: + match = re.search( "^\s*\'(.*)\'\s*$",text) + if match: + return match.group(1) + else: + return text + else: - return text + if not re.search( "^\s*\'(.*)\'\s*$",text): + return "'" + text.replace("'", "'\\''") + "'" + else: + return text else: return None diff --git a/applications/smurf/smurf.ifd.in b/applications/smurf/smurf.ifd.in index f4b263d94a8..bff923793ad 100755 --- a/applications/smurf/smurf.ifd.in +++ b/applications/smurf/smurf.ifd.in @@ -2783,13 +2783,13 @@ package @PACKAGE@ { helpkey * } - parameter usexph { + parameter proj { type LITERAL access READ vpath DEFAULT ppath CURRENT DEFAULT - prompt {XPH projection pole - north or south} - default "None" + prompt {JSA projection} + default "HPX" helpkey * } } @@ -2996,13 +2996,13 @@ package @PACKAGE@ { helpkey * } - parameter usexph { + parameter proj { type LITERAL access READ vpath DEFAULT ppath CURRENT DEFAULT - prompt {XPH projection pole - north or south} - default "None" + prompt {JSA projection} + default "HPX" helpkey * } @@ -3033,6 +3033,14 @@ package @PACKAGE@ { helpkey * } + parameter proj { + type _CHAR + access WRITE + vpath DEFAULT + default UNKNOWN + helpkey * + } + parameter tiles { size * type _INTEGER