healpix_java-3.31/0000755000175000017500000000000013021550137012210 5ustar leoleohealpix_java-3.31/src/0000755000175000017500000000000012760017537013012 5ustar leoleohealpix_java-3.31/src/healpix/0000755000175000017500000000000012760017537014444 5ustar leoleohealpix_java-3.31/src/healpix/essentials/0000755000175000017500000000000012760017540016610 5ustar leoleohealpix_java-3.31/src/healpix/essentials/HealpixMap.tmpl0000644000175000017500000001755512422415246021553 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; import java.util.Arrays; /** Class representing a full HEALPix map containing values. This class is conceptually very similar the the Healpix_Map<> class of Healpix_cxx. @copyright 2011,2012 Max-Planck-Society @author Martin Reinecke */ public class HealpixMap extends HealpixBase { private [] data; public static final undef=()(-1.6375e30); public HealpixMap() throws Exception { this(1,Scheme.NESTED); } public HealpixMap(long nside_in, Scheme scheme_in) throws Exception { super(nside_in,scheme_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=new [(int)getNpix()]; } public HealpixMap([] data_in, Scheme scheme_in) throws Exception { super(npix2Nside(data_in.length),scheme_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=data_in; } /** Adjusts the object to nside_in. @param nside_in the new Nside parameter */ public void setNside (long nside_in) throws Exception { if (nside_in!=nside) { super.setNside(nside_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=new [(int)getNpix()]; } } /** Adjusts the object to nside_in and scheme_in. @param nside_in the new Nside parameter @param scheme_in the new ordering scheme */ public void setNsideAndScheme (long nside_in, Scheme scheme_in) throws Exception { super.setNsideAndScheme(nside_in,scheme_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=new [(int)getNpix()]; } /** Adjusts the object to scheme_in, and sets pixel data to data_in. @param data_in pixel data; must have a valid length (12*nside^2) @param scheme_in the new ordering scheme */ public void setDataAndScheme([] data_in, Scheme scheme_in) throws Exception { super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in); data=data_in; } /** Sets all map pixel to a specific value. @param val pixel value to use */ public void fill( val) { Arrays.fill(data,val); } /** Converts the map from NESTED to RING scheme or vice versa. This operation is done in-place, i.e. it does not require additional memory. */ public void swapScheme() throws Exception { HealpixUtils.check((order>=0) && (order<=13), "swapping not supported for this Nside"); for (int m=0; m pixbuf = data[istart]; long iold = istart, inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart); while (inew != istart) { data[(int)iold] = data[(int)inew]; iold = inew; inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew); } data[(int)iold] = pixbuf; } scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING; } /** Returns the value of the pixel with a given index. @param ipix index of the requested pixel @return pixel value */ public getPixel(int ipix) { return data[ipix]; } /** Returns the value of the pixel with a given index. @param ipix index of the requested pixel @return pixel value */ public getPixel(long ipix) { return data[(int)ipix]; } /** Sets the value of a specific pixel. @param ipix index of the pixel @param val new value for the pixel */ public void setPixel(int ipix, val) { data[ipix] = val; } /** Sets the value of a specific pixel. @param ipix index of the pixel @param val new value for the pixel */ public void setPixel(long ipix, val) { data[(int)ipix] = val; } /** Returns the array containing all map pixels. @return the map array */ public [] getData() { return data; } /** Imports the map "orig" to this object, adjusting pixel ordering. @param orig map to import */ public void importNograde (HealpixMap orig) throws Exception { HealpixUtils.check (nside==orig.nside, "importNograde: maps have different nside"); if (orig.scheme == scheme) System.arraycopy(orig.data,0,data,0,(int)npix); else for (int m=0; m orig) throws Exception { HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade"); int fact = (int)(nside/orig.nside); HealpixUtils.check(nside==orig.nside*fact, "the larger Nside must be a multiple of the smaller one"); for (int m=0; m orig, boolean pessimistic) throws Exception { HealpixUtils.check(nside) (sum/hits); } } /** Imports the map "orig" to this object, adjusting pixel ordering and resolution if necessary. @param orig map to import @param pessimistic only used when resolution must be reduced: if true, set a pixel to undefined if at least one the original subpixels was undefined; otherwise only set it to undefined if all original subpixels were undefined. */ public void importGeneral (HealpixMap orig, boolean pessimistic) throws Exception { if (orig.nside==nside) importNograde(orig); else if (orig.nside=2,"too few points"); center = point[0].add(point[1]); center.normalize(); cosrad = point[0].dot(center); for (int i=2; i bhdu = (new Fits(inp)).getHDU(1); Header head = bhdu.getHeader(); Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(0); long[] data=null; if (tmp instanceof long[]) data = (long[])tmp; else if (tmp instanceof int[]) { int[] tmp2 = (int[])tmp; data = new long[tmp2.length]; for (int i=0; i0) maxval=data[data.length-1]; if (maxval<=0x7fff) { short[] dtmp = new short[data.length]; for (int i=0; i=2*Math.PI) phi -= 2*Math.PI; } /** Conversion from {@link Zphi} */ public Pointing (Zphi zphi) { double xy=Math.sqrt((1.-zphi.z)*(1.+zphi.z)); theta = FastMath.atan2(xy,zphi.z); phi=zphi.phi; } // for some reason, the alternative below is much slower... //{ theta=FastMath.acos(zphi.z); phi=zphi.phi; } /** Normalize theta range */ public void normalizeTheta() { theta=HealpixUtils.fmodulo(theta,2*Math.PI); if (theta>Math.PI) { phi+=Math.PI; theta=2*Math.PI-theta; } } /** Normalize theta and phi ranges */ public void normalize() { normalizeTheta(); phi=HealpixUtils.fmodulo(phi,2*Math.PI); } public String toString() { StringBuilder s = new StringBuilder(); s.append("ptg(");s.append(theta); s.append(",");s.append(phi); s.append(")"); return s.toString(); } public boolean equals(Object o) { if (this==o) return true; if ((o==null) || (getClass()!=o.getClass())) return false; Pointing pointing = (Pointing) o; if (Double.compare(pointing.phi, phi) != 0) return false; if (Double.compare(pointing.theta, theta) != 0) return false; return true; } public int hashCode() { int result = Double.valueOf(theta).hashCode(); result = 31 * result + Double.valueOf(phi).hashCode(); return result; } } healpix_java-3.31/src/healpix/essentials/HealpixMapFloat.java0000644000175000017500000001752312422415246022501 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; import java.util.Arrays; /** Class representing a full HEALPix map containing float values. This class is conceptually very similar the the Healpix_Map<float> class of Healpix_cxx. @copyright 2011,2012 Max-Planck-Society @author Martin Reinecke */ public class HealpixMapFloat extends HealpixBase { private float[] data; public static final float undef=(float)(-1.6375e30); public HealpixMapFloat() throws Exception { this(1,Scheme.NESTED); } public HealpixMapFloat(long nside_in, Scheme scheme_in) throws Exception { super(nside_in,scheme_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=new float[(int)getNpix()]; } public HealpixMapFloat(float[] data_in, Scheme scheme_in) throws Exception { super(npix2Nside(data_in.length),scheme_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=data_in; } /** Adjusts the object to nside_in. @param nside_in the new Nside parameter */ public void setNside (long nside_in) throws Exception { if (nside_in!=nside) { super.setNside(nside_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=new float[(int)getNpix()]; } } /** Adjusts the object to nside_in and scheme_in. @param nside_in the new Nside parameter @param scheme_in the new ordering scheme */ public void setNsideAndScheme (long nside_in, Scheme scheme_in) throws Exception { super.setNsideAndScheme(nside_in,scheme_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=new float[(int)getNpix()]; } /** Adjusts the object to scheme_in, and sets pixel data to data_in. @param data_in pixel data; must have a valid length (12*nside^2) @param scheme_in the new ordering scheme */ public void setDataAndScheme(float[] data_in, Scheme scheme_in) throws Exception { super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in); data=data_in; } /** Sets all map pixel to a specific value. @param val pixel value to use */ public void fill(float val) { Arrays.fill(data,val); } /** Converts the map from NESTED to RING scheme or vice versa. This operation is done in-place, i.e. it does not require additional memory. */ public void swapScheme() throws Exception { HealpixUtils.check((order>=0) && (order<=13), "swapping not supported for this Nside"); for (int m=0; morig.nside,"importUpgrade: this is no upgrade"); int fact = (int)(nside/orig.nside); HealpixUtils.check(nside==orig.nside*fact, "the larger Nside must be a multiple of the smaller one"); for (int m=0; m>>1); } /** Returns a Moc with degraded resolution. @param order the maximum HEALPix order used for the result @param keepPartialCells if true, partially filled cells will be included in the output Moc; if false, they will be ignored. */ public Moc degradedToOrder (int order, boolean keepPartialCells) { int shift=2*(maxorder-order); long ofs=(1L<a) rs2.append(a,b); } return fromNewRangeSet(rs2); } /** Adds a range of pixels at a given HEALPix order to the Moc. @param order the HEALPix order of the added pixels @param p1 the first pixel of the range @param p2 the one-after-last pixel of the range */ public void addPixelRange (int order, long p1, long p2) { int shift=2*(maxorder-order); rs.add(p1<>>shift, b=r2.ivend(iv)>>>shift; r3.append(a<>>(bits-bitsleft))&((1<0,"empty input array"); bitpos=0; data=data_in.clone(); } private long get_internal (long val, int bits) { int bitsleft = 8-(int)(bitpos&7); if (bitsleft==8) {curval=data[(int)(bitpos>>>3)]; if (curval<0) curval+=256;} if (bits<=bitsleft) { val |= ((curval>>>(bitsleft-bits))&((1L<>>shift) - (r-l) + 1; if (nval<=1) return; int nb = 1+HealpixUtils.ilog2(nval-1); long val = (data[m]>>>shift)-((data[l]>>>shift)+(m-l)); long nshort=(1L<=end) // empty range { obs.put(0,8); return obs.getData(); } HealpixUtils.check(data[begin]>=0,"numbers must be nonnegative"); long combo=data[begin]; for (int i=begin+1; i>>shift; if (end-begin>maxnum) maxnum = end-begin; int maxbits=1+HealpixUtils.ilog2(maxnum); obs.put(maxbits,8); obs.put(shift,8); obs.put(end-begin,maxbits); obs.put(data[begin]>>>shift,maxbits); if (end-begin==1) return obs.getData(); // a single data entry obs.put(data[end-1]>>>shift,maxbits); interpol_encode2(data,begin,end-1,obs,shift); return obs.getData(); } private static void interpol_decode2 (long[] data, int l, int r, ibitstream ibs, int shift) throws Exception { if (r-l<=1) return; int m=l+(r-l)/2; long nval = ((data[r]-data[l])>>>shift) - (r-l) + 1; long val=0; if (nval>1) { int nb = 1+HealpixUtils.ilog2(nval-1); long nshort=(1L<=nshort) val=(val<<1)+ ibs.get(1) - nshort; } data[m]=data[l]+(((m-l)+val)< healpix.essentials is a Java package aiming to combine the advantages of other Java HEALPix libraries like the gov.fnal.eag.healpix package by N. Kuropatkin (http://home.fnal.gov/~kuropat/HEALPIX/PixTools.html), Jan Kotek's org.asterope.healpix package (https://github.com/jankotek/HEALPix), and the healpix.core package developed at ESO.
Current features include:
  • close similarities with Healpix_Base_T class from Healpix C++, which allows simultaneous development and bug fixes for both.
  • support for arbitrary positive Nside values in RING scheme; no longer limited to powers of 2
  • maximum supported Nside value: 2^29
  • significant performance improvements: most methods have been accelerated by integral factors, some by more than an order of magnitude.
  • re-implementation of queryDisc and queryPolygon:
    • query methods return RangeSet objects which allow much more compact storage of the result
    • new native query methods for NESTED ordering; these are slower than those for RING ordering, but much quicker than converting all pixels from a RING result to NESTED.
    • inclusive queries have been improved: several bugs were fixed, and the number of false positives in the result has been reduced. Users can now choose between quick inclusive queries returning more false positives, and slower ones returning fewer false positives.
  • the HealpixProc class offers a procedural (instead of object-oriented) interface to the HealpixBase functionality, which simplifies transition for users of the "Healpix" and "PixTools" classes. NOTE: this only works for Nside parameters which are powers of 2
  • many bug fixes
  • no external library dependencies, except for "nom.tam.fits" if FITS I/O is required
  • the code base is thread-safe in the following sense:
    • HealpixProc methods can be called concurrently
    • HealpixBase methods can be called concurrently on different objects
@copyright 2011, 2012 Max-Planck-Society @author Martin Reinecke */ package healpix.essentials; healpix_java-3.31/src/healpix/essentials/Vec3.java0000644000175000017500000001225112506765003020256 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; /** Cartesian 3-vector. Instead of using the javax.vecmath.Vector3d class, this separate class was implemented for two reasons: first, to avoid the external dependency from vecmath.jar, and also because the function Vector3d.angle(Vector3d v1) is too inaccurate for usage in Healpix for very small angles. @copyright (C) 2011-2015 Max-Planck-Society @author Martin Reinecke */ public class Vec3 { public double x, y, z; /** Default constructor. */ public Vec3() {} public Vec3 (Vec3 v) { x=v.x; y=v.y; z=v.z; } /** Creation from individual components */ public Vec3 (double x1, double y1, double z1) { x=x1; y=y1; z=z1; } /** Conversion from {@link Pointing} */ public Vec3 (Pointing ptg) { double sth = FastMath.sin(ptg.theta); x=sth*FastMath.cos(ptg.phi); y=sth*FastMath.sin(ptg.phi); z=FastMath.cos(ptg.theta); } /** Conversion from {@link Zphi} */ public Vec3 (Zphi zphi) { double sth = Math.sqrt((1.0-zphi.z)*(1.0+zphi.z)); x=sth*FastMath.cos(zphi.phi); y=sth*FastMath.sin(zphi.phi); z=zphi.z; } public Vec3 (double[] arr) { if(arr.length!=3) throw new IllegalArgumentException("Wrong array size"); x = arr[0]; y = arr[1]; z = arr[2]; } /** Vector length @return the length of the vector. */ public final double length() { return Math.sqrt(lengthSquared()); } /** Squared vector length @return the squared length of the vector. */ public final double lengthSquared() { return x*x + y*y + z*z; } /** Normalize the vector */ public void normalize() { double d = 1./length(); x *= d; y *= d; z *= d; } /** Return normalized vector */ public Vec3 norm() { double d = 1./length(); return new Vec3(x*d,y*d,z*d); } /** Angle between two vectors. @param v1 another vector @return the angle in radians between this vector and {@code v1}; constrained to the range [0,PI]. */ public final double angle(Vec3 v1) { return FastMath.atan2(cross(v1).length(), dot(v1)); } /** Vector cross product. @param v another vector @return the vector cross product between this vector and {@code v} */ public Vec3 cross(Vec3 v) { return new Vec3(y*v.z - v.y*z, z*v.x - v.z*x, x*v.y - v.x*y); } /** Vector scaling. * @param n the scale number to be multiply to the coordinates {@code x,y,z} * @return the vector with coordinates multiplied by {@code n} */ public Vec3 mul(double n) { return new Vec3(n*x, n*y, n*z); } /** Invert the signs of all components */ public void flip() { x=-x; y=-y; z=-z; } public Vec3 flipped() { return new Vec3(-x,-y,-z); } /** Scale the vector by a given factor @param n the scale factor */ public void scale(double n) { x*=n; y*=n; z*=n; } /** Computes the dot product of the this vector and {@code v1}. * @param v1 another vector * @return dot product */ public final double dot(Vec3 v1) { return x*v1.x + y*v1.y + z*v1.z; } /** Vector addition * @param v the vector to be added * @return addition result */ public Vec3 add(Vec3 v) { return new Vec3(x+v.x, y+v.y, z+v.z); } /** Vector subtraction * @param v the vector to be subtracted * @return subtraction result */ public Vec3 sub(Vec3 v) { return new Vec3(x-v.x, y-v.y, z-v.z); } public String toString() { StringBuilder s = new StringBuilder(); s.append("vec3(");s.append(x); s.append(",");s.append(y); s.append(",");s.append(z); s.append(")"); return s.toString(); } public double[] toArray() { return new double[]{x,y,z}; } public void toArray(double[] arr) { if(arr.length!=3) throw new IllegalArgumentException("wrong array size"); arr[0] = x; arr[1] = y; arr[2] = z; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Vec3 vec3 = (Vec3) o; if (Double.compare(vec3.x, x) != 0) return false; if (Double.compare(vec3.y, y) != 0) return false; if (Double.compare(vec3.z, z) != 0) return false; return true; } public int hashCode() { int result = Double.valueOf(x).hashCode(); result = 31 * result + Double.valueOf(y).hashCode(); result = 31 * result + Double.valueOf(z).hashCode(); return result; } } healpix_java-3.31/src/healpix/essentials/HealpixProc.java0000644000175000017500000001250212127025574021674 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; /** Procedural interface to the {@link HealpixBase} functionality. This class is intended for users who prefer a procedural (instead of object-oriented) interface to the HEALPix functionality. It should make transition from packages like PixTools easier. @copyright 2012 Max-Planck-Society @author Martin Reinecke */ public abstract class HealpixProc extends HealpixBase { static final HealpixBase[] bn=new HealpixBase[HealpixBase.order_max+1], br=new HealpixBase[HealpixBase.order_max+1]; static final double[] mpr =new double[HealpixBase.order_max+1], cmpr=new double[HealpixBase.order_max+1], smpr=new double[HealpixBase.order_max+1]; static { try { for (int i=0; i<=HealpixBase.order_max; ++i) { bn[i]=new HealpixBase(1L< 2/3 { int ntt = Math.min(3,(int)tt); double tp = tt-ntt; double tmp = ((za<0.99)||(!loc.have_sth)) ? Math.sqrt(3*(1-za)) : loc.sth/Math.sqrt((1.+za)/3.); double jp = tp*tmp; // increasing edge line index double jm = (1.0-tp)*tmp; // decreasing edge line index if (jp>=1.) jp = 1.; // for points too close to the boundary if (jm>=1.) jm = 1.; if (z>=0) { fx=1.-jm; fy=1.-jp; face=ntt; } else { fx=jp; fy=jm; face=ntt+8; } } } public Fxyf(Vec3 v) { this(new Hploc(v)); } protected Hploc toHploc() { Hploc loc = new Hploc(); double jr = jrll[face] - fx - fy; double nr; if (jr<1) { nr = jr; double tmp = nr*nr/3.; loc.z = 1 - tmp; if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; } } else if (jr>3) { nr = 4-jr; double tmp = nr*nr/3.; loc.z = tmp - 1; if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; } } else { nr = 1; loc.z = (2-jr)*2./3.; } double tmp=jpll[face]*nr+fx-fy; if (tmp<0) tmp+=8; if (tmp>=8) tmp-=8; loc.phi = (nr<1e-15) ? 0 : (0.5*Constants.halfpi*tmp)/nr; return loc; } public Vec3 toVec3() { return toHploc().toVec3(); } } healpix_java-3.31/src/healpix/essentials/Constants.java0000644000175000017500000000241412127025574021433 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; /** Some frequently used constants. */ public class Constants { /** The Constant halfpi */ public static final double halfpi = Math.PI/2.; public static final double inv_halfpi = 2./Math.PI; /** The Constant twopi. */ public static final double twopi = 2*Math.PI; public static final double inv_twopi = 1./(2*Math.PI); /** The Constant twothird. */ public static final double twothird = 2./3.; } healpix_java-3.31/src/healpix/essentials/HealpixUtils.java0000644000175000017500000001302012421674651022070 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; /** Collection of utility functions. @copyright 2011-2014 Max-Planck-Society @author Martin Reinecke */ public class HealpixUtils { /** Evaluates cond; if it is false, throws an Exception containing errtxt. */ static public void check(boolean cond, String errtxt) throws Exception { if (!cond) throw new Exception(errtxt); } /** Integer base 2 logarithm. @param arg @return the largest integer {@code n} that fulfills {@code 2^n<=arg}. For negative arguments and zero, 0 is returned. */ static public int ilog2(long arg) { return 63-Long.numberOfLeadingZeros(Math.max(arg,1L)); } /** Integer square root. @param arg @return the integer {@code n} which fulfills {@code n^2<=arg<(n+1)^2} */ static public int isqrt(long arg) { long res = (long)Math.sqrt(((double)arg)+0.5); if (arg<(1L<<50)) return (int)res; if (res*res>arg) --res; else if ((res+1)*(res+1)<=arg) ++res; return (int)res; } /** Computes the cosine of the angular distance between two z, phi positions on the unit sphere. */ static public double cosdist_zphi (double z1, double phi1, double z2, double phi2) { return z1*z2+ FastMath.cos(phi1-phi2)* Math.sqrt((1.0-z1*z1)*(1.0-z2*z2)); } /** Computes the cosine of the angular distance between two z, phi positions on the unit sphere. */ static public double cosdist_zphi (Zphi zp1, Zphi zp2) { return cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi); } /** Returns the remainder of the division {@code v1/v2}. The result is non-negative. @param v1 dividend; can be positive or negative @param v2 divisor; must be positive @return remainder of the division; positive and smaller than {@code v2} */ static public double fmodulo (double v1, double v2) { if (v1>=0) return (v1>>2)>>>1; } static private long nest_peano_helper (long pix, int order, int dir) { final short arr2[] = { 0, 35, 65, 66, 68, 5,103, 6,110,109, 15, 44, 72, 9,107, 10, 31,126, 60,125, 81, 16, 82, 51,123, 88, 26, 25,119, 84, 22, 21, 42, 75, 41,104, 12, 47, 77, 78, 38, 71, 37,100, 98, 97, 3, 32, 53, 54,116, 87, 57, 58,120, 91, 19,114, 48,113, 93, 28, 94, 63, 64, 1, 99, 2, 46, 79, 45,108, 4, 39, 69, 70, 8, 43, 73, 74, 85, 20, 86, 55,115, 80, 18, 17, 89, 24, 90, 59, 61, 62,124, 95, 106,105, 11, 40,102,101, 7, 36, 76, 13,111, 14, 34, 67, 33, 96, 127, 92, 30, 29, 27,122, 56,121, 49, 50,112, 83, 23,118, 52,117, 128,194,195,161,196,133,135,230,204,141,143,238,171,233,232,138, 149,212,214,183,221,159,158,252,217,155,154,248,178,243,241,144, 175,237,236,142,235,170,168,201,227,162,160,193,132,198,199,165, 186,251,249,152,242,176,177,211,246,180,181,215,157,220,222,191, 192,129,131,226,136,202,203,169,140,206,207,173,231,166,164,197, 213,151,150,244,145,208,210,179,153,216,218,187,254,188,189,223, 239,174,172,205,167,229,228,134,163,225,224,130,200,137,139,234, 250,184,185,219,190,255,253,156,182,247,245,148,209,147,146,240 }; final byte arr[] = { 16, 1,27, 2,31,20, 6, 5,10,19, 9,24,13,14,28,23, 0,11,17,18,21, 4,22,15,26,25, 3, 8, 7,30,12,29, 48,33,35,58,53,39,38,60,59,42,40,49,62,44,45,55, 32,50,51,41,37,52,54,47,43,57,56,34,46,63,61,36 }; final byte peano_face2path[][] = { { 2,5,2,5,3,6,3,6,2,3,2,3 }, { 2,6,2,3,3,5,2,6,2,3,3,5 } }; final byte peano_face2face[][] = { { 0,5,6,11,10,1,4,7,2,3,8,9 }, { 0,5,8,9,6,1,2,7,10,11,4,3 } }; int face = (int)(pix>>>(2*order)); long result = 0L; int state = ((peano_face2path[dir][face]<<4))|(dir<<7); int shift=2*order-4; for (; shift>=0; shift-=4) { state=arr2[(state&0xF0) | (((int)(pix>>>shift))&0xF)]; result = (result<<4) | (state&0xF); } if (shift==-2) { state=arr[((state>>>2)&0xFC) | ((int)(pix)&0x3)]; result = (result<<2) | (state&0x3); } return result + (((long)peano_face2face[dir][face])<<(2*order)); } static public long nest2peano(long pix, int order) { return nest_peano_helper(pix,order,0); } static public long peano2nest(long pix, int order) { return nest_peano_helper(pix,order,1); } } healpix_java-3.31/src/healpix/essentials/Scheme.java0000644000175000017500000000024111756436717020673 0ustar leoleopackage healpix.essentials; /** The Healpix pixel ordering scheme. */ public enum Scheme { /** RING ordering. */ RING, /** NESTED ordering. */ NESTED } healpix_java-3.31/src/healpix/essentials/HealpixMapDouble.java0000644000175000017500000001753212422415246022646 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; import java.util.Arrays; /** Class representing a full HEALPix map containing double values. This class is conceptually very similar the the Healpix_Map<double> class of Healpix_cxx. @copyright 2011,2012 Max-Planck-Society @author Martin Reinecke */ public class HealpixMapDouble extends HealpixBase { private double[] data; public static final double undef=-1.6375e30; public HealpixMapDouble() throws Exception { this(1,Scheme.NESTED); } public HealpixMapDouble(long nside_in, Scheme scheme_in) throws Exception { super(nside_in,scheme_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=new double[(int)getNpix()]; } public HealpixMapDouble(double[] data_in, Scheme scheme_in) throws Exception { super(npix2Nside(data_in.length),scheme_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=data_in; } /** Adjusts the object to nside_in. @param nside_in the new Nside parameter */ public void setNside (long nside_in) throws Exception { if (nside_in!=nside) { super.setNside(nside_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=new double[(int)getNpix()]; } } /** Adjusts the object to nside_in and scheme_in. @param nside_in the new Nside parameter @param scheme_in the new ordering scheme */ public void setNsideAndScheme (long nside_in, Scheme scheme_in) throws Exception { super.setNsideAndScheme(nside_in,scheme_in); HealpixUtils.check(nside<=(1<<13),"resolution too high"); data=new double[(int)getNpix()]; } /** Adjusts the object to scheme_in, and sets pixel data to data_in. @param data_in pixel data; must have a valid length (12*nside^2) @param scheme_in the new ordering scheme */ public void setDataAndScheme(double[] data_in, Scheme scheme_in) throws Exception { super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in); data=data_in; } /** Sets all map pixel to a specific value. @param val pixel value to use */ public void fill(double val) { Arrays.fill(data,val); } /** Converts the map from NESTED to RING scheme or vice versa. This operation is done in-place, i.e. it does not require additional memory. */ public void swapScheme() throws Exception { HealpixUtils.check((order>=0) && (order<=13), "swapping not supported for this Nside"); for (int m=0; morig.nside,"importUpgrade: this is no upgrade"); int fact = (int)(nside/orig.nside); HealpixUtils.check(nside==orig.nside*fact, "the larger Nside must be a multiple of the smaller one"); for (int m=0; m0.0); } } public void test_ringnestring()throws Exception { System.out.println("Testing identity ring2nest(nest2ring(i))==i"); Random rng = new Random(5); for (int order=0; order<=HealpixBase.order_max; ++order) { HealpixBase base = new HealpixBase (1L<=mincos); zp2 = base2.pix2zphi(base2.zphi2pix(zp1)); cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi); assertTrue("zphipixzphi problem",cd1>=mincos); } } for (long nside=3; nside<(1L<=mincos); } } } public void test_neighbours() throws Exception { System.out.println("Testing neighbour function"); int omax=HealpixBase.order_max; Random rng = new Random(5); for (int order=0; order<=omax; ++order) { HealpixBase base1 = new HealpixBase (1L<=7)||((order==0)&&(nnb>=6))); } } for (long nside=3; nside<(1L<=0) { ++nnb; assertTrue("neighbour problem 5",base.pix2vec(nb[n]).angle(v)=7); } } } public void test_query_disc_strict() throws Exception { System.out.println("Testing non-inclusive queryDisc()"); Random rng = new Random(5); for (int order=0; order<=5; ++order) { HealpixBase base = new HealpixBase (1L<cosrad; assertFalse ("query_disc_strict problem",inside^map[i]); } for (int i=0; i>order)); for (int m=0; m=nv2); assertTrue("queryDisc problem 3", nv2>=nval); } } } public void testQueryPolygon() throws Exception { System.out.println("Testing queryPolygon()"); HealpixBase base = new HealpixBase(1024,Scheme.NESTED); Pointing[] corner = new Pointing[4]; corner[0]=new Pointing(new Vec3(1,0.01,0.01)); corner[1]=new Pointing(new Vec3(1,1,-0.3)); corner[2]=new Pointing(new Vec3(0.01,1,0.01)); corner[3]=new Pointing(new Vec3(0.01,0.01,1)); RangeSet lrs=base.queryPolygon(corner); assertEquals("QueryPolygon problem",lrs.nval(),1696714); lrs=base.queryPolygonInclusive(corner,4); assertEquals("QueryPolygon problem",lrs.nval(),1700206); base = new HealpixBase(1024,Scheme.RING); lrs=base.queryPolygon(corner); assertEquals("QueryPolygon problem",lrs.nval(),1696714); lrs=base.queryPolygonInclusive(corner,4); assertEquals("QueryPolygon problem",lrs.nval(),1700206); } public void testQueryPolygon2() throws Exception { System.out.println("Testing queryPolygon() empirically"); int omax=17; Random rng = new Random(5); for (int order=0; order<=omax; ++order) { HealpixBase rbase = new HealpixBase (1L<>order)); for (int m=0; m=nv2); assertTrue("queryPolygon problem 3", nv2>=nval); } } } public void testSmallPoly() throws Exception { System.out.println("Testing small polygon"); HealpixBase base = new HealpixBase(1024,Scheme.NESTED); Pointing[] corner = new Pointing[4]; corner[0]=new Pointing(2.7190983373838,1.50840508184223); corner[1]=new Pointing(2.7190980835706067,1.5084057923700163); corner[2]=new Pointing(2.719101654815075,1.5084144044115078); corner[3]=new Pointing(2.719101908630556,1.5084136938829422); RangeSet lrs=base.queryPolygon(corner); } public void test() throws Exception { int nside=256; HealpixBase base = new HealpixBase(nside,Scheme.NESTED); HealpixBase base2 = new HealpixBase(nside,Scheme.RING); for (int i=0; i<12*nside*nside; ++i) { assertEquals ("pixel mismatch_nest",i,base.ang2pix(base.pix2ang(i))); assertEquals ("pixel mismatch_nest",i,base.vec2pix(base.pix2vec(i))); assertEquals ("pixel mismatch_ring",i,base2.ang2pix(base2.pix2ang(i))); assertEquals ("pixel mismatch_ring",i,base2.vec2pix(base2.pix2vec(i))); assertEquals ("pixel mismatch",i,base.ring2nest(base2.ang2pix(base.pix2ang(i)))); assertEquals ("pixel mismatch_ringnestring",i,base.ring2nest(base.nest2ring(i))); } } } healpix_java-3.31/src/healpix/essentials/test/MocQueryTest.java0000644000175000017500000005625212551150407023046 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials.test; import healpix.essentials.*; import junit.framework.TestCase; import java.io.*; import java.util.Arrays; import java.util.ArrayList; /** Tests for the MocQuery class @copyright 2015 Max-Planck-Society @author Martin Reinecke */ public class MocQueryTest extends TestCase { private ArrayList rawToPoly(double[] inp) throws Exception { HealpixUtils.check((inp.length>=6)&&((inp.length&1)==0), "bad input array"); ArrayList res = new ArrayList(); for (int i=0; i poly, int o1, int o2, String out) throws Exception { Moc moc = MocQuery.queryGeneralPolygonInclusive (poly,o1,o1); if (out!="") MocFitsIO.mocToFits(moc,out+"_inc_"+o1+".fits"); for (int o=o1+1; o<=o2; ++o) { Moc moc2 = MocQuery.queryGeneralPolygonInclusive (poly,o1,o2); assertTrue("inconsistency",moc.contains(moc2)); if (out!="") MocFitsIO.mocToFits(moc2,out+"_inc_"+o+".fits"); moc=moc2; } Moc moc2 = MocQuery.queryGeneralPolygon(poly,o1); if (out!="") MocFitsIO.mocToFits(moc2,out+".fits"); assertTrue("inconsistency",moc.contains(moc2)); } public void test1() throws Exception { double[] polyraw=new double[]{ 83.6479647404001, 22.06796566083695, 83.57919759304697, 22.014902754311912, 83.54565527259793, 22.05666932013043, 83.54535325267885, 22.05666728060237, 83.54535545323692, 22.056387364445676, 83.54535985432697, 22.05582753212609, 83.54536865640274, 22.05470786746255, 83.54537525786826, 22.05386811894398, 83.53952949498002, 21.952773396955234, 83.63157603991105, 21.995362438376056, 83.64144959973622, 21.965751089665403, 83.69912966373616, 22.00612703969729 }; checkPoly(rawToPoly(polyraw),13,15,""); } public void test2() throws Exception { double[] polyraw=new double[]{ 83.69572488226052, 22.01842407483951, 83.66469321144844, 22.05155150183524, 83.66439120028902, 22.051549680680765, 83.62952475535761, 22.02838142338798, 83.58771024980035, 22.04715033027345, 83.5874082491367, 22.04714836793211, 83.58741036646086, 22.0468684509572, 83.58741671838312, 22.046028700022926, 83.57147626994606, 21.99805614401068, 83.59369254263831, 21.934377044862455, 83.59369043939574, 21.93465696148893, 83.59368833614487, 21.934936878119167, 83.59338236664615, 21.935494760357145, 83.59338026277467, 21.93577467699384, 83.64687451268995, 21.966904215256918, 83.60550939897153, 22.00919444338953, 83.66653272555045, 22.004534367269507, 83.69542484507058, 22.018142392123163 }; checkPoly(rawToPoly(polyraw),13,15,""); } public void test3() throws Exception { ArrayList vert=new ArrayList(); vert.add(new Vec3(new Pointing(1.1523428941043317,1.000795791041251))); vert.add(new Vec3(new Pointing(1.1523106929911657,1.0008281306683644))); vert.add(new Vec3(new Pointing(1.1521818924889993,1.0009574985526972))); vert.add(new Vec3(new Pointing(1.1519887035905163,1.001151578519077))); vert.add(new Vec3(new Pointing(1.151859918897493,1.0012809839336458))); vert.add(new Vec3(new Pointing(1.1514894198468866,1.001263637028638))); vert.add(new Vec3(new Pointing(1.1513659202048774,1.0012578536443903))); vert.add(new Vec3(new Pointing(1.1511859573237597,1.0011139425394953))); vert.add(new Vec3(new Pointing(1.1510060020113047,1.0009700085527964))); vert.add(new Vec3(new Pointing(1.1508556031353578,1.0008613172356937))); vert.add(new Vec3(new Pointing(1.150673007120061,1.0007849744501682))); vert.add(new Vec3(new Pointing(1.1503938085112773,1.0008057187152946))); vert.add(new Vec3(new Pointing(1.150205908484378,1.0008646491036832))); vert.add(new Vec3(new Pointing(1.149953611594119,1.000988341677547))); vert.add(new Vec3(new Pointing(1.1497335179693469,1.0010796806589697))); vert.add(new Vec3(new Pointing(1.1494247698862567,1.0010651879076278))); vert.add(new Vec3(new Pointing(1.1492448165599576,1.0009211385295873))); vert.add(new Vec3(new Pointing(1.149000469199188,1.0008418420185987))); vert.add(new Vec3(new Pointing(1.1485894925444542,1.000279935669881))); vert.add(new Vec3(new Pointing(1.1486539077047668,1.0002151640462313))); vert.add(new Vec3(new Pointing(1.1490324086471566,1.0000296562389843))); vert.add(new Vec3(new Pointing(1.1492203271505665,0.9999707639528252))); vert.add(new Vec3(new Pointing(1.1495639559481354,0.9998853760122856))); vert.add(new Vec3(new Pointing(1.149848517849616,0.9997294255486839))); vert.add(new Vec3(new Pointing(1.1499773768285775,0.9995999921162992))); vert.add(new Vec3(new Pointing(1.1501062421175312,0.9994705737522844))); vert.add(new Vec3(new Pointing(1.1501733657022064,0.9993382245815566))); vert.add(new Vec3(new Pointing(1.150157309455921,0.9989646985587307))); vert.add(new Vec3(new Pointing(1.1502783613271745,0.9982588937208289))); vert.add(new Vec3(new Pointing(1.150367358658019,0.9975854875791592))); vert.add(new Vec3(new Pointing(1.1503145561122339,0.9966002329829549))); vert.add(new Vec3(new Pointing(1.1501837017642849,0.9960177261452899))); vert.add(new Vec3(new Pointing(1.1500880289072624,0.9953352142578803))); vert.add(new Vec3(new Pointing(1.1498339618638964,0.9947464292684306))); vert.add(new Vec3(new Pointing(1.1496599663238942,0.9944665891792631))); vert.add(new Vec3(new Pointing(1.1495211017074738,0.9940867625529576))); vert.add(new Vec3(new Pointing(1.1494032633666398,0.993945254823653))); vert.add(new Vec3(new Pointing(1.1492854324600088,0.9938037321908275))); vert.add(new Vec3(new Pointing(1.1491647775622915,0.9937298631728655))); vert.add(new Vec3(new Pointing(1.1489093237140704,0.9939204821489465))); vert.add(new Vec3(new Pointing(1.1487240963858985,0.9939111896936369))); vert.add(new Vec3(new Pointing(1.148418211419246,0.9938280074878991))); vert.add(new Vec3(new Pointing(1.148203527561705,0.9937833060402974))); vert.add(new Vec3(new Pointing(1.1480562505373242,0.9936062948138628))); vert.add(new Vec3(new Pointing(1.1479678899060295,0.9935000768652547))); vert.add(new Vec3(new Pointing(1.1479089851456499,0.9934292602260698))); vert.add(new Vec3(new Pointing(1.1478263164713338,0.9931876107503619))); vert.add(new Vec3(new Pointing(1.147658188833066,0.9927719711268423))); vert.add(new Vec3(new Pointing(1.147605019627341,0.9925656960713723))); vert.add(new Vec3(new Pointing(1.147513838399067,0.9925271325090353))); vert.add(new Vec3(new Pointing(1.1469790356795493,0.9927375232998785))); vert.add(new Vec3(new Pointing(1.1467586597155184,0.9928281691313717))); vert.add(new Vec3(new Pointing(1.1466646212864107,0.9928573452285496))); vert.add(new Vec3(new Pointing(1.146570583168876,0.9928865238140747))); vert.add(new Vec3(new Pointing(1.1464822508174166,0.9927802065018877))); vert.add(new Vec3(new Pointing(1.1464233649158908,0.9927093236024059))); vert.add(new Vec3(new Pointing(1.1463350395636842,0.9926029922143758))); vert.add(new Vec3(new Pointing(1.1464082297063476,0.9923351250888106))); vert.add(new Vec3(new Pointing(1.1465403155639036,0.9921381737414078))); vert.add(new Vec3(new Pointing(1.146801650920068,0.9918120793817878))); vert.add(new Vec3(new Pointing(1.146992632145478,0.9916860897831967))); vert.add(new Vec3(new Pointing(1.147336526500701,0.9916018945040467))); vert.add(new Vec3(new Pointing(1.1475540582351127,0.991579108720834))); vert.add(new Vec3(new Pointing(1.148297344412475,0.9908370227283142))); vert.add(new Vec3(new Pointing(1.14831771135701,0.9903631889078771))); vert.add(new Vec3(new Pointing(1.1483410904887272,0.9898216751345671))); vert.add(new Vec3(new Pointing(1.14817642568152,0.9893381849506938))); vert.add(new Vec3(new Pointing(1.1478619397258643,0.9887449725688633))); vert.add(new Vec3(new Pointing(1.1476621504872502,0.9883612311158905))); vert.add(new Vec3(new Pointing(1.1473389454791498,0.987970892009681))); vert.add(new Vec3(new Pointing(1.1470745474697959,0.9876514390156884))); vert.add(new Vec3(new Pointing(1.1467220762850698,0.9872253830842613))); vert.add(new Vec3(new Pointing(1.1465134990729606,0.9870445283107344))); vert.add(new Vec3(new Pointing(1.1463576636239432,0.9870701715700294))); vert.add(new Vec3(new Pointing(1.1461311065061512,0.987295784658764))); vert.add(new Vec3(new Pointing(1.145969291549504,0.9874569649988388))); vert.add(new Vec3(new Pointing(1.1456780489082319,0.9877471487418389))); vert.add(new Vec3(new Pointing(1.1453544826095992,0.9880696643744283))); vert.add(new Vec3(new Pointing(1.1451309779989192,0.9882276968098427))); vert.add(new Vec3(new Pointing(1.1449223325837785,0.9880468062013319))); vert.add(new Vec3(new Pointing(1.144684321314146,0.9878303468533963))); vert.add(new Vec3(new Pointing(1.1444786880119573,0.9875815784705101))); vert.add(new Vec3(new Pointing(1.1444055321874065,0.9871359210384268))); vert.add(new Vec3(new Pointing(1.1443527978610553,0.9869292081606309))); vert.add(new Vec3(new Pointing(1.1443588066568586,0.9867935954286845))); vert.add(new Vec3(new Pointing(1.1443294428641322,0.9867580408743656))); vert.add(new Vec3(new Pointing(1.1441178863108807,0.9866447588708069))); vert.add(new Vec3(new Pointing(1.143627025593574,0.9865504721602422))); vert.add(new Vec3(new Pointing(1.1430714198687517,0.9865206748900628))); vert.add(new Vec3(new Pointing(1.142486453971728,0.9864552736851653))); vert.add(new Vec3(new Pointing(1.1421130353865951,0.9865032583536448))); vert.add(new Vec3(new Pointing(1.1418013514800418,0.9865545719393494))); vert.add(new Vec3(new Pointing(1.1415280685012117,0.9864378231638371))); vert.add(new Vec3(new Pointing(1.1413195436592867,0.9862564662025781))); vert.add(new Vec3(new Pointing(1.1411140566169835,0.9860071695710151))); vert.add(new Vec3(new Pointing(1.1410583793726072,0.9858680266790968))); vert.add(new Vec3(new Pointing(1.1411585594318707,0.9857032675075046))); vert.add(new Vec3(new Pointing(1.1415471911174158,0.9853159421723982))); vert.add(new Vec3(new Pointing(1.1417091373202277,0.9851545968685336))); vert.add(new Vec3(new Pointing(1.141935878135893,0.9849287531836823))); vert.add(new Vec3(new Pointing(1.1421919741278386,0.9847385729150904))); vert.add(new Vec3(new Pointing(1.1427212823451636,0.9846653708690231))); vert.add(new Vec3(new Pointing(1.1429388730086534,0.9846432208437782))); vert.add(new Vec3(new Pointing(1.1431888603402285,0.9845888377168718))); vert.add(new Vec3(new Pointing(1.143221257341095,0.9845566013231962))); vert.add(new Vec3(new Pointing(1.1431393920272823,0.9843141087835374))); vert.add(new Vec3(new Pointing(1.142940242012983,0.9839291446460309))); vert.add(new Vec3(new Pointing(1.1427704685698539,0.9835797337470248))); vert.add(new Vec3(new Pointing(1.1426917873195213,0.9832693018292363))); vert.add(new Vec3(new Pointing(1.142613142293535,0.9829588475331977))); vert.add(new Vec3(new Pointing(1.1426935245487904,0.9825551447276581))); vert.add(new Vec3(new Pointing(1.1428587549013667,0.9823262384230973))); vert.add(new Vec3(new Pointing(1.1432802997807938,0.9819076068355195))); vert.add(new Vec3(new Pointing(1.1435428818201463,0.981582241584326))); vert.add(new Vec3(new Pointing(1.1438023569877103,0.9813247693528765))); vert.add(new Vec3(new Pointing(1.1440879942426359,0.981170799141964))); vert.add(new Vec3(new Pointing(1.1443087617014966,0.9810812052364875))); vert.add(new Vec3(new Pointing(1.1444939405572025,0.9810915890969772))); vert.add(new Vec3(new Pointing(1.1446435321631656,0.9812019262076423))); vert.add(new Vec3(new Pointing(1.1449657419610033,0.9815937325674373))); vert.add(new Vec3(new Pointing(1.145170814762998,0.9818430040096161))); vert.add(new Vec3(new Pointing(1.145405212420505,0.9821278286770655))); vert.add(new Vec3(new Pointing(1.1455810307686392,0.982341407316913))); vert.add(new Vec3(new Pointing(1.1456396407122253,0.9824125926080799))); vert.add(new Vec3(new Pointing(1.1457568663384885,0.9825549518114552))); vert.add(new Vec3(new Pointing(1.1458447905784235,0.982661711260155))); vert.add(new Vec3(new Pointing(1.146056176224855,0.9827752848212115))); vert.add(new Vec3(new Pointing(1.1464203363305736,0.982931223860804))); vert.add(new Vec3(new Pointing(1.1465700046565381,0.983041338988599))); vert.add(new Vec3(new Pointing(1.146931084242241,0.9832649203344934))); vert.add(new Vec3(new Pointing(1.147304554977569,0.983217580321881))); vert.add(new Vec3(new Pointing(1.14755456833011,0.983163460791517))); vert.add(new Vec3(new Pointing(1.1476518102952684,0.9830670054161794))); vert.add(new Vec3(new Pointing(1.147911138996274,0.9828098319777566))); vert.add(new Vec3(new Pointing(1.1480146153175843,0.9825780284118409))); vert.add(new Vec3(new Pointing(1.1478512630860116,0.982093928824457))); vert.add(new Vec3(new Pointing(1.1477465895705665,0.981680894029768))); vert.add(new Vec3(new Pointing(1.1477037064890643,0.9812712698299393))); vert.add(new Vec3(new Pointing(1.1476901713851657,0.980897208503522))); vert.add(new Vec3(new Pointing(1.147738413955949,0.9805266127850084))); vert.add(new Vec3(new Pointing(1.1479718818582025,0.9801664735990022))); vert.add(new Vec3(new Pointing(1.148205397839398,0.9798064091969002))); vert.add(new Vec3(new Pointing(1.1483708576902831,0.9795782695316553))); vert.add(new Vec3(new Pointing(1.1487928200059858,0.9791611823574279))); vert.add(new Vec3(new Pointing(1.1493382912635042,0.9787512843635041))); vert.add(new Vec3(new Pointing(1.1502609222180684,0.9788716216588957))); vert.add(new Vec3(new Pointing(1.1504396821178993,0.9790173766494347))); vert.add(new Vec3(new Pointing(1.1507908399518807,0.9794440181022032))); vert.add(new Vec3(new Pointing(1.1509893471305994,0.9798280210118206))); vert.add(new Vec3(new Pointing(1.1511815695494167,0.9803471360053592))); vert.add(new Vec3(new Pointing(1.1513477656945341,0.9807630544316528))); vert.add(new Vec3(new Pointing(1.1516604798024512,0.98135646536512))); vert.add(new Vec3(new Pointing(1.1517033801181038,0.981765361770002))); vert.add(new Vec3(new Pointing(1.1517170406506425,0.9821387451013951))); vert.add(new Vec3(new Pointing(1.1515842233393097,0.9823346503008543))); vert.add(new Vec3(new Pointing(1.1513896921866162,0.9825271705205277))); vert.add(new Vec3(new Pointing(1.1511627565046656,0.9827518193104232))); vert.add(new Vec3(new Pointing(1.1508710094941494,0.9830407197788995))); vert.add(new Vec3(new Pointing(1.1506441165054242,0.9832654717657893))); vert.add(new Vec3(new Pointing(1.150482061529942,0.9834260365777083))); vert.add(new Vec3(new Pointing(1.1503524244193444,0.9835545050450514))); vert.add(new Vec3(new Pointing(1.1502258785647448,0.983615364692989))); vert.add(new Vec3(new Pointing(1.150040689827067,0.9836052230787131))); vert.add(new Vec3(new Pointing(1.1497289561324662,0.9836559547866632))); vert.add(new Vec3(new Pointing(1.1496348192975478,0.9836847052609023))); vert.add(new Vec3(new Pointing(1.1494727890458836,0.9838453720714817))); vert.add(new Vec3(new Pointing(1.1494049018076335,0.9839772939956009))); vert.add(new Vec3(new Pointing(1.149324740233309,0.9843798294222985))); vert.add(new Vec3(new Pointing(1.1492739766976383,0.9848178951560865))); vert.add(new Vec3(new Pointing(1.1492880620951265,0.9851916630592842))); vert.add(new Vec3(new Pointing(1.1494023951081926,0.9854012904878543))); vert.add(new Vec3(new Pointing(1.149519781095103,0.9855432489469033))); vert.add(new Vec3(new Pointing(1.1497839272856774,0.9858626006164312))); vert.add(new Vec3(new Pointing(1.1501482692615095,0.986017767907073))); vert.add(new Vec3(new Pointing(1.1506158045877952,0.9859411952965156))); vert.add(new Vec3(new Pointing(1.1510863719564317,0.9857970535978254))); vert.add(new Vec3(new Pointing(1.1514010989298469,0.9856784621213586))); vert.add(new Vec3(new Pointing(1.1517158310959092,0.9855599035665571))); vert.add(new Vec3(new Pointing(1.1520923005998371,0.9854447044733927))); vert.add(new Vec3(new Pointing(1.152556811551436,0.9854358697505938))); vert.add(new Vec3(new Pointing(1.152936329868326,0.9852531893604244))); vert.add(new Vec3(new Pointing(1.1534980080389958,0.9851480997557343))); vert.add(new Vec3(new Pointing(1.1542448858126413,0.9850530625072047))); vert.add(new Vec3(new Pointing(1.1548713566503563,0.9848839302619462))); vert.add(new Vec3(new Pointing(1.155238694559804,0.9849714230186063))); vert.add(new Vec3(new Pointing(1.155511913488695,0.9850876232716619))); vert.add(new Vec3(new Pointing(1.1556879733525678,0.9852999969140172))); vert.add(new Vec3(new Pointing(1.1559784112498703,0.9857213321874994))); vert.add(new Vec3(new Pointing(1.1559865844022958,0.9862288863472906))); vert.add(new Vec3(new Pointing(1.1560385791492556,0.9871444375227638))); vert.add(new Vec3(new Pointing(1.1560116805212006,0.9877515244318255))); vert.add(new Vec3(new Pointing(1.1558379990039347,0.9881818725706057))); vert.add(new Vec3(new Pointing(1.155543873841697,0.9885383490226638))); vert.add(new Vec3(new Pointing(1.1552557042400238,0.9887599602232404))); vert.add(new Vec3(new Pointing(1.1549352096290768,0.9890137597369755))); vert.add(new Vec3(new Pointing(1.1546147391191914,0.9892676311236104))); vert.add(new Vec3(new Pointing(1.1542354927708685,0.9894508532485825))); vert.add(new Vec3(new Pointing(1.1538621301597058,0.9894990936671686))); vert.add(new Vec3(new Pointing(1.1536181187451178,0.9894187147674598))); vert.add(new Vec3(new Pointing(1.1533447121031735,0.9893029412643478))); vert.add(new Vec3(new Pointing(1.1529537305101472,0.9890455986187472))); vert.add(new Vec3(new Pointing(1.1524980830083356,0.9888524937214215))); vert.add(new Vec3(new Pointing(1.1523481741773312,0.9887430639190622))); vert.add(new Vec3(new Pointing(1.1520629738824093,0.988897439436812))); vert.add(new Vec3(new Pointing(1.1518395192779805,0.9890550816485132))); vert.add(new Vec3(new Pointing(1.1515513932259047,0.9892771221299574))); vert.add(new Vec3(new Pointing(1.1513250228779512,0.9895024356245301))); vert.add(new Vec3(new Pointing(1.1510957407699558,0.9897953995250245))); vert.add(new Vec3(new Pointing(1.1508988210950766,0.9900562178915127))); vert.add(new Vec3(new Pointing(1.150763665085474,0.9903202764372446))); vert.add(new Vec3(new Pointing(1.1507843367123325,0.990558526439852))); vert.add(new Vec3(new Pointing(1.1507992237525468,0.9909320025905168))); vert.add(new Vec3(new Pointing(1.1508522671724446,0.9911380213792874))); vert.add(new Vec3(new Pointing(1.1509376417668262,0.9913118073666528))); vert.add(new Vec3(new Pointing(1.1510230276226834,0.9914855800960104))); vert.add(new Vec3(new Pointing(1.1511701646336845,0.9916624962872871))); vert.add(new Vec3(new Pointing(1.1513467444499845,0.9918747650352789))); vert.add(new Vec3(new Pointing(1.151493907126133,0.9920516301034698))); vert.add(new Vec3(new Pointing(1.15167051772407,0.9922638375354705))); vert.add(new Vec3(new Pointing(1.1517825427272692,0.9925404659613722))); vert.add(new Vec3(new Pointing(1.1518945962236837,0.9928170667717601))); vert.add(new Vec3(new Pointing(1.151944936626454,0.9930905238387734))); vert.add(new Vec3(new Pointing(1.1519364038488704,0.9932932756669433))); vert.add(new Vec3(new Pointing(1.1519545044629247,0.9935989574717053))); vert.add(new Vec3(new Pointing(1.1518899290891478,0.9936634411834805))); vert.add(new Vec3(new Pointing(1.1518576419864373,0.9936956844356148))); vert.add(new Vec3(new Pointing(1.1515670755926695,0.9939859156123069))); vert.add(new Vec3(new Pointing(1.1514056634584344,0.9941471877691483))); vert.add(new Vec3(new Pointing(1.151209167317511,0.9944083526588667))); vert.add(new Vec3(new Pointing(1.1510098905412778,0.9947371775119466))); vert.add(new Vec3(new Pointing(1.1509074670044037,0.9949692293531077))); vert.add(new Vec3(new Pointing(1.1507939027845748,0.9954717874109883))); vert.add(new Vec3(new Pointing(1.1507154681212395,0.9958744790360815))); vert.add(new Vec3(new Pointing(1.150728328381526,0.9963155562525036))); vert.add(new Vec3(new Pointing(1.1507145219246022,0.9966536818156724))); vert.add(new Vec3(new Pointing(1.150698010346289,0.9970594382294491))); vert.add(new Vec3(new Pointing(1.1507515235186312,0.9972653214392541))); vert.add(new Vec3(new Pointing(1.15074330622707,0.9974681979653209))); vert.add(new Vec3(new Pointing(1.150794120124925,0.9977416918927585))); vert.add(new Vec3(new Pointing(1.1508449617882088,0.9980151735411477))); vert.add(new Vec3(new Pointing(1.150810006084698,0.9981151193696918))); vert.add(new Vec3(new Pointing(1.1508045689258863,0.9982503689627922))); vert.add(new Vec3(new Pointing(1.1507669084789147,0.9984179465727627))); vert.add(new Vec3(new Pointing(1.1507882982747644,0.9986561219049502))); vert.add(new Vec3(new Pointing(1.1508097091375338,0.9988942928018621))); vert.add(new Vec3(new Pointing(1.1508955843794588,0.9990677867461779))); vert.add(new Vec3(new Pointing(1.1509814707456794,0.9992412674747779))); vert.add(new Vec3(new Pointing(1.1510968986908656,0.999450015299713))); vert.add(new Vec3(new Pointing(1.1511559609826625,0.9995205731460943))); vert.add(new Vec3(new Pointing(1.151370737557223,0.9995646668380104))); vert.add(new Vec3(new Pointing(1.1514620182432866,0.9996028778795772))); vert.add(new Vec3(new Pointing(1.1515855148424001,0.9996087523184793))); vert.add(new Vec3(new Pointing(1.1516794788958802,0.9995793575868965))); vert.add(new Vec3(new Pointing(1.15174122717978,0.9995822953104395))); vert.add(new Vec3(new Pointing(1.1518647237644064,0.9995881703312073))); vert.add(new Vec3(new Pointing(1.151894256435611,0.9996234359315822))); vert.add(new Vec3(new Pointing(1.1519855379350588,0.9996616359063851))); vert.add(new Vec3(new Pointing(1.152015071556617,0.9996968986628608))); checkPoly(vert,13,17,""); } } healpix_java-3.31/src/healpix/essentials/test/FastMathTest.java0000644000175000017500000001032111756436717023015 0ustar leoleopackage healpix.essentials.test; import junit.framework.TestCase; import java.text.DecimalFormat; import static healpix.essentials.FastMath.*; /** A class to perform correctness and speed tests for FastMath class * * @author Naoki Shibata */ public class FastMathTest extends TestCase { private static final double p0=+0.0, m0=-0.0, pinf=Double.POSITIVE_INFINITY, minf=Double.NEGATIVE_INFINITY, nan=Double.NaN; private static boolean isPlusZero(double x) { return x == 0 && Math.copySign(1, x) == 1; } private static boolean isMinusZero(double x) { return x == 0 && Math.copySign(1, x) == -1; } private static boolean cmpDenorm(double x, double y) { if (Double.isNaN(x) && Double.isNaN(y)) return true; if (x == pinf && y == pinf) return true; if (x == minf && y == minf) return true; if (!Double.isNaN(x) && !Double.isNaN(y) && !Double.isInfinite(x) && !Double.isInfinite(y)) return true; return false; } private static void ulptest (double v1, double v2, double ulp) { assertTrue ("inconsistency",Math.abs((v1-v2)/Math.ulp(v2))<=ulp); } private static void check1 (double d) { ulptest (sin(d),Math.sin(d),2.); ulptest (cos(d),Math.cos(d),2.); ulptest (atan(d),Math.atan(d),2.); } private static void check2 (double d) { ulptest (asin(d),Math.asin(d),3.); ulptest (acos(d),Math.acos(d),2.); } public void testmain() throws Exception { assertEquals("inconsistency", Math.PI,(atan2(p0, m0))); assertEquals("inconsistency",-Math.PI,(atan2(m0, m0))); assertTrue("inconsistency",isPlusZero(atan2(p0, p0))); assertTrue("inconsistency",isMinusZero(atan2(m0, p0))); assertEquals("inconsistency",3*Math.PI/4,atan2(pinf, minf)); assertEquals("inconsistency",-3*Math.PI/4,atan2(minf, minf)); assertEquals("inconsistency",Math.PI/4,atan2(pinf, pinf)); assertEquals("inconsistency",-Math.PI/4,atan2(minf, pinf)); assertTrue("inconsistency",Double.isNaN(atan2(nan,nan))); double[] a = { 100000.5, 100000, 3, 2.5, 2, 1.5, 1.0, 0.5 }; double[] b = { nan, pinf, minf }; double[] c = { nan, pinf, minf, 2, -2 }; for(int i=0;i0.0); } public void test_ringnestring()throws Exception { System.out.println("Testing identity ring2nest(nest2ring(i))==i"); Random rng = new Random(5); for (int o=0; o<=HealpixBase.order_max; ++o) { for (int m=0; m=7)||((o==0)&&(nnb>=6))); } } } public void test_query_disc_strict() throws Exception { System.out.println("Testing non-inclusive queryDisc()"); Random rng = new Random(5); for (int o=0; o<=5; ++o) { int npix=(int)HealpixProc.order2Npix(o); boolean[] map = new boolean[npix]; Vec3[] vmap = new Vec3[npix]; for (int m=0; mcosrad; assertFalse ("query_disc_strict problem",inside^map[i]); } for (int i=0; i>o)); for (int m=0; m=nv2); assertTrue("queryDisc problem 3", nv2>=nval); } } } public void testQueryPolygon() throws Exception { System.out.println("Testing queryPolygon()"); Pointing[] corner = new Pointing[4]; corner[0]=new Pointing(new Vec3(1,0.01,0.01)); corner[1]=new Pointing(new Vec3(1,1,-0.3)); corner[2]=new Pointing(new Vec3(0.01,1,0.01)); corner[3]=new Pointing(new Vec3(0.01,0.01,1)); RangeSet lrs=HealpixProc.queryPolygonNest(10,corner); assertEquals("QueryPolygon problem",lrs.nval(),1696714); lrs=HealpixProc.queryPolygonInclusiveNest(10,corner,4); assertEquals("QueryPolygon problem",lrs.nval(),1700206); lrs=HealpixProc.queryPolygonRing(10,corner); assertEquals("QueryPolygon problem",lrs.nval(),1696714); lrs=HealpixProc.queryPolygonInclusiveRing(10,corner,4); assertEquals("QueryPolygon problem",lrs.nval(),1700206); } public void testQueryPolygon2() throws Exception { System.out.println("Testing queryPolygon() empirically"); int omax=17; Random rng = new Random(5); for (int o=0; o<=omax; ++o) { int niter=Math.max(1,Math.min(nsamples/1000,100000>>o)); for (int m=0; m=nv2); assertTrue("queryPolygon problem 3", nv2>=nval); } } } public void test() throws Exception { int o=8; for (int i=0; i=a.nval()); assertTrue(a.union(b).nval()>=b.nval()); assertTrue(a.intersection(b).nval()<=a.nval()); assertTrue(a.intersection(b).nval()<=b.nval()); assertTrue(a.union(b).contains(a)); assertTrue(a.union(b).contains(b)); assertFalse(a.difference(b).overlaps(b)); assertFalse(b.difference(a).overlaps(a)); assertEquals(a.union(b).nval(),a.nval()+b.nval()-a.intersection(b).nval()); assertEquals(a.union(b).difference(a.intersection(b)).nval(), a.union(b).nval()-a.intersection(b).nval()); assertEquals(a,RangeSet.fromCompressed(a.toCompressed())); } public static void testOps() throws Exception { int niter = 100; Random rng = new Random(42); for (int iter=0; iterSLEEF * library. Some of the methods can be used as substitutions of the * corresponding methods in Math class. They have slightly less * accuracy, and some methods are faster compared to those methods in * Math class. Please note that the methods in the standard Math class * are JNI methods, and the SLEEF library is specialized for SIMD * operations. */ public final class FastMath { private static final double mulsign(double x, double y) { return Math.copySign(1, y) * x; } /** Checks if the argument is a NaN or not. */ private static final boolean isnan(double d) { return d != d; } /** Checks if the argument is either positive or negative infinity. */ private static final boolean isinf(double d) { return Math.abs(d) == Double.POSITIVE_INFINITY; } private static final double sign(double d) { return Math.copySign(1, d); } private static final double atanhelper(double s) { double t = s * s; double u = -1.88796008463073496563746e-05; u = u * t + (0.000209850076645816976906797); u = u * t + (-0.00110611831486672482563471); u = u * t + (0.00370026744188713119232403); u = u * t + (-0.00889896195887655491740809); u = u * t + (0.016599329773529201970117); u = u * t + (-0.0254517624932312641616861); u = u * t + (0.0337852580001353069993897); u = u * t + (-0.0407629191276836500001934); u = u * t + (0.0466667150077840625632675); u = u * t + (-0.0523674852303482457616113); u = u * t + (0.0587666392926673580854313); u = u * t + (-0.0666573579361080525984562); u = u * t + (0.0769219538311769618355029); u = u * t + (-0.090908995008245008229153); u = u * t + (0.111111105648261418443745); u = u * t + (-0.14285714266771329383765); u = u * t + (0.199999999996591265594148); u = u * t + (-0.333333333333311110369124); return u * t * s + s; } private static final double atan2k(double y, double x) { double q = 0.; if (x < 0) { x = -x; q = -2.; } if (y > x) { double t = x; x = y; y = -t; q += 1.; } return atanhelper(y/x) + q*(Math.PI/2); } /** This method calculates the arc tangent of y/x in radians, using the signs of the two arguments to determine the quadrant of the result. The results may have maximum error of 2 ulps. */ public static final double atan2(double y, double x) { double r = atan2k(Math.abs(y), x); r = mulsign(r, x); if (isinf(x) || x == 0) r = Math.PI/2 - (isinf(x) ? (sign(x) * (Math.PI /2)) : 0); if (isinf(y) ) r = Math.PI/2 - (isinf(x) ? (sign(x) * (Math.PI*1/4)) : 0); if ( y == 0) r = (sign(x) == -1 ? Math.PI : 0); return isnan(x) || isnan(y) ? Double.NaN : mulsign(r, y); } /** This method calculates the arc sine of x in radians. The return value is in the range [-pi/2, pi/2]. The results may have maximum error of 3 ulps. */ public static double asin(double d) { return mulsign(atan2k(Math.abs(d), Math.sqrt((1+d)*(1-d))), d); } /** This method calculates the arc cosine of x in radians. The return value is in the range [0, pi]. The results may have maximum error of 3 ulps. */ public static double acos(double d) { return mulsign(atan2k(Math.sqrt((1+d)*(1-d)), Math.abs(d)), d) + (d<0 ? Math.PI : 0); } /** Returns the arc tangent of an angle. The results may have maximum error of 2 ulps. */ public static final double atan(double s) { int q = 0; if (s < 0) { s = -s; q = 2; } if (s > 1) { s = 1.0 / s; q |= 1; } double t=atanhelper(s); if ((q & 1) != 0) t = 1.570796326794896557998982 - t; if ((q & 2) != 0) t = -t; return t; } private static final double PI4_A = .7853981554508209228515625; private static final double PI4_B = .794662735614792836713604629039764404296875e-8; private static final double PI4_C = .306161699786838294306516483068750264552437361480769e-16; private static final double M_1_PI = 0.3183098861837906715377675267450287; private final static double sincoshelper(double d) { double s = d * d; double u = -7.97255955009037868891952e-18; u = u*s +2.81009972710863200091251e-15; u = u*s -7.64712219118158833288484e-13; u = u*s +1.60590430605664501629054e-10; u = u*s -2.50521083763502045810755e-08; u = u*s +2.75573192239198747630416e-06; u = u*s -0.000198412698412696162806809; u = u*s +0.00833333333333332974823815; u = u*s -0.166666666666666657414808; return s*u*d + d; } /** Returns the trigonometric sine of an angle. The results may have maximum error of 2 ulps. */ public static final double sin(double d) { double u = d * M_1_PI; long q = (long)(u < 0 ? u - 0.5 : u + 0.5); double x=4.*q; d -= x*PI4_A; d -= x*PI4_B; d -= x*PI4_C; if ((q&1) != 0) d = -d; return sincoshelper(d); } /** Returns the trigonometric cosine of an angle. The results may have maximum error of 2 ulps. */ public static final double cos(double d) { double u = d*M_1_PI - 0.5; long q = 1+2*(long)(u < 0 ? u - 0.5 : u + 0.5); double x=2.*q; d -= x*PI4_A; d -= x*PI4_B; d -= x*PI4_C; if ((q&2) == 0) d = -d; return sincoshelper(d); } } healpix_java-3.31/src/healpix/essentials/Zphi.java0000644000175000017500000000453512127025574020377 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; /** Class for storing a position on the unit sphere as a (z,phi)-tuple. @copyright (C) 2011 Max-Planck-Society @author Martin Reinecke */ public final class Zphi { /** Cosine of the colatitude, or z component of unit vector; Range [-1;1]. */ public double z; /** Longitude in radians; Range [0; 2Pi]. */ public double phi; /** Default constructor */ public Zphi() {} /** Creation from individual components */ public Zphi (double z_, double phi_) { z=z_; phi=phi_; } /** Conversion from {@link Vec3} */ public Zphi (Vec3 v) { z = v.z/v.length(); phi = FastMath.atan2(v.y,v.x); } /** Conversion from {@link Pointing} */ public Zphi (Pointing ptg) { z = FastMath.cos(ptg.theta); phi=ptg.phi; } public String toString() { StringBuilder s = new StringBuilder(); s.append("zphi(");s.append(z); s.append(",");s.append(phi); s.append(")"); return s.toString(); } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Zphi zphi = (Zphi) o; if (Double.compare(zphi.phi, phi) != 0) return false; if (Double.compare(zphi.z, z) != 0) return false; return true; } public int hashCode() { long temp = z != +0.0d ? Double.doubleToLongBits(z) : 0L; int result = (int) (temp ^ (temp >>> 32)); temp = phi != +0.0d ? Double.doubleToLongBits(phi) : 0L; result = 31 * result + (int) (temp ^ (temp >>> 32)); return result; } } healpix_java-3.31/src/healpix/essentials/Hploc.java0000644000175000017500000000413312127025574020524 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; /** Healpix-internal class for specifying locations on the sphere. @copyright 2011 Max-Planck-Society @author Martin Reinecke */ final class Hploc { public double z, phi, sth; public boolean have_sth; /** Default constructor. */ public Hploc() {} public Hploc (Vec3 v) { double xl = 1./v.length(); z = v.z*xl; phi = FastMath.atan2(v.y,v.x); if (Math.abs(z)>0.99) { sth = Math.sqrt(v.x*v.x+v.y*v.y)*xl; have_sth=true; } } public Hploc (Zphi zphi) { z = zphi.z; phi = zphi.phi; have_sth=false; } public Hploc (Pointing ptg) throws Exception { HealpixUtils.check((ptg.theta>=0.)&&(ptg.theta<=Math.PI), "invalid theta value"); z = FastMath.cos(ptg.theta); phi = ptg.phi; if (Math.abs(z)>0.99) { sth = FastMath.sin(ptg.theta); have_sth=true; } } public Zphi toZphi() { return new Zphi(z,phi); } public Pointing toPointing() { double st = have_sth ? sth : Math.sqrt((1.0-z)*(1.0+z)); return new Pointing(FastMath.atan2(st,z),phi); } public Vec3 toVec3() { double st = have_sth ? sth : Math.sqrt((1.0-z)*(1.0+z)); return new Vec3(st*FastMath.cos(phi),st*FastMath.sin(phi),z); } } healpix_java-3.31/src/healpix/essentials/RangeSet.java0000644000175000017500000004104012506765003021164 0ustar leoleo/* * This file is part of Healpix Java. * * This code 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 2 of the License, or * (at your option) any later version. * * This code 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 code; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information about HEALPix, see http://healpix.sourceforge.net */ package healpix.essentials; import java.util.NoSuchElementException; /** Class for dealing with sets of integer ranges. Ranges are described by the first element and the one-past-last element. This code was inspired by Jan Kotek's "LongRangeSet" class, but has been completely reimplemented. @copyright 2011-2015 Max-Planck-Society @author Martin Reinecke */ public class RangeSet { /** Interface describing an iterator for going through all values in a RangeSet object. */ public interface ValueIterator { public boolean hasNext(); public long next(); } private static final ValueIterator EMPTY_ITER = new ValueIterator() { public boolean hasNext() { return false; } public long next() { throw new NoSuchElementException(); } }; /** Sorted list of interval boundaries. */ protected long[] r; /** Current number of active entries. */ protected int sz; /** Construct new object with initial space for 4 ranges. */ public RangeSet() { this(4); } /** Construct new object with initial capacity for a given number of ranges. @param cap number of initially reserved ranges. */ public RangeSet(int cap) { if (cap<0) throw new IllegalArgumentException("capacity must be positive"); r = new long[cap<<1]; sz=0; } /** Construct new object from an array of longs. @param data */ public RangeSet(long[] data) { sz=data.length; r = new long[sz]; System.arraycopy(data,0,r,0,sz); checkConsistency(); } /** Construct new object from another RangeSet @param other */ public RangeSet(RangeSet other) { sz=other.sz; r = new long[sz]; System.arraycopy(other.r,0,r,0,sz); } /** Checks the object for internal consistency. If a problem is detected, an IllegalArgumentException is thrown. */ public void checkConsistency() { if ((sz&1)!=0) throw new IllegalArgumentException("invalid number of entries"); for (int i=1; i=sz) resize(sz); } /** Returns an internal representation of the interval a number belongs to. @param val number whose interval is requested @return interval number, starting with -1 (smaller than all numbers in the RangeSet), 0 (first "on" interval), 1 (first "off" interval etc.), up to (and including) sz-1 (larger than all numbers in the RangeSet). */ private int iiv (long val) { int count=sz, first=0; while (count>0) { int step=count>>>1, it = first+step; if (r[it]<=val) { first=++it; count-=step+1; } else count=step; } return first-1; } /** Append a single-value range to the object. @param val value to append */ public void append(long val) { append(val,val+1); } /** Append a range to the object. @param a first long in range @param b one-after-last long in range */ public void append (long a, long b) { if (a>=b) return; if ((sz>0) && (a<=r[sz-1])) { if (ar[sz-1]) r[sz-1]=b; return; } ensureCapacity(sz+2); r[sz] = a; r[sz+1] = b; sz+=2; } /** Append an entire range set to the object. */ public void append (RangeSet other) { for (int i=0; i>>1; } /** @return true if no entries are stored, else false. */ public boolean isEmpty() { return sz==0; } /** @return first number in range iv. */ public long ivbegin(int iv) { return r[2*iv]; } /** @return one-past-last number in range iv. */ public long ivend(int iv) { return r[2*iv+1]; } /** Remove all entries in the set. */ public void clear() { sz=0; } /** Push a single entry at the end of the entry vector. */ private void pushv(long v) { ensureCapacity(sz+1); r[sz++]=v; } /** Estimate a good strategy for set operations involving two RangeSets. */ private static int strategy (int sza, int szb) { final double fct1 = 1.; final double fct2 = 1.; int slo = szaa.r[a.sz-1])) return false; } else { int ivb=b.iiv(a.r[iva]); if ((ivb!=b.sz-1)&&(b.r[ivb+1]-1) && (!state_b)) res.pushv(a.r[iva]); while((ivb=0) && (r[pos1]==a)) --pos1; // first to delete is at pos1+1; last is at pos2 boolean insert_a = (pos1&1)==v; boolean insert_b = (pos2&1)==v; int rmstart=pos1+1+(insert_a ? 1 : 0); int rmend =pos2-(insert_b?1:0); if (((rmend-rmstart)&1)==0) throw new IllegalArgumentException("cannot happen: "+rmstart+" "+rmend); if (insert_a && insert_b && (pos1+1>pos2)) // insert { ensureCapacity(sz+2); System.arraycopy(r,pos1+1,r,pos1+3,sz-pos1-1); // move to right r[pos1+1]=a; r[pos1+2]=b; sz+=2; } else { if (insert_a) r[pos1+1]=a; if (insert_b) r[pos2]=b; if (rmstart!=rmend+1) System.arraycopy(r,rmend+1,r,rmstart,sz-rmend-1); // move to left sz-=rmend-rmstart+1; } } /** After this operation, the RangeSet contains the intersection of itself and [a;b[. */ public void intersect (long a, long b) { int pos1=iiv(a), pos2=iiv(b); if ((pos2>=0) && (r[pos2]==b)) --pos2; // delete all up to pos1 (inclusive); and starting from pos2+1 boolean insert_a = (pos1&1)==0; boolean insert_b = (pos2&1)==0; // cut off end sz=pos2+1; if (insert_b) r[sz++]=b; // erase start if (insert_a) r[pos1--]=a; if (pos1>=0) System.arraycopy(r,pos1+1,r,0,sz-pos1-1); // move to left sz-=pos1+1; if ((sz&1)!=0) throw new IllegalArgumentException("cannot happen"); } /** After this operation, the RangeSet contains the union of itself and [a;b[. */ public void add (long a, long b) { if ((sz==0)||(a>=r[sz-1])) append(a,b); else addRemove(a,b,1); } /** After this operation, the RangeSet contains the union of itself and [a;a+1[. */ public void add (long a) { if ((sz==0)||(a>=r[sz-1])) append(a,a+1); else addRemove(a,a+1,1); } /** After this operation, the RangeSet contains the difference of itself and [a;b[. */ public void remove (long a, long b) { addRemove(a,b,0); } /** After this operation, the RangeSet contains the difference of itself and [a;a+1[. */ public void remove (long a) { addRemove(a,a+1,0); } /** Creates an array containing all the numbers in the RangeSet. Not recommended, because the arrays can become prohibitively large. It is preferrable to use a ValueIterator or explicit loops. */ public long[] toArray(){ long[] res = new long[(int)nval()]; int ofs=0; for (int i=0; i0) ? r[0] : 0; public boolean hasNext() { return (possz) throw new NoSuchElementException(); long ret = value; if (++value==r[pos+1]) { pos+=2; if (pos>> 8)&0xff])<<16) | ((long)(utab[(v>>>16)&0xff])<<32) | ((long)(utab[(v>>>24)&0xff])<<48); } private static int compress_bits (long v) { long raw = v&0x5555555555555555L; raw |= raw>>>15; int raw1 = (int)(raw&0xffffL), raw2 = (int)((raw>>>32)&0xffffL); return ctab[raw1&0xff] | (ctab[raw1>>>8]<< 4) | (ctab[raw2&0xff]<<16) | (ctab[raw2>>>8]<<20); } private Xyf nest2xyf(long ipix) { long pix=ipix&(npface-1); return new Xyf (compress_bits(pix), compress_bits(pix>>>1), (int)(ipix>>>(2*order))); } private long xyf2nest(int ix, int iy, int face_num) { return ((long)(face_num)<<(2*order)) + spread_bits(ix) + (spread_bits(iy)<<1); } private long xyf2ring(int ix, int iy, int face_num) { long jr = ((long)jrll[face_num]*nside) - (long)ix - (long)iy - 1L; RingInfoSmall ris = get_ring_info_small(jr); long nr=ris.ringpix>>>2, kshift=ris.shifted ? 0:1; long jp = (jpll[face_num]*nr + (long)ix - (long)iy + 1L + kshift) / 2L; if (jp>nl4) jp-=nl4; else if (jp<1) jp+=nl4; return ris.startpix + jp - 1L; } protected Xyf ring2xyf(long pix) { Xyf ret = new Xyf(); long iring, iphi, kshift, nr; if (pix>>1; //counted from North pole iphi = (pix+1) - 2*iring*(iring-1); kshift = 0; nr = iring; ret.face=(int)((iphi-1)/nr); } else if (pix<(npix-ncap)) // Equatorial region { long ip = pix - ncap; long tmp = (order>=0) ? ip>>>(order+2) : ip/nl4; iring = tmp+nside; iphi = ip-tmp*nl4 + 1; kshift = (iring+nside)&1; nr = nside; long ire = iring-nside+1, irm = nl2+2-ire; long ifm = iphi - (ire>>>1) + nside -1, ifp = iphi - (irm>>>1) + nside -1; if (order>=0) { ifm >>>= order; ifp >>>= order; } else { ifm /= nside; ifp /= nside; } ret.face = (int)((ifp==ifm) ? (ifp|4) : ((ifp>>1; //counted from South pole iphi = 4L*iring + 1 - (ip - 2L*iring*(iring-1L)); kshift = 0; nr = iring; iring = 2L*nl2-iring; ret.face = 8 + (int)((iphi-1)/nr); } long irt = iring - ((long)jrll[ret.face]*nside) + 1L; long ipt = 2L*iphi- (long)jpll[ret.face]*nr - kshift -1L; if (ipt>=nl2) ipt-=8L*nside; ret.ix = (int)(( ipt-irt)>>>1); ret.iy = (int)((-ipt-irt)>>>1); return ret; } protected Xyf pix2xyf (long pix) { return (scheme==Scheme.RING) ? ring2xyf(pix) : nest2xyf(pix); } protected long xyf2pix (int ix, int iy, int face_num) { return (scheme==Scheme.RING) ? xyf2ring(ix,iy,face_num) : xyf2nest(ix,iy,face_num); } protected long xyf2pix (Xyf xyf) { return (scheme==Scheme.RING) ? xyf2ring(xyf.ix,xyf.iy,xyf.face) : xyf2nest(xyf.ix,xyf.iy,xyf.face); } /** Calculates the map order from its Nside parameter. @param nside the Nside parameter @return the map order corresponding to {@code nside}; -1 if {@code nside} is not a power of 2. */ public static int nside2order(long nside) throws Exception { HealpixUtils.check (nside>0,"nside must be positive"); return ((nside&(nside-1))!=0) ? -1 : HealpixUtils.ilog2(nside); } /** Calculates the Nside parameter from the number of pixels. @param npix the number of pixels @return the computed Nside parameter */ public static long npix2Nside(long npix) throws Exception { HealpixUtils.check (npix>0,"npix must be positive"); long nside = HealpixUtils.isqrt(npix/12); HealpixUtils.check(12*nside*nside==npix,"npix is not 12*nside*nside"); HealpixUtils.check(nside<=ns_max,"nside is too large"); return nside; } /** Calculates the number of pixels from the Nside parameter. @param nside the Nside parameter @return the computed number of pixels */ public static long nside2Npix(long nside) throws Exception { HealpixUtils.check (nside>0,"nside must be positive"); HealpixUtils.check(nside<=ns_max,"nside is too large"); return 12*nside*nside; } /** Calculates the number of pixels from the order parameter. @param order the order parameter @return the computed number of pixels */ public static long order2Npix(int order) throws Exception { HealpixUtils.check (order>=0,"order must be nonnegative"); HealpixUtils.check(order<=order_max,"order is too large"); return 12*(1L<<(2*order)); } /** Adjusts the object to nside_in. @param nside_in the new Nside parameter */ public void setNside (long nside_in) throws Exception { if (nside==nside_in) return; nside=nside_in; HealpixUtils.check(nside<=ns_max && nside>0, "Nside must be between 1 and " + ns_max); order = nside2order(nside); if (scheme==Scheme.NESTED && order<0) throw new Exception("Nside must be a power of 2 for NESTED scheme"); nl2 = 2*nside; nl3 = 3*nside; nl4 = 4*nside; npface = nside*nside; ncap = 2*nside*(nside-1); // pixels in each polar cap npix = 12*npface; fact2 = 4.0/npix; fact1 = (nside<<1)*fact2; } /** Adjusts the object to nside_in and scheme_in. @param nside_in the new Nside parameter @param scheme_in the new ordering scheme */ public void setNsideAndScheme (long nside_in, Scheme scheme_in) throws Exception { if ((scheme==scheme_in) && (nside==nside_in)) return; HealpixUtils.check (((nside_in&(nside_in-1))==0)||(scheme_in==Scheme.RING), "Nside must be a power of 2 for NESTED scheme"); scheme=scheme_in; setNside(nside_in); } /** Initializes the object to Nside=1 and scheme=NESTED. */ public HealpixBase() { try { nside=0; setNsideAndScheme(1,Scheme.NESTED); } catch(Exception Ex) {/*cannot happen*/} } /** Initializes the object to a user-supplied Nside and ordering scheme. @param nside_in the Nside parameter @param scheme_in the ordering scheme */ public HealpixBase(long nside_in, Scheme scheme_in) throws Exception { nside=nside_in-1; setNsideAndScheme(nside_in, scheme_in); } /** Returns the current ordering scheme. @return the current ordering scheme */ public Scheme getScheme() { return scheme; } /** Returns the current Nside parameter. @return the current Nside parameter */ public int getNside() { return (int)nside; } /** Returns the total number of pixels in the pixelisation. @return the current total number of pixels */ public long getNpix() { return npix; } /** Adjusts the object to scheme. @param scheme_in the new ordering scheme */ public void setScheme(Scheme scheme_in) throws Exception { if (scheme_in==Scheme.NESTED && order<0) throw new Exception("Nside must be a power of 2 for NESTED scheme"); scheme = scheme_in; } /** Returns the current order parameter. @return the current map order parameter. */ public int getOrder() { return order; } /** Returns the pixel which contains the supplied Pointing. @param ptg the requested location on the sphere. @return the pixel number containing the location. */ public long ang2pix(Pointing ptg) throws Exception { return loc2pix(new Hploc(ptg)); } /** Returns the Pointing corresponding to the center of the supplied pixel. @param pix the requested pixel number. @return the pixel's center coordinates. */ public Pointing pix2ang(long pix) throws Exception { return pix2loc(pix).toPointing(); } /** Returns the pixel which contains the supplied Vec3. @param vec the requested location on the sphere (need not be normalized). @return the pixel number containing the location. */ public long vec2pix(Vec3 vec) throws Exception { return loc2pix(new Hploc(vec)); } /** Returns the normalized 3-vector corresponding to the center of the supplied pixel. @param pix the requested pixel number. @return the pixel's center coordinates. */ public Vec3 pix2vec(long pix) throws Exception { return pix2loc(pix).toVec3(); } /** Returns nested pixel number for the supplied ring pixel number. @param ipring the requested pixel number in RING scheme. @return the corresponding pixel number in NESTED scheme. */ public long ring2nest(long ipring) throws Exception { Xyf xyf = ring2xyf(ipring); return xyf2nest (xyf.ix,xyf.iy, xyf.face); } /** Returns ring pixel number for the supplied nested pixel number. @param ipnest the requested pixel number in NESTED scheme. @return the corresponding pixel number in RING scheme. */ public long nest2ring(long ipnest) throws Exception { Xyf xyf = nest2xyf(ipnest); return xyf2ring (xyf.ix,xyf.iy, xyf.face); } protected long loc2pix (Hploc loc) { double z=loc.z, phi=loc.phi; double za = Math.abs(z); double tt = HealpixUtils.fmodulo((phi*Constants.inv_halfpi),4.0);// in [0,4) if (scheme==Scheme.RING) { if (za<=Constants.twothird) // Equatorial region { double temp1 = nside*(0.5+tt); double temp2 = nside*z*0.75; long jp = (long)(temp1-temp2); // index of ascending edge line long jm = (long)(temp1+temp2); // index of descending edge line // ring number counted from z=2/3 long ir = nside + 1 + jp - jm; // in {1,2n+1} long kshift = 1-(ir&1); // kshift=1 if ir even, 0 otherwise long t1 = jp+jm-nside+kshift+1+nl4+nl4; long ip = (order>0) ? (t1>>>1)&(nl4-1) : ((t1>>>1)%nl4); // in {0,4n-1} return ncap + (ir-1)*nl4 + ip; } else // North & South polar caps { double tp = tt-(long)(tt); double tmp = ((za<0.99)||(!loc.have_sth)) ? nside*Math.sqrt(3*(1-za)) : nside*loc.sth/Math.sqrt((1.+za)/3.); long jp = (long)(tp*tmp); // increasing edge line index long jm = (long)((1.0-tp)*tmp); // decreasing edge line index long ir = jp+jm+1; // ring number counted from the closest pole long ip = (long)(tt*ir); // in {0,4*ir-1} assert((ip>=0)&&(ip<4*ir)); return (z>0) ? 2*ir*(ir-1) + ip : npix - 2*ir*(ir+1) + ip; } } else // scheme_ == NEST { if (za<=Constants.twothird) // Equatorial region { double temp1 = nside*(0.5+tt); double temp2 = nside*(z*0.75); long jp = (long)(temp1-temp2); // index of ascending edge line long jm = (long)(temp1+temp2); // index of descending edge line long ifp = jp >>> order; // in {0,4} long ifm = jm >>> order; long face_num = (ifp==ifm) ? (ifp|4) : ((ifp 2/3 { int ntt = Math.min(3,(int)tt); double tp = tt-ntt; double tmp = ((za<0.99)||(!loc.have_sth)) ? nside*Math.sqrt(3*(1-za)) : nside*loc.sth/Math.sqrt((1.+za)/3.); long jp = (long)(tp*tmp); // increasing edge line index long jm = (long)((1.0-tp)*tmp); // decreasing edge line index if (jp>=nside) jp = nside-1; // for points too close to the boundary if (jm>=nside) jm = nside-1; return (z>=0) ? xyf2nest((int)(nside-jm -1),(int)(nside-jp-1),ntt) : xyf2nest((int)jp,(int)jm,ntt+8); } } } /** Returns the pixel which contains the supplied Zphi. @param zphi the requested location on the sphere. @return the pixel number containing the location. */ public long zphi2pix (Zphi zphi) { return loc2pix (new Hploc(zphi)); } protected Hploc pix2loc (long pix) { Hploc loc = new Hploc(); if (scheme==Scheme.RING) { if (pix>>1; //from North pole long iphi = (pix+1) - 2*iring*(iring-1); double tmp = (iring*iring)*fact2; loc.z = 1.0 - tmp; if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; } loc.phi = (iphi-0.5) * Constants.halfpi/iring; } else if (pix<(npix-ncap)) // Equatorial region { long ip = pix - ncap; long tmp = (order>=0) ? ip>>>(order+2) : ip/nl4; long iring = tmp + nside, iphi = ip-nl4*tmp+1;; // 1 if iring+nside is odd, 1/2 otherwise double fodd = ((iring+nside)&1)!=0 ? 1 : 0.5; loc.z = (nl2-iring)*fact1; loc.phi = (iphi-fodd) * Math.PI*0.75*fact1; } else // South Polar cap { long ip = npix - pix; long iring = (1+HealpixUtils.isqrt(2*ip-1))>>>1; //from South pole long iphi = 4*iring + 1 - (ip - 2*iring*(iring-1)); double tmp = (iring*iring)*fact2; loc.z = tmp-1.0; if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; } loc.phi = (iphi-0.5) * Constants.halfpi/iring; } } else { Xyf xyf= nest2xyf(pix); long jr = ((long)(jrll[xyf.face])<0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; } } else if (jr>nl3) { nr = nl4-jr; double tmp = (nr*nr)*fact2; loc.z = tmp - 1; if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; } } else { nr = nside; loc.z = (nl2-jr)*fact1; } long tmp=(long)(jpll[xyf.face])*nr+xyf.ix-xyf.iy; assert(tmp<8*nr); // must not happen if (tmp<0) tmp+=8*nr; loc.phi = (nr==nside) ? 0.75*Constants.halfpi*tmp*fact1 : (0.5*Constants.halfpi*tmp)/nr; } return loc; } /** Returns the Zphi corresponding to the center of the supplied pixel. @param pix the requested pixel number. @return the pixel's center coordinates. */ public Zphi pix2zphi (long pix) { return pix2loc(pix).toZphi(); } /** Returns the neighboring pixels of ipix. This method works in both RING and NEST schemes, but is considerably faster in the NEST scheme. @param ipix the requested pixel number. @return array with indices of the neighboring pixels. The returned array contains (in this order) the pixel numbers of the SW, W, NW, N, NE, E, SE and S neighbor of ipix. If a neighbor does not exist (this can only happen for the W, N, E and S neighbors), its entry is set to -1. */ public long[] neighbours(long ipix) throws Exception { long[] result = new long[8]; Xyf xyf = (scheme==Scheme.NESTED) ? nest2xyf(ipix) : ring2xyf(ipix); int ix = xyf.ix, iy=xyf.iy, face_num=xyf.face; long nsm1 = nside-1; if ((ix>0)&&(ix0)&&(iy=nside) { x-=nside; nbnum+=1; } if (y<0) { y+=nside; nbnum-=3; } else if (y>=nside) { y-=nside; nbnum+=3; } int f = facearray[nbnum][face_num]; if (f>=0) { int bits = swaparray[nbnum][face_num>>>2]; if ((bits&1)>0) x=(int)(nside-x-1); if ((bits&2)>0) y=(int)(nside-y-1); if ((bits&4)>0) { int tint=x; x=y; y=tint; } result[i] = (scheme==Scheme.NESTED) ? xyf2nest(x,y,f) : xyf2ring(x,y,f); } else result[i]=-1; } } return result; } /** Returns the maximum angular distance between a pixel center and its corners. @return maximum angular distance between a pixel center and its corners. */ public double maxPixrad() { Vec3 va = new Vec3(new Zphi(2./3., Math.PI/nl4)); double t1 = 1.-1./nside; t1*=t1; Vec3 vb = new Vec3(new Zphi(1-t1/3, 0)); return va.angle(vb); } private RingInfoSmall get_ring_info_small (long ring) { RingInfoSmall ret = new RingInfoSmall(); if (ring Constants.twothird) // polar caps { long iring = (long)(nside*Math.sqrt(3*(1-az))); return (z>0) ? iring : nl4-iring-1; } else // equatorial region return (long)(nside*(2.0-1.5*z)); } /** Returns the z-coordinate (equivalent to the cosine of the colatitude) for the requested ring. This method also accepts the not-really-existing ring indices 0 and 4*Nside, which correspond to North and South Poles, respectively. @param ring ring index: the northernmost ring in the map has index 1; ring indices are increasing towards the South pole. @return z-coordinate of the ring. */ public double ring2z (long ring) { if (ring The latitude range is defined as follows:
  • if {@code theta1
  • otherwise it is the range between 0 and {@code theta2}, and between {@code theta1} and pi.
This method currently only works in the RING scheme. */ public RangeSet queryStrip(double theta1, double theta2, boolean inclusive) throws Exception { if (theta1=nr) pix-=nr; if (pix<0) pix+=nr; pix+=ipix1; if (pix==cpix) return false; // disk center in pixel => overlap Xyf xyf=pix2xyf(pix); for (int i=0; icosrp2) return false; // overlap xyf2.ix=ox+fct-1; xyf2.iy=oy+i; if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2) return false; // overlap xyf2.ix=ox+fct-1-i; xyf2.iy=oy+fct-1; if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2) return false; // overlap xyf2.ix=ox; xyf2.iy=oy+fct-1-i; if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2) return false; // overlap } return true; } private RangeSet queryDiscInternal(Pointing ptg, double radius, int fact) throws Exception { boolean inclusive=(fact!=0); RangeSet pixset = new RangeSet(); if (scheme==Scheme.RING) { int fct=1; if (inclusive) { HealpixUtils.check ((1L<=fact, "invalid oversampling factor"); fct = fact; } HealpixBase b2=null; double rsmall,rbig; if (fct>1) { b2=new HealpixBase(fct*nside,Scheme.RING); rsmall = radius+b2.maxPixrad(); rbig = radius+maxPixrad(); } else rsmall = rbig = inclusive ? radius+maxPixrad() : radius; if (rsmall>=Math.PI) { pixset.append(0,npix); return pixset; } rbig = Math.min (Math.PI,rbig); double cosrsmall = FastMath.cos(rsmall); double cosrbig = FastMath.cos(rbig); double z0 = FastMath.cos(ptg.theta); double xa = 1./Math.sqrt((1-z0)*(1+z0)); Zphi czphi = new Zphi(z0,ptg.phi); long cpix = zphi2pix(czphi); double rlat1 = ptg.theta - rsmall; double zmax = FastMath.cos(rlat1); long irmin = ringAbove (zmax)+1; if ((rlat1<=0) && (irmin>1)) // north pole in the disk { RingInfoSmall info =get_ring_info_small(irmin-1); pixset.append(0,info.startpix+info.ringpix); } if ((fct>1) && (rlat1>0)) irmin=Math.max(1L,irmin-1); double rlat2 = ptg.theta + rsmall; double zmin = FastMath.cos(rlat2); long irmax = ringAbove (zmin); if ((fct>1) && (rlat20) { RingInfoSmall info =get_ring_info_small(iz); long ipix1 = info.startpix, nr=info.ringpix, ipix2=ipix1+nr-1; double shift = info.shifted ? 0.5 : 0.; long ip_lo = (long)Math.floor (nr*Constants.inv_twopi*(ptg.phi-dphi) - shift)+1; long ip_hi = (long)Math.floor (nr*Constants.inv_twopi*(ptg.phi+dphi) - shift); if (fct>1) { while ((ip_lo<=ip_hi) && checkPixelRing (b2,ip_lo,nr,ipix1,fct,czphi,cosrsmall,cpix)) ++ip_lo; while ((ip_hi>ip_lo) && checkPixelRing (b2,ip_hi,nr,ipix1,fct,czphi,cosrsmall,cpix)) --ip_hi; } if (ip_lo<=ip_hi) { if (ip_hi>=nr) { ip_lo-=nr; ip_hi-=nr; } if (ip_lo<0) { pixset.append(ipix1,ipix1+ip_hi+1); pixset.append(ipix1+ip_lo+nr,ipix2+1); } else pixset.append(ipix1+ip_lo,ipix1+ip_hi+1); } } } if ((rlat2>=Math.PI) && (irmax+1=Math.PI) // disk covers the whole sphere { pixset.append(0,npix); return pixset; } int oplus=0; if (inclusive) { HealpixUtils.check ((1L<=fact,"invalid oversampling factor"); HealpixUtils.check ((fact&(fact-1))==0, "oversampling factor must be a power of 2"); oplus=HealpixUtils.ilog2(fact); } int omax=Math.min(order_max,order+oplus); // the order up to which we test Vec3 vptg = new Vec3(ptg); double[] crpdr = new double[omax+1]; double[] crmdr = new double[omax+1]; double cosrad=FastMath.cos(radius), sinrad=FastMath.sin(radius); for (int o=0; o<=omax; o++) // prepare data at the required orders { double dr = HealpixProc.mpr[o]; // safety distance double cdr = HealpixProc.cmpr[o]; double sdr = HealpixProc.smpr[o]; crpdr[o] = (radius+dr>Math.PI) ? -1. : cosrad*cdr-sinrad*sdr; crmdr[o] = (radius-dr<0.) ? 1. : cosrad*cdr+sinrad*sdr; } pstack stk=new pstack(12+3*omax); /* Still experimental, therefore disabled Fxyf fxyf=new Fxyf(vptg); for (int o=order; o>=0; --o) { long nsd=HealpixProc.bn[o].nside; double fx=nsd*fxyf.fx-(int)(nsd*fxyf.fx), fy=nsd*fxyf.fy-(int)(nsd*fxyf.fy); double fmin = Math.min(Math.min(fx,fy),Math.min(1-fx,1-fy)); if (fmin*0.7>nsd*radius) { System.out.println("contained completely at order "+o); stk.push(HealpixProc.bn[o].vec2pix(vptg),o); break; } } if (stk.size()==0) */ for (int i=0; i<12; i++) // insert the 12 base pixels in reverse order stk.push(11-i,0); while (stk.size()>0) {// as long as there are pixels on the stack // pop current pixel number and order from the stack long pix=stk.ptop(); int o=stk.otop(); stk.pop(); Zphi pos=HealpixProc.bn[o].pix2zphi(pix); // cosine of angular distance between pixel center and disk center double cangdist=HealpixUtils.cosdist_zphi(vptg.z,ptg.phi,pos.z,pos.phi); if (cangdist>crpdr[o]) { int zone = (cangdist This method is more efficient in the RING scheme. @param ptg the angular coordinates of the disk center @param radius the radius (in radians) of the disk @return the requested set of pixel number ranges */ public RangeSet queryDisc(Pointing ptg, double radius) throws Exception { return queryDiscInternal (ptg, radius, 0); } /** Returns a range set of pixels which overlap with a given disk.

This method is more efficient in the RING scheme.

This method may return some pixels which don't overlap with the polygon at all. The higher {@code fact} is chosen, the fewer false positives are returned, at the cost of increased run time. @param ptg the angular coordinates of the disk center @param radius the radius (in radians) of the disk @param fact The overlapping test will be done at the resolution {@code fact*nside}. For NESTED ordering, {@code fact} must be a power of 2, else it can be any positive integer. A typical choice would be 4. @return the requested set of pixel number ranges */ public RangeSet queryDiscInclusive (Pointing ptg, double radius, int fact) throws Exception { return queryDiscInternal (ptg, radius, fact); } private RangeSet queryMultiDisc (Vec3[] norm, double[] rad, int fact) throws Exception { boolean inclusive = (fact!=0); int nv=norm.length; HealpixUtils.check(nv==rad.length,"inconsistent input arrays"); RangeSet res = new RangeSet(); if (scheme==Scheme.RING) { int fct=1; if (inclusive) { HealpixUtils.check (((1L<=fact, "invalid oversampling factor"); fct = fact; } HealpixBase b2=null; double rpsmall,rpbig; if (fct>1) { b2=new HealpixBase(fct*nside,Scheme.RING); rpsmall = b2.maxPixrad(); rpbig = maxPixrad(); } else rpsmall = rpbig = inclusive ? maxPixrad() : 0; long irmin=1, irmax=nl4-1; int nd=0; double[] z0=new double[nv]; double[] xa=new double[nv]; double[] cosrsmall=new double[nv]; double[] cosrbig=new double[nv]; Pointing[] ptg=new Pointing[nv]; long[] cpix=new long[nv]; Zphi[] czphi=new Zphi[nv]; for (int i=0; i1) cpix[nd]=zphi2pix(new Zphi(cth,pnt.phi)); if (fct>1) czphi[nd]=new Zphi(cth,pnt.phi); xa[nd]=1./Math.sqrt((1-cth)*(1+cth)); ptg[nd]=pnt; double rlat1 = pnt.theta - rsmall; double zmax = FastMath.cos(rlat1); long irmin_t = (rlat1<=0) ? 1 : ringAbove (zmax)+1; if ((fct>1) && (rlat1>0)) irmin_t=Math.max(1L,irmin_t-1); double rlat2 = pnt.theta + rsmall; double zmin = FastMath.cos(rlat2); long irmax_t = (rlat2>=Math.PI) ? nl4-1 : ringAbove (zmin); if ((fct>1) && (rlat2 irmin) irmin=irmin_t; ++nd; } } for (long iz=irmin; iz<=irmax; ++iz) { double z=ring2z(iz); RingInfoSmall ris=get_ring_info_small(iz); long ipix1=ris.startpix, nr=ris.ringpix; long ipix2 = ipix1 + nr - 1; // highest pixel number in the ring double shift = ris.shifted ? 0.5 : 0.; RangeSet rstmp = new RangeSet(); rstmp.append(ipix1,ipix2+1); for (int j=0; (j0); ++j) { double x = (cosrbig[j]-z*z0[j])*xa[j]; double ysq = 1.-z*z-x*x; double dphi = (ysq<=0) ? Math.PI-1e-15 : FastMath.atan2(Math.sqrt(ysq),x); long ip_lo = (long)Math.floor (nr*Constants.inv_twopi*(ptg[j].phi-dphi)-shift)+1; long ip_hi = (long)Math.floor (nr*Constants.inv_twopi*(ptg[j].phi+dphi)-shift); if (fct>1) { while ((ip_lo<=ip_hi) && checkPixelRing (b2,ip_lo,nr,ipix1,fct,czphi[j],cosrsmall[j],cpix[j])) ++ip_lo; while ((ip_hi>ip_lo) && checkPixelRing (b2,ip_hi,nr,ipix1,fct,czphi[j],cosrsmall[j],cpix[j])) --ip_hi; } if (ip_hi>=nr) { ip_lo-=nr; ip_hi-=nr;} if (ip_lo<0) { if (ip_hi+1<=ip_lo+nr-1) rstmp.remove(ipix1+ip_hi+1,ipix1+ip_lo+nr); } else rstmp.intersect(ipix1+ip_lo,ipix1+ip_hi+1); } res.append(rstmp); } } else // scheme == NEST { int oplus = 0; if (inclusive) { HealpixUtils.check ((1L<<(order_max-order))>=fact, "invalid oversampling factor"); HealpixUtils.check ((fact&(fact-1))==0, "oversampling factor must be a power of 2"); oplus=HealpixUtils.ilog2(fact); } int omax=order+oplus; // the order up to which we test // TODO: ignore all disks with radius>=pi double[][][] crlimit=new double[omax+1][nv][3]; for (int o=0; o<=omax; ++o) // prepare data at the required orders { double dr=HealpixProc.bn[o].maxPixrad(); // safety distance for (int i=0; iMath.PI) ? -1: FastMath.cos(rad[i]+dr); crlimit[o][i][1] = (o==0) ? FastMath.cos(rad[i]) : crlimit[0][i][1]; crlimit[o][i][2] = (rad[i]-dr<0.) ? 1. : FastMath.cos(rad[i]-dr); } } pstack stk=new pstack(12+3*omax); for (int i=0; i<12; i++) // insert the 12 base pixels in reverse order stk.push(11-i,0); while (stk.size()>0) { // as long as there are pixels on the stack // pop current pixel number and order from the stack long pix=stk.ptop(); int o=stk.otop(); stk.pop(); Vec3 pv = HealpixProc.bn[o].pix2vec(pix); int zone=3; for (int i=0; (i0); ++i) { double crad=pv.dot(norm[i]); for (int iz=0; iz0) check_pixel (o, omax, zone, res, pix, stk, inclusive); } } return res; } private RangeSet queryPolygonInternal (Pointing[] vertex, int fact) throws Exception { boolean inclusive = (fact!=0); int nv=vertex.length; int ncirc = inclusive ? nv+1 : nv; HealpixUtils.check(nv>=3,"not enough vertices in polygon"); Vec3[] vv = new Vec3[nv]; for (int i=0; i1e-10,"degenerate corner"); if (i==0) flip = (hnd<0.) ? -1 : 1; else HealpixUtils.check(flip*hnd>0,"polygon is not convex"); normal[i].scale(flip); } double[] rad = new double[ncirc]; Arrays.fill(rad,Constants.halfpi); if (inclusive) { CircleFinder cf = new CircleFinder(vv); normal[nv]=cf.getCenter(); rad[nv]=FastMath.acos(cf.getCosrad()); } return queryMultiDisc(normal,rad,fact); } /** Returns a range set of pixels whose centers lie within the convex polygon defined by the {@code vertex} array.

This method is more efficient in the RING scheme. @param vertex an array containing the vertices of the requested convex polygon. @return the requested set of pixel number ranges */ public RangeSet queryPolygon (Pointing[] vertex) throws Exception { return queryPolygonInternal (vertex, 0); } /** Returns a range set of pixels that overlap with the convex polygon defined by the {@code vertex} array.

This method is more efficient in the RING scheme.

This method may return some pixels which don't overlap with the polygon at all. The higher {@code fact} is chosen, the fewer false positives are returned, at the cost of increased run time. @param vertex an array containing the vertices of the requested convex polygon. @param fact The overlapping test will be done at the resolution {@code fact*nside}. For NESTED ordering, {@code fact} must be a power of 2, else it can be any positive integer. A typical choice would be 4. @return the requested set of pixel number ranges */ public RangeSet queryPolygonInclusive (Pointing[] vertex, int fact) throws Exception { return queryPolygonInternal (vertex, fact); } private void check_pixel (int o, int omax, int zone, RangeSet pixset, long pix, pstack stk, boolean inclusive) { if (zone==0) return; if (o=3) // output all subpixels { int sdist=2*(order-o); // the "bit-shift distance" between map orders pixset.append(pix<=1) for (int i=0; i<4; ++i) stk.push(4*pix+3-i,o+1); // add children } else if (o>order) // this implies that inclusive==true { if (zone>=2) // pixel center in shape { pixset.append(pix>>>(2*(o-order))); // output the parent pixel at order stk.popToMark(); // unwind the stack } else // (zone>=1): pixel center in safety range { if (o>>(2*(o-order)));// output the parent pixel at order stk.popToMark(); // unwind the stack } } } else // o==order { if (zone>=2) pixset.append(pix); else if (inclusive) // and (zone>=1) { if (order>>1; // counted from North pole else if (pix<(npix-ncap)) // Equatorial region return (pix-ncap)/nl4 + nside; // counted from North pole else // South Polar cap return nl4-((1+HealpixUtils.isqrt(2*(npix-pix)-1))>>>1); } else { Xyf xyf = nest2xyf(pix); return ((long)(jrll[xyf.face])<0,"step must be positive"); Vec3[] points = new Vec3[4*step]; Xyf xyf = pix2xyf(pix); double dc=0.5/nside; double xc=(xyf.ix+0.5)/nside, yc=(xyf.iy+0.5)/nside; double d = 1./(step*nside); for (int i=0; i bhdu = (new Fits(filename)).getHDU(hdu-1); Header head = bhdu.getHeader(); Scheme scheme = getScheme(head); int nside = Integer.parseInt(getKey(head,"Nside")); Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(col-1); float[] data=null; if (tmp instanceof float[]) data = (float[])tmp; else if (tmp instanceof double[]) { double[] tmp2 = (double[])tmp; data = new float[tmp2.length]; for (int i=0; i bhdu = (new Fits(filename)).getHDU(hdu-1); Header head = bhdu.getHeader(); Scheme scheme = getScheme(head); int nside = Integer.parseInt(getKey(head,"Nside")); Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(col-1); double[] data=null; if (tmp instanceof double[]) data = (double[])tmp; else if (tmp instanceof float[]) { float[] tmp2 = (float[])tmp; data = new double[tmp2.length]; for (int i=0; i=2,"bad nops"); break; case XOR: HealpixUtils.check(nops==2,"bad nops"); break; case NOT: HealpixUtils.check(nops==1,"bad nops"); break; case NONE: HealpixUtils.check(false,"bad operator"); break; } } public MocQueryComponent(Vec3 cnt, double rad) { op = MocQueryOp.NONE; center = new Vec3(cnt); center.normalize(); radius = rad; nops=0; } } static private class queryHelper { private final class pstack { private long[] p; private int[] o; private int s, m; public pstack (int sz) { p=new long[sz]; o=new int[sz]; s=m=0; } public void push (long p_, int o_) { p[s]=p_; o[s]=o_; ++s; } public void pop () { --s; } public void popToMark () { s=m; } public int size () { return s; } public void mark () { m=s; } public int otop () { return o[s-1]; } public long ptop () { return p[s-1]; } public void clear () { s=m=0; } public boolean empty () { return s==0; } } private int order, omax, ncomp; private boolean inclusive; private HealpixBase base[]; private double cr[], crmin[][], crmax[][]; private int shortcut[]; private MocQueryOp op[]; private int nops[]; private Vec3 center[]; private pstack stk; // stack for pixel numbers and their orders private long pix; private int o; private Vec3 pv; private int loc; private void check_pixel (int zone, Moc pixset) { if (zone==0) return; if (o=3) pixset.addPixel(o,pix); // output all subpixels else // (zone>=1) for (int i=0; i<4; ++i) stk.push(4*pix+3-i,o+1); // add children } else if (o>order) // this implies that inclusive==true { if (zone>=2) // pixel center in shape { pixset.addPixel(order,pix>>>(2*(o-order))); // output parent pixel stk.popToMark(); // unwind the stack } else // (zone>=1): pixel center in safety range { if (o>>(2*(o-order))); // output parent pixel stk.popToMark(); // unwind the stack } } } else // o==order { if (zone>=2) pixset.addPixel(order,pix); else if (inclusive) // and (zone>=1) { if (order=0)&&(myloc comp) throws Exception { order=order_; omax=omax_; ncomp=comp.size(); inclusive=inclusive_; base=new HealpixBase[omax+1]; cr=new double[ncomp]; crmin=new double [omax+1][ncomp]; crmax=new double [omax+1][ncomp]; HealpixUtils.check(ncomp>=1,"bad query component ArrayList"); HealpixUtils.check(order<=omax,"order>omax"); if (!inclusive) HealpixUtils.check(order==omax,"inconsistency"); HealpixUtils.check(omax<=HealpixBase.order_max,"omax too high"); op=new MocQueryOp[ncomp]; nops=new int[ncomp]; center=new Vec3[ncomp]; for (int i=0; i=Math.PI) ? -1.01 : Math.cos(r+dr); crmin[o][i] = (r-dr<=0.) ? 1.01 : Math.cos(r-dr); } } stk=new pstack(12+3*omax); // reserve maximum size to avoid reallocation shortcut=new int[ncomp]; for (int i=0; i comp) throws Exception { return (new queryHelper(order,order,false,comp)).result(); } static public Moc doMocQueryInclusive (int order, int omax, ArrayList comp) throws Exception { return (new queryHelper(order,omax,true,comp)).result(); } static private double isLeft (Vec3 a, Vec3 b, Vec3 c) { return (a.cross(b)).dot(c); } // adapted from code available at http://geomalgorithms.com/a12-_hull-3.html // Original copyright notice follows: // Copyright 2001 softSurfer, 2012 Dan Sunday // This code may be freely used and modified for any purpose // providing that this copyright notice is included with it. // SoftSurfer makes no warranty for this code, and cannot be held // liable for any real or imagined damage resulting from its use. // Users of this code must verify correctness for their application. static private int[] getHull (Vec3 vert[], int P[]) throws Exception { // initialize a deque D[] from bottom to top so that the // 1st three vertices of P[] are a ccw triangle int n = P.length; int D[] = new int[2*n+1]; int bot = n-2, top = bot+3; // initial bottom and top deque indices D[bot] = D[top] = P[2]; // 3rd vertex is at both bot and top if (isLeft(vert[P[0]], vert[P[1]], vert[P[2]]) > 0) { D[bot+1] = P[0]; D[bot+2] = P[1]; // ccw vertices are: 2,0,1,2 } else { D[bot+1] = P[1]; D[bot+2] = P[0]; // ccw vertices are: 2,1,0,2 } // compute the hull on the deque D[] for (int i=3; i 0) && (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) > 0) ) continue; // skip an interior vertex // incrementally add an exterior vertex to the deque hull // get the rightmost tangent at the deque bot while (isLeft(vert[D[bot]], vert[D[bot+1]], vert[P[i]]) <= 0) ++bot; // remove bot of deque D[--bot] = P[i]; // insert P[i] at bot of deque // get the leftmost tangent at the deque top while (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) <= 0) --top; // pop top of deque D[++top] = P[i]; // push P[i] onto top of deque } // transcribe deque D[] to the output hull array H[] int nout = top-bot; int res[] = new int[nout]; for (int h=0; h prepPolyHelper (Vec3 vv[], int P[], ArrayList comp, boolean doLast) throws Exception { int hull[]=getHull(vv,P); boolean addHull[]=new boolean[hull.length]; // sync both sequences at the first point of the convex hull int ihull=0, ipoly=0, nhull=hull.length, npoly=P.length; while (hull[ihull]!=P[ipoly]) ++ipoly; // iterate over the pockets between the polygon and its convex hull int npockets=0; if (P.length==3) for (int i=0; i<3; i++) addHull[i]=true; else { do { int ihull_next = (ihull+1)%nhull, ipoly_next = (ipoly+1)%npoly; if (hull[ihull_next]==P[ipoly_next]) // no pocket found { addHull[ihull]=true; ihull=ihull_next; ipoly=ipoly_next; } else // query pocket { int nvpocket=2; // number of vertices for this pocket while (P[ipoly_next]!=hull[ihull_next]) { ipoly_next = (ipoly_next+1)%npoly; ++nvpocket; } int ppocket[] = new int[nvpocket]; int idx=0; int ipoly_bw=ipoly_next; while (P[ipoly_bw]!=hull[ihull]) { ppocket[idx++]=P[ipoly_bw]; ipoly_bw=(ipoly_bw+npoly-1)%npoly; } ppocket[idx]=hull[ihull]; // process pocket recursively ++npockets; comp=prepPolyHelper (vv, ppocket, comp, false); ihull=ihull_next; ipoly=ipoly_next; } } while (ihull!=0); } if (npockets>1) comp.add(new MocQueryComponent(MocQueryOp.OR,npockets)); if (npockets>0) comp.add(new MocQueryComponent(MocQueryOp.NOT)); if (!doLast) addHull[hull.length-1]=false; // add convex hull for (int i=0; i0) ++num_and; if (num_and>1) comp.add(new MocQueryComponent(MocQueryOp.AND,num_and)); return comp; } static public ArrayList prepPolygon(ArrayList vertex) throws Exception { HealpixUtils.check(vertex.size()>=3,"not enough vertices in polygon"); Vec3 vv[] = new Vec3[vertex.size()]; for (int i=0; i comp = new ArrayList(); return prepPolyHelper(vv,P,comp,true); } static public Moc queryGeneralPolygon (ArrayList vertex, int order) throws Exception { return doMocQuery (order, MocQuery.prepPolygon(vertex)); } static public Moc queryGeneralPolygonInclusive (ArrayList vertex, int order, int omax) throws Exception { return doMocQueryInclusive (order, omax, MocQuery.prepPolygon(vertex)); } } healpix_java-3.31/src/healpix/essentials/MocStringIO.java0000644000175000017500000000774212546152426021627 0ustar leoleo/* * This file is part of Healpix Java. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ package healpix.essentials; import java.io.*; /** Moc string I/O routines. @copyright 2014-2015 Max-Planck-Society @author Martin Reinecke */ public class MocStringIO { /** Parses a string following either the basic ASCII or JSON syntax given in the MOC standard document, and converts it into a MOC. The string need not obey the rules for a well-formed MOC given in the document. */ public static Moc mocFromString(String in) { in=in.replaceAll(",+"," "); // replace commas with spaces in=in.replaceAll("[\\[\\]{}\"]+",""); // get rid of useless characters in=in.replaceAll("\\s*[:/]\\s*","/ "); // stick order indicator to order in=in.replaceAll("\\s*-\\s*","-"); // fuse ranges into one token String[] tok = in.split("[\\s]+"); // split at whitespace RangeSet ru = new RangeSet(); int order=0; long ofs=0; for (int i=0; ia+1) s.append("-").append(b-1); } } } if (json&&prefix) s.append("]"); } if (json) s.append("}"); return s.toString(); } /** Converts the Moc to its basic ASCII representation as described in the MOC standard document. The result is well-formed. */ public static String mocToStringASCII (Moc moc) { return mocToStringGeneral(moc,false); } /** Converts the Moc to its JSON representation as described in the MOC standard document. The result is well-formed. */ public static String mocToStringJSON(Moc moc) { return mocToStringGeneral(moc,true); } } healpix_java-3.31/COPYING0000644000175000017500000004313311757651304013263 0ustar leoleo GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 2 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. healpix_java-3.31/README0000644000175000017500000000237612506327634013113 0ustar leoleoInstallation of Healpix Java ---------------------------- requires a Java Development Kit and Apache Ant (see below Notes on installing Java, and on junit) % ant for information on the build targets available: % ant -p Documentation ------------- preinstalled in /doc/html/java/index.html % ant docs will generate /src/java/doc/index.html from the source files ----------------------------------------------------------------- Installing Java =============== Java Development Kit (JDK aka SDK): required to compile any Java code --------------------------------- http://www.oracle.com/technetwork/java/index.html Java based build tool: Ant -------------------------- http://ant.apache.org/bindownload.cgi It is also available thru fink for MacOS About Junit =========== junit.jar is required for Java Healpix library installation. It is shipped with Healpix and available in /src/java/lib/ Just make sure that this path (or a path to any other junit.jar) is included in your CLASSPATH environment variable. Alternatively you can use ant's "-lib" option: ant -lib lib/junit*.jar test Please contact healpix-support AT lists.sourceforge.net for any questions on the code or its installation. healpix_java-3.31/CHANGES0000644000175000017500000000447612546540460013227 0ustar leoleoNew features and improvements introduced with the healpix.essentials package, compared to the HealpixIndex, Healpix and PixTools classes: - close similarities with Healpix_Base_T class from Healpix C++, which allows simultaneous development and bug fixes for both. - support for arbitrary positive Nside values in RING scheme; no longer limited to powers of 2 - maximum supported Nside value: 2^29 - significant performance improvements: most methods have been accelerated by integral factors, some by more than an order of magnitude. - trigonometric functions are computed using an adapted version of Naoki Shibata's SLEEF library (http://freecode.com/projects/sleef), which is considerably faster than Java's own implementation. - re-implementation of queryDisc and queryPolygon: * query methods return RangeSet objects which allow much more compact storage of the result * new native query methods for NESTED ordering; these are slower than those for RING ordering, but much quicker than converting all pixels from a RING result to NESTED. * inclusive queries have been improved: several bugs were fixed, and the number of false positives in the result has been reduced. Users can now choose between quick inclusive queries returning more false positives, and slower ones returning fewer false positives. - the HealpixProc class offers a procedural (instead of object-oriented) interface to the HealpixBase functionality, which simplifies transition for users of the "Healpix" and "PixTools" classes. NOTE: this only works for Nside parameters which are powers of 2 - many bug fixes - no external library dependencies, except for "nom.tam.fits" if FITS I/O is required - the code base is thread-safe in the following sense: * HealpixProc methods can be called concurrently * HealpixBase methods can be called concurrently on different objects Changes after version 3.11: =========================== RangeSet.size() -> RangeSet.nranges() RangeSet(int) constructor has new semantics; see documentation! Changes after version 3.20: =========================== - deprecated parts of the library have been removed - MOC support (see http://ivoa.net/documents/MOC/ for high-level description) - queries for arbitrary polygons (using MOC) - new targets in build.xml which allow compilation without external JARs