Codebase list healpix-java / ec0057c
Import Upstream version 3.30 Leo Singer 7 years ago
39 changed file(s) with 7596 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 New features and improvements introduced with the healpix.essentials package,
1 compared to the HealpixIndex, Healpix and PixTools classes:
2
3 - close similarities with Healpix_Base_T class from Healpix C++, which allows
4 simultaneous development and bug fixes for both.
5 - support for arbitrary positive Nside values in RING scheme; no longer limited
6 to powers of 2
7 - maximum supported Nside value: 2^29
8 - significant performance improvements: most methods have been accelerated
9 by integral factors, some by more than an order of magnitude.
10 - trigonometric functions are computed using an adapted version of Naoki
11 Shibata's SLEEF library (http://freecode.com/projects/sleef), which is
12 considerably faster than Java's own implementation.
13 - re-implementation of queryDisc and queryPolygon:
14 * query methods return RangeSet objects which allow much more compact storage
15 of the result
16 * new native query methods for NESTED ordering; these are slower than those
17 for RING ordering, but much quicker than converting all pixels from a RING
18 result to NESTED.
19 * inclusive queries have been improved: several bugs were fixed, and the
20 number of false positives in the result has been reduced. Users can now
21 choose between quick inclusive queries returning more false positives,
22 and slower ones returning fewer false positives.
23 - the HealpixProc class offers a procedural (instead of object-oriented)
24 interface to the HealpixBase functionality, which simplifies transition
25 for users of the "Healpix" and "PixTools" classes.
26 NOTE: this only works for Nside parameters which are powers of 2
27 - many bug fixes
28 - no external library dependencies, except for "nom.tam.fits" if FITS I/O is
29 required
30 - the code base is thread-safe in the following sense:
31 * HealpixProc methods can be called concurrently
32 * HealpixBase methods can be called concurrently on different objects
33
34
35 Changes after version 3.11:
36 ===========================
37
38 RangeSet.size() -> RangeSet.nranges()
39 RangeSet(int) constructor has new semantics; see documentation!
40
41 Changes after version 3.20:
42 ===========================
43
44 - deprecated parts of the library have been removed
45 - MOC support (see http://ivoa.net/documents/MOC/ for high-level description)
46 - queries for arbitrary polygons (using MOC)
47 - new targets in build.xml which allow compilation without external JARs
0 GNU GENERAL PUBLIC LICENSE
1 Version 2, June 1991
2
3 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
4 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 Preamble
9
10 The licenses for most software are designed to take away your
11 freedom to share and change it. By contrast, the GNU General Public
12 License is intended to guarantee your freedom to share and change free
13 software--to make sure the software is free for all its users. This
14 General Public License applies to most of the Free Software
15 Foundation's software and to any other program whose authors commit to
16 using it. (Some other Free Software Foundation software is covered by
17 the GNU Library General Public License instead.) You can apply it to
18 your programs, too.
19
20 When we speak of free software, we are referring to freedom, not
21 price. Our General Public Licenses are designed to make sure that you
22 have the freedom to distribute copies of free software (and charge for
23 this service if you wish), that you receive source code or can get it
24 if you want it, that you can change the software or use pieces of it
25 in new free programs; and that you know you can do these things.
26
27 To protect your rights, we need to make restrictions that forbid
28 anyone to deny you these rights or to ask you to surrender the rights.
29 These restrictions translate to certain responsibilities for you if you
30 distribute copies of the software, or if you modify it.
31
32 For example, if you distribute copies of such a program, whether
33 gratis or for a fee, you must give the recipients all the rights that
34 you have. You must make sure that they, too, receive or can get the
35 source code. And you must show them these terms so they know their
36 rights.
37
38 We protect your rights with two steps: (1) copyright the software, and
39 (2) offer you this license which gives you legal permission to copy,
40 distribute and/or modify the software.
41
42 Also, for each author's protection and ours, we want to make certain
43 that everyone understands that there is no warranty for this free
44 software. If the software is modified by someone else and passed on, we
45 want its recipients to know that what they have is not the original, so
46 that any problems introduced by others will not reflect on the original
47 authors' reputations.
48
49 Finally, any free program is threatened constantly by software
50 patents. We wish to avoid the danger that redistributors of a free
51 program will individually obtain patent licenses, in effect making the
52 program proprietary. To prevent this, we have made it clear that any
53 patent must be licensed for everyone's free use or not licensed at all.
54
55 The precise terms and conditions for copying, distribution and
56 modification follow.
57
58 GNU GENERAL PUBLIC LICENSE
59 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
60
61 0. This License applies to any program or other work which contains
62 a notice placed by the copyright holder saying it may be distributed
63 under the terms of this General Public License. The "Program", below,
64 refers to any such program or work, and a "work based on the Program"
65 means either the Program or any derivative work under copyright law:
66 that is to say, a work containing the Program or a portion of it,
67 either verbatim or with modifications and/or translated into another
68 language. (Hereinafter, translation is included without limitation in
69 the term "modification".) Each licensee is addressed as "you".
70
71 Activities other than copying, distribution and modification are not
72 covered by this License; they are outside its scope. The act of
73 running the Program is not restricted, and the output from the Program
74 is covered only if its contents constitute a work based on the
75 Program (independent of having been made by running the Program).
76 Whether that is true depends on what the Program does.
77
78 1. You may copy and distribute verbatim copies of the Program's
79 source code as you receive it, in any medium, provided that you
80 conspicuously and appropriately publish on each copy an appropriate
81 copyright notice and disclaimer of warranty; keep intact all the
82 notices that refer to this License and to the absence of any warranty;
83 and give any other recipients of the Program a copy of this License
84 along with the Program.
85
86 You may charge a fee for the physical act of transferring a copy, and
87 you may at your option offer warranty protection in exchange for a fee.
88
89 2. You may modify your copy or copies of the Program or any portion
90 of it, thus forming a work based on the Program, and copy and
91 distribute such modifications or work under the terms of Section 1
92 above, provided that you also meet all of these conditions:
93
94 a) You must cause the modified files to carry prominent notices
95 stating that you changed the files and the date of any change.
96
97 b) You must cause any work that you distribute or publish, that in
98 whole or in part contains or is derived from the Program or any
99 part thereof, to be licensed as a whole at no charge to all third
100 parties under the terms of this License.
101
102 c) If the modified program normally reads commands interactively
103 when run, you must cause it, when started running for such
104 interactive use in the most ordinary way, to print or display an
105 announcement including an appropriate copyright notice and a
106 notice that there is no warranty (or else, saying that you provide
107 a warranty) and that users may redistribute the program under
108 these conditions, and telling the user how to view a copy of this
109 License. (Exception: if the Program itself is interactive but
110 does not normally print such an announcement, your work based on
111 the Program is not required to print an announcement.)
112
113 These requirements apply to the modified work as a whole. If
114 identifiable sections of that work are not derived from the Program,
115 and can be reasonably considered independent and separate works in
116 themselves, then this License, and its terms, do not apply to those
117 sections when you distribute them as separate works. But when you
118 distribute the same sections as part of a whole which is a work based
119 on the Program, the distribution of the whole must be on the terms of
120 this License, whose permissions for other licensees extend to the
121 entire whole, and thus to each and every part regardless of who wrote it.
122
123 Thus, it is not the intent of this section to claim rights or contest
124 your rights to work written entirely by you; rather, the intent is to
125 exercise the right to control the distribution of derivative or
126 collective works based on the Program.
127
128 In addition, mere aggregation of another work not based on the Program
129 with the Program (or with a work based on the Program) on a volume of
130 a storage or distribution medium does not bring the other work under
131 the scope of this License.
132
133 3. You may copy and distribute the Program (or a work based on it,
134 under Section 2) in object code or executable form under the terms of
135 Sections 1 and 2 above provided that you also do one of the following:
136
137 a) Accompany it with the complete corresponding machine-readable
138 source code, which must be distributed under the terms of Sections
139 1 and 2 above on a medium customarily used for software interchange; or,
140
141 b) Accompany it with a written offer, valid for at least three
142 years, to give any third party, for a charge no more than your
143 cost of physically performing source distribution, a complete
144 machine-readable copy of the corresponding source code, to be
145 distributed under the terms of Sections 1 and 2 above on a medium
146 customarily used for software interchange; or,
147
148 c) Accompany it with the information you received as to the offer
149 to distribute corresponding source code. (This alternative is
150 allowed only for noncommercial distribution and only if you
151 received the program in object code or executable form with such
152 an offer, in accord with Subsection b above.)
153
154 The source code for a work means the preferred form of the work for
155 making modifications to it. For an executable work, complete source
156 code means all the source code for all modules it contains, plus any
157 associated interface definition files, plus the scripts used to
158 control compilation and installation of the executable. However, as a
159 special exception, the source code distributed need not include
160 anything that is normally distributed (in either source or binary
161 form) with the major components (compiler, kernel, and so on) of the
162 operating system on which the executable runs, unless that component
163 itself accompanies the executable.
164
165 If distribution of executable or object code is made by offering
166 access to copy from a designated place, then offering equivalent
167 access to copy the source code from the same place counts as
168 distribution of the source code, even though third parties are not
169 compelled to copy the source along with the object code.
170
171 4. You may not copy, modify, sublicense, or distribute the Program
172 except as expressly provided under this License. Any attempt
173 otherwise to copy, modify, sublicense or distribute the Program is
174 void, and will automatically terminate your rights under this License.
175 However, parties who have received copies, or rights, from you under
176 this License will not have their licenses terminated so long as such
177 parties remain in full compliance.
178
179 5. You are not required to accept this License, since you have not
180 signed it. However, nothing else grants you permission to modify or
181 distribute the Program or its derivative works. These actions are
182 prohibited by law if you do not accept this License. Therefore, by
183 modifying or distributing the Program (or any work based on the
184 Program), you indicate your acceptance of this License to do so, and
185 all its terms and conditions for copying, distributing or modifying
186 the Program or works based on it.
187
188 6. Each time you redistribute the Program (or any work based on the
189 Program), the recipient automatically receives a license from the
190 original licensor to copy, distribute or modify the Program subject to
191 these terms and conditions. You may not impose any further
192 restrictions on the recipients' exercise of the rights granted herein.
193 You are not responsible for enforcing compliance by third parties to
194 this License.
195
196 7. If, as a consequence of a court judgment or allegation of patent
197 infringement or for any other reason (not limited to patent issues),
198 conditions are imposed on you (whether by court order, agreement or
199 otherwise) that contradict the conditions of this License, they do not
200 excuse you from the conditions of this License. If you cannot
201 distribute so as to satisfy simultaneously your obligations under this
202 License and any other pertinent obligations, then as a consequence you
203 may not distribute the Program at all. For example, if a patent
204 license would not permit royalty-free redistribution of the Program by
205 all those who receive copies directly or indirectly through you, then
206 the only way you could satisfy both it and this License would be to
207 refrain entirely from distribution of the Program.
208
209 If any portion of this section is held invalid or unenforceable under
210 any particular circumstance, the balance of the section is intended to
211 apply and the section as a whole is intended to apply in other
212 circumstances.
213
214 It is not the purpose of this section to induce you to infringe any
215 patents or other property right claims or to contest validity of any
216 such claims; this section has the sole purpose of protecting the
217 integrity of the free software distribution system, which is
218 implemented by public license practices. Many people have made
219 generous contributions to the wide range of software distributed
220 through that system in reliance on consistent application of that
221 system; it is up to the author/donor to decide if he or she is willing
222 to distribute software through any other system and a licensee cannot
223 impose that choice.
224
225 This section is intended to make thoroughly clear what is believed to
226 be a consequence of the rest of this License.
227
228 8. If the distribution and/or use of the Program is restricted in
229 certain countries either by patents or by copyrighted interfaces, the
230 original copyright holder who places the Program under this License
231 may add an explicit geographical distribution limitation excluding
232 those countries, so that distribution is permitted only in or among
233 countries not thus excluded. In such case, this License incorporates
234 the limitation as if written in the body of this License.
235
236 9. The Free Software Foundation may publish revised and/or new versions
237 of the General Public License from time to time. Such new versions will
238 be similar in spirit to the present version, but may differ in detail to
239 address new problems or concerns.
240
241 Each version is given a distinguishing version number. If the Program
242 specifies a version number of this License which applies to it and "any
243 later version", you have the option of following the terms and conditions
244 either of that version or of any later version published by the Free
245 Software Foundation. If the Program does not specify a version number of
246 this License, you may choose any version ever published by the Free Software
247 Foundation.
248
249 10. If you wish to incorporate parts of the Program into other free
250 programs whose distribution conditions are different, write to the author
251 to ask for permission. For software which is copyrighted by the Free
252 Software Foundation, write to the Free Software Foundation; we sometimes
253 make exceptions for this. Our decision will be guided by the two goals
254 of preserving the free status of all derivatives of our free software and
255 of promoting the sharing and reuse of software generally.
256
257 NO WARRANTY
258
259 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
260 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
261 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
262 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
263 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
264 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
265 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
266 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
267 REPAIR OR CORRECTION.
268
269 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
270 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
271 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
272 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
273 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
274 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
275 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
276 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
277 POSSIBILITY OF SUCH DAMAGES.
278
279 END OF TERMS AND CONDITIONS
280
281 How to Apply These Terms to Your New Programs
282
283 If you develop a new program, and you want it to be of the greatest
284 possible use to the public, the best way to achieve this is to make it
285 free software which everyone can redistribute and change under these terms.
286
287 To do so, attach the following notices to the program. It is safest
288 to attach them to the start of each source file to most effectively
289 convey the exclusion of warranty; and each file should have at least
290 the "copyright" line and a pointer to where the full notice is found.
291
292 <one line to give the program's name and a brief idea of what it does.>
293 Copyright (C) <year> <name of author>
294
295 This program is free software; you can redistribute it and/or modify
296 it under the terms of the GNU General Public License as published by
297 the Free Software Foundation; either version 2 of the License, or
298 (at your option) any later version.
299
300 This program is distributed in the hope that it will be useful,
301 but WITHOUT ANY WARRANTY; without even the implied warranty of
302 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
303 GNU General Public License for more details.
304
305 You should have received a copy of the GNU General Public License
306 along with this program; if not, write to the Free Software
307 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
308
309
310 Also add information on how to contact you by electronic and paper mail.
311
312 If the program is interactive, make it output a short notice like this
313 when it starts in an interactive mode:
314
315 Gnomovision version 69, Copyright (C) year name of author
316 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 This is free software, and you are welcome to redistribute it
318 under certain conditions; type `show c' for details.
319
320 The hypothetical commands `show w' and `show c' should show the appropriate
321 parts of the General Public License. Of course, the commands you use may
322 be called something other than `show w' and `show c'; they could even be
323 mouse-clicks or menu items--whatever suits your program.
324
325 You should also get your employer (if you work as a programmer) or your
326 school, if any, to sign a "copyright disclaimer" for the program, if
327 necessary. Here is a sample; alter the names:
328
329 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332 <signature of Ty Coon>, 1 April 1989
333 Ty Coon, President of Vice
334
335 This General Public License does not permit incorporating your program into
336 proprietary programs. If your program is a subroutine library, you may
337 consider it more useful to permit linking proprietary applications with the
338 library. If this is what you want to do, use the GNU Library General
339 Public License instead of this License.
0 Installation of Healpix Java
1 ----------------------------
2 requires a Java Development Kit and Apache Ant
3 (see below Notes on installing Java, and on junit)
4 % ant
5
6 for information on the build targets available:
7 % ant -p
8
9 Documentation
10 -------------
11 preinstalled in <HEALPIX>/doc/html/java/index.html
12
13 % ant docs
14 will generate
15 <HEALPIX>/src/java/doc/index.html
16 from the source files
17
18 -----------------------------------------------------------------
19
20
21 Installing Java
22 ===============
23
24 Java Development Kit (JDK aka SDK): required to compile any Java code
25 ---------------------------------
26 http://www.oracle.com/technetwork/java/index.html
27
28 Java based build tool: Ant
29 --------------------------
30 http://ant.apache.org/bindownload.cgi
31 It is also available thru fink for MacOS
32
33
34 About Junit
35 ===========
36 junit.jar is required for Java Healpix library installation.
37 It is shipped with Healpix and available in
38 <HEALPIX>/src/java/lib/
39 Just make sure that this path (or a path to any other junit.jar)
40 is included in your CLASSPATH environment variable.
41 Alternatively you can use ant's "-lib" option:
42 ant -lib lib/junit*.jar test
43
44 Please contact healpix-support AT lists.sourceforge.net for any questions on the
45 code or its installation.
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Finds the smallest enclosing cone for a point set on the sphere according to
23 Barequet & Elber: Information Processing Letters 93(2005), p.83.
24 All points are expected to be passed as unit vectors.
25 The enclosing cone must have an opening angle smaller than pi/2.
26
27 @copyright 2011 Max-Planck-Society
28 @author Martin Reinecke */
29 final class CircleFinder
30 {
31 private Vec3 center;
32 private double cosrad;
33
34 private void getCircle (Vec3[] point, int q1, int q2)
35 {
36 center = point[q1].add(point[q2]); center.normalize();
37 cosrad = point[q1].dot(center);
38 for (int i=0; i<q1; ++i)
39 if (point[i].dot(center)<cosrad) // point outside the current circle
40 {
41 center=(point[q1].sub(point[i])).cross(point[q2].sub(point[i]));
42 center.normalize();
43 cosrad=point[i].dot(center);
44 if (cosrad<0)
45 { center.flip(); cosrad=-cosrad; }
46 }
47 }
48 private void getCircle (Vec3[] point, int q)
49 {
50 center = point[0].add(point[q]); center.normalize();
51 cosrad = point[0].dot(center);
52 for (int i=1; i<q; ++i)
53 if (point[i].dot(center)<cosrad) // point outside the current circle
54 getCircle(point,i,q);
55 }
56
57 public CircleFinder (Vec3[] point) throws Exception
58 {
59 int np=point.length;
60 HealpixUtils.check(np>=2,"too few points");
61 center = point[0].add(point[1]); center.normalize();
62 cosrad = point[0].dot(center);
63 for (int i=2; i<np; ++i)
64 if (point[i].dot(center)<cosrad) // point outside the current circle
65 getCircle(point,i);
66 }
67
68 public Vec3 getCenter() { return new Vec3(center); }
69 public double getCosrad() { return cosrad; }
70 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21 import java.io.ByteArrayOutputStream;
22
23 /** Class for compressing/uncompressing monotonous integer sequences.
24 Implementation inspired by Moffat and Stuiver 2000: "Binary Interpolative
25 Coding for Effective Index Compression", Information Retrieval 3, 25
26
27 @copyright 2014 Max-Planck-Society
28 @author Martin Reinecke */
29 public class Compressor
30 {
31 //FIXME: move into separate class
32 private static final class obitstream
33 {
34 private long bitpos;
35 private int curval;
36 private ByteArrayOutputStream strm;
37
38 public obitstream()
39 {
40 bitpos=0;
41 curval=0;
42 strm=new ByteArrayOutputStream();
43 }
44 private void put_internal (long val, int bits)
45 {
46 int bitsleft = 8-(int)(bitpos&7);
47 if (bits<=bitsleft) // wbits==bits
48 {
49 curval |= ((val&((1L<<bits)-1))<<(bitsleft-bits));
50 bitpos+=bits;
51 if ((bitpos&7)==0) { strm.write(curval); curval=0; }
52 }
53 else // wbits==bitsleft
54 {
55 curval |= ((val>>>(bits-bitsleft))&((1<<bitsleft)-1));
56 bitpos+=bitsleft;
57 if ((bitpos&7)==0) { strm.write(curval); curval=0; }
58 put_internal(val,bits-bitsleft);
59 }
60 }
61
62 public void put (long val, int bits) throws Exception
63 {
64 if (bits==0) return;
65 HealpixUtils.check(bits<=63,"too many bits");
66 HealpixUtils.check(val-(val&((1L<<bits)-1))==0,
67 "value has too many bits");
68 put_internal(val,bits);
69 }
70
71 public byte[] getData() throws Exception
72 {
73 if ((bitpos&7)!=0) strm.write(curval);
74 return strm.toByteArray();
75 }
76 }
77
78 //FIXME: move into separate class
79 private static final class ibitstream
80 {
81 private long bitpos;
82 private int curval;
83 private byte[] data;
84
85 public ibitstream(byte[] data_in) throws Exception
86 {
87 HealpixUtils.check(data_in.length>0,"empty input array");
88 bitpos=0;
89 data=data_in.clone();
90 }
91 private long get_internal (long val, int bits)
92 {
93 int bitsleft = 8-(int)(bitpos&7);
94 if (bitsleft==8)
95 {curval=data[(int)(bitpos>>>3)]; if (curval<0) curval+=256;}
96 if (bits<=bitsleft)
97 {
98 val |= ((curval>>>(bitsleft-bits))&((1L<<bits)-1));
99 bitpos+=bits;
100 }
101 else
102 {
103 val |= (curval&((1L<<bitsleft)-1))<<(bits-bitsleft);
104 bitpos+=bitsleft;
105 val=get_internal(val,bits-bitsleft);
106 }
107 return val;
108 }
109 public long get (int bits) throws Exception
110 {
111 if (bits==0) return 0L;
112 HealpixUtils.check(bits<=63,"too many bits");
113 HealpixUtils.check((bitpos+bits)<=8*(long)data.length,
114 "reading past end of stream");
115 long res=0L;
116 return get_internal(res,bits);
117 }
118 }
119
120 private static void interpol_encode2 (long[] data, int l, int r,
121 obitstream obs, int shift) throws Exception
122 {
123 if (r-l<=1) return;
124 int m=l+(r-l)/2;
125
126 long nval = ((data[r]-data[l])>>>shift) - (r-l) + 1;
127 if (nval<=1) return;
128
129 int nb = 1+HealpixUtils.ilog2(nval-1);
130 long val = (data[m]>>>shift)-((data[l]>>>shift)+(m-l));
131 long nshort=(1L<<nb)-nval;
132 if (val<nshort)
133 obs.put(val,nb-1);
134 else
135 obs.put(val+nshort,nb);
136 interpol_encode2(data,l,m,obs,shift);
137 interpol_encode2(data,m,r,obs,shift);
138 }
139
140 /** Return a byte array representing the compressed sequence
141 [data[begin]; data[end-1]] */
142 public static byte[] interpol_encode (long[] data, int begin, int end)
143 throws Exception
144 {
145 obitstream obs=new obitstream();
146 if (begin>=end) // empty range
147 { obs.put(0,8); return obs.getData(); }
148 HealpixUtils.check(data[begin]>=0,"numbers must be nonnegative");
149 long combo=data[begin];
150 for (int i=begin+1; i<end; ++i)
151 {
152 HealpixUtils.check(data[i-1]<data[i],"numbers not strictly increasing");
153 combo|=data[i];
154 }
155 //determine allowable right shift
156 int shift = Long.numberOfTrailingZeros(combo);
157
158 long maxnum=data[end-1]>>>shift;
159 if (end-begin>maxnum) maxnum = end-begin;
160 int maxbits=1+HealpixUtils.ilog2(maxnum);
161 obs.put(maxbits,8);
162 obs.put(shift,8);
163 obs.put(end-begin,maxbits);
164 obs.put(data[begin]>>>shift,maxbits);
165 if (end-begin==1) return obs.getData(); // a single data entry
166 obs.put(data[end-1]>>>shift,maxbits);
167 interpol_encode2(data,begin,end-1,obs,shift);
168 return obs.getData();
169 }
170
171 private static void interpol_decode2 (long[] data, int l, int r,
172 ibitstream ibs, int shift) throws Exception
173 {
174 if (r-l<=1) return;
175 int m=l+(r-l)/2;
176
177 long nval = ((data[r]-data[l])>>>shift) - (r-l) + 1;
178 long val=0;
179
180 if (nval>1)
181 {
182 int nb = 1+HealpixUtils.ilog2(nval-1);
183 long nshort=(1L<<nb)-nval;
184 val=ibs.get(nb-1);
185 if (val>=nshort)
186 val=(val<<1)+ ibs.get(1) - nshort;
187 }
188 data[m]=data[l]+(((m-l)+val)<<shift);
189
190 interpol_decode2(data,l,m,ibs,shift);
191 interpol_decode2(data,m,r,ibs,shift);
192 }
193
194 /** Return an array containing the number sequence decompressed from data. */
195 public static long[] interpol_decode (byte[] data) throws Exception
196 {
197 ibitstream ibs=new ibitstream(data);
198 int maxbits=(int)ibs.get(8);
199 if (maxbits==0) return new long[0];
200 int shift=(int)ibs.get(8);
201 long[] v=new long[(int)ibs.get(maxbits)];
202 v[0]=ibs.get(maxbits)<<shift;
203 if (v.length==1) return v;
204 v[v.length-1]=ibs.get(maxbits)<<shift;
205 interpol_decode2(v,0,v.length-1,ibs,shift);
206 return v;
207 }
208 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Some frequently used constants. */
23 public class Constants
24 {
25 /** The Constant halfpi */
26 public static final double halfpi = Math.PI/2.;
27
28 public static final double inv_halfpi = 2./Math.PI;
29
30 /** The Constant twopi. */
31 public static final double twopi = 2*Math.PI;
32 public static final double inv_twopi = 1./(2*Math.PI);
33
34 /** The Constant twothird. */
35 public static final double twothird = 2./3.;
36 }
0 package healpix.essentials;
1
2 /* Subset of the SLEEF Java library by Naoki Shibata. The code in this file is
3 released to the Public Domain. */
4
5 /**
6 * FastMath class is a Java implementation of the
7 * <a href="http://freecode.com/projects/sleef">SLEEF</a>
8 * library. Some of the methods can be used as substitutions of the
9 * corresponding methods in Math class. They have slightly less
10 * accuracy, and some methods are faster compared to those methods in
11 * Math class. Please note that the methods in the standard Math class
12 * are JNI methods, and the SLEEF library is specialized for SIMD
13 * operations.
14 */
15 public final class FastMath {
16 private static final double mulsign(double x, double y)
17 { return Math.copySign(1, y) * x; }
18
19 /** Checks if the argument is a NaN or not. */
20 private static final boolean isnan(double d)
21 { return d != d; }
22
23 /** Checks if the argument is either positive or negative infinity. */
24 private static final boolean isinf(double d)
25 { return Math.abs(d) == Double.POSITIVE_INFINITY; }
26
27 private static final double sign(double d) { return Math.copySign(1, d); }
28
29 private static final double atanhelper(double s)
30 {
31 double t = s * s;
32 double u = -1.88796008463073496563746e-05;
33 u = u * t + (0.000209850076645816976906797);
34 u = u * t + (-0.00110611831486672482563471);
35 u = u * t + (0.00370026744188713119232403);
36 u = u * t + (-0.00889896195887655491740809);
37 u = u * t + (0.016599329773529201970117);
38 u = u * t + (-0.0254517624932312641616861);
39 u = u * t + (0.0337852580001353069993897);
40 u = u * t + (-0.0407629191276836500001934);
41 u = u * t + (0.0466667150077840625632675);
42 u = u * t + (-0.0523674852303482457616113);
43 u = u * t + (0.0587666392926673580854313);
44 u = u * t + (-0.0666573579361080525984562);
45 u = u * t + (0.0769219538311769618355029);
46 u = u * t + (-0.090908995008245008229153);
47 u = u * t + (0.111111105648261418443745);
48 u = u * t + (-0.14285714266771329383765);
49 u = u * t + (0.199999999996591265594148);
50 u = u * t + (-0.333333333333311110369124);
51
52 return u * t * s + s;
53 }
54
55 private static final double atan2k(double y, double x)
56 {
57 double q = 0.;
58
59 if (x < 0) { x = -x; q = -2.; }
60 if (y > x) { double t = x; x = y; y = -t; q += 1.; }
61
62 return atanhelper(y/x) + q*(Math.PI/2);
63 }
64
65 /** This method calculates the arc tangent of y/x in radians, using
66 the signs of the two arguments to determine the quadrant of the
67 result. The results may have maximum error of 2 ulps. */
68 public static final double atan2(double y, double x)
69 {
70 double r = atan2k(Math.abs(y), x);
71
72 r = mulsign(r, x);
73 if (isinf(x) || x == 0)
74 r = Math.PI/2 - (isinf(x) ? (sign(x) * (Math.PI /2)) : 0);
75 if (isinf(y) )
76 r = Math.PI/2 - (isinf(x) ? (sign(x) * (Math.PI*1/4)) : 0);
77 if ( y == 0)
78 r = (sign(x) == -1 ? Math.PI : 0);
79 return isnan(x) || isnan(y) ? Double.NaN : mulsign(r, y);
80 }
81
82 /** This method calculates the arc sine of x in radians. The return
83 value is in the range [-pi/2, pi/2]. The results may have
84 maximum error of 3 ulps. */
85 public static double asin(double d)
86 { return mulsign(atan2k(Math.abs(d), Math.sqrt((1+d)*(1-d))), d); }
87
88 /** This method calculates the arc cosine of x in radians. The
89 return value is in the range [0, pi]. The results may have
90 maximum error of 3 ulps. */
91 public static double acos(double d) {
92 return mulsign(atan2k(Math.sqrt((1+d)*(1-d)), Math.abs(d)), d)
93 + (d<0 ? Math.PI : 0);
94 }
95
96 /** Returns the arc tangent of an angle. The results may have
97 maximum error of 2 ulps. */
98 public static final double atan(double s)
99 {
100 int q = 0;
101 if (s < 0) { s = -s; q = 2; }
102 if (s > 1) { s = 1.0 / s; q |= 1; }
103
104 double t=atanhelper(s);
105
106 if ((q & 1) != 0) t = 1.570796326794896557998982 - t;
107 if ((q & 2) != 0) t = -t;
108
109 return t;
110 }
111
112 private static final double PI4_A = .7853981554508209228515625;
113 private static final double PI4_B
114 = .794662735614792836713604629039764404296875e-8;
115 private static final double PI4_C
116 = .306161699786838294306516483068750264552437361480769e-16;
117 private static final double M_1_PI = 0.3183098861837906715377675267450287;
118
119 private final static double sincoshelper(double d)
120 {
121 double s = d * d;
122 double u = -7.97255955009037868891952e-18;
123 u = u*s +2.81009972710863200091251e-15;
124 u = u*s -7.64712219118158833288484e-13;
125 u = u*s +1.60590430605664501629054e-10;
126 u = u*s -2.50521083763502045810755e-08;
127 u = u*s +2.75573192239198747630416e-06;
128 u = u*s -0.000198412698412696162806809;
129 u = u*s +0.00833333333333332974823815;
130 u = u*s -0.166666666666666657414808;
131 return s*u*d + d;
132 }
133
134 /** Returns the trigonometric sine of an angle. The results may
135 have maximum error of 2 ulps. */
136 public static final double sin(double d)
137 {
138 double u = d * M_1_PI;
139 long q = (long)(u < 0 ? u - 0.5 : u + 0.5);
140
141 double x=4.*q;
142 d -= x*PI4_A;
143 d -= x*PI4_B;
144 d -= x*PI4_C;
145
146 if ((q&1) != 0) d = -d;
147
148 return sincoshelper(d);
149 }
150
151 /** Returns the trigonometric cosine of an angle. The results may
152 have maximum error of 2 ulps. */
153 public static final double cos(double d)
154 {
155 double u = d*M_1_PI - 0.5;
156 long q = 1+2*(long)(u < 0 ? u - 0.5 : u + 0.5);
157
158 double x=2.*q;
159 d -= x*PI4_A;
160 d -= x*PI4_B;
161 d -= x*PI4_C;
162
163 if ((q&2) == 0) d = -d;
164
165 return sincoshelper(d);
166 }
167 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 */
18 package healpix.essentials;
19
20 import java.io.FileOutputStream;
21
22 import nom.tam.fits.BasicHDU;
23 import nom.tam.fits.BinaryTable;
24 import nom.tam.fits.BinaryTableHDU;
25 import nom.tam.fits.Fits;
26 import nom.tam.fits.FitsFactory;
27 import nom.tam.fits.Header;
28 import nom.tam.util.BufferedDataOutputStream;
29
30 /** Basic FITS I/O support for Healpix maps.
31
32 @copyright 2011 Max-Planck-Society
33 @author Martin Reinecke */
34 public class FitsUtil
35 {
36 private static String getKey (Header head, String key) throws Exception
37 {
38 String upkey = key.toUpperCase();
39 if (head.containsKey(upkey))
40 return head.findCard(upkey).getValue().trim();
41 else if (head.containsKey("HIERARCH."+key))
42 return head.findCard("HIERARCH."+key).getValue().trim();
43 else
44 HealpixUtils.check(false,"key not found: "+key);
45 return null;
46 }
47
48 private static Scheme getScheme(Header head) throws Exception
49 {
50 String fscheme=getKey(head,"Ordering");
51 HealpixUtils.check((fscheme.equals("RING")) || (fscheme.equals("NESTED")),
52 "unsupported ordering scheme");
53 return (fscheme.equals("RING")) ? Scheme.RING : Scheme.NESTED;
54 }
55
56 public static HealpixMapFloat getFloatMap(String filename, int hdu, int col)
57 throws Exception
58 {
59 FitsFactory.setUseHierarch(true);
60 FitsFactory.setUseAsciiTables(false);
61 BasicHDU bhdu = (new Fits(filename)).getHDU(hdu-1);
62 Header head = bhdu.getHeader();
63 Header.setLongStringsEnabled(true);
64
65 Scheme scheme = getScheme(head);
66 int nside = Integer.parseInt(getKey(head,"Nside"));
67
68 Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(col-1);
69 float[] data=null;
70 if (tmp instanceof float[])
71 data = (float[])tmp;
72 else if (tmp instanceof double[])
73 {
74 double[] tmp2 = (double[])tmp;
75 data = new float[tmp2.length];
76 for (int i=0; i<tmp2.length; ++i)
77 data[i] = (float)tmp2[i];
78 }
79 else
80 HealpixUtils.check(false,"unsupported data format");
81
82 HealpixUtils.check(nside*nside*12==data.length,
83 "inconsistent Nside and column length");
84 return new HealpixMapFloat(data, scheme);
85 }
86 public static HealpixMapDouble getDoubleMap(String filename, int hdu, int col)
87 throws Exception
88 {
89 FitsFactory.setUseHierarch(true);
90 FitsFactory.setUseAsciiTables(false);
91 BasicHDU bhdu = (new Fits(filename)).getHDU(hdu-1);
92 Header head = bhdu.getHeader();
93 Header.setLongStringsEnabled(true);
94
95 Scheme scheme = getScheme(head);
96 int nside = Integer.parseInt(getKey(head,"Nside"));
97
98 Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(col-1);
99 double[] data=null;
100 if (tmp instanceof double[])
101 data = (double[])tmp;
102 else if (tmp instanceof float[])
103 {
104 float[] tmp2 = (float[])tmp;
105 data = new double[tmp2.length];
106 for (int i=0; i<tmp2.length; ++i)
107 data[i] = tmp2[i];
108 }
109 else
110 HealpixUtils.check(false,"unsupported data format");
111
112 HealpixUtils.check(nside*nside*12==data.length,
113 "inconsistent Nside and column length");
114 return new HealpixMapDouble(data, scheme);
115 }
116
117 public static void writeFloatMap(HealpixMapFloat map, String filename)
118 throws Exception
119 {
120 FitsFactory.setUseHierarch(true);
121 FitsFactory.setUseAsciiTables(false);
122 Fits f = new Fits();
123 Object[] table = new Object[1];
124 table[0] = map.getData();
125
126 f.addHDU(Fits.makeHDU(table));
127 BinaryTableHDU bhdu = (BinaryTableHDU) f.getHDU(1);
128
129 bhdu.setColumnName(0, "data", "values");
130
131 bhdu.addValue("PIXTYPE", "HEALPIX", "This is a HEALPix map");
132 bhdu.addValue("NSIDE", map.getNside(), "HEALPix NSIDE parameter");
133 bhdu.addValue("ORDERING", map.getScheme().toString().toUpperCase(),
134 "HEALPix ordering scheme");
135
136 FileOutputStream fos = new FileOutputStream(filename);
137 BufferedDataOutputStream s = new BufferedDataOutputStream(fos);
138
139 f.write(s);
140 s.flush();
141 s.close();
142 }
143 public static void writeDoubleMap(HealpixMapDouble map, String filename)
144 throws Exception
145 {
146 FitsFactory.setUseHierarch(true);
147 FitsFactory.setUseAsciiTables(false);
148 Fits f = new Fits();
149 Object[] table = new Object[1];
150 table[0] = map.getData();
151
152 f.addHDU(Fits.makeHDU(table));
153 BinaryTableHDU bhdu = (BinaryTableHDU) f.getHDU(1);
154
155 bhdu.setColumnName(0, "data", "values");
156
157 bhdu.addValue("PIXTYPE", "HEALPIX", "This is a HEALPix map");
158 bhdu.addValue("NSIDE", map.getNside(), "HEALPix NSIDE parameter");
159 bhdu.addValue("ORDERING", map.getScheme().toString().toUpperCase(),
160 "HEALPix ordering scheme");
161
162 FileOutputStream fos = new FileOutputStream(filename);
163 BufferedDataOutputStream s = new BufferedDataOutputStream(fos);
164
165 f.write(s);
166 s.flush();
167 s.close();
168 }
169 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Class describing a location on the sphere
23
24 @copyright 2012 Max-Planck-Society
25 @author Martin Reinecke */
26 public final class Fxyf extends HealpixTables
27 {
28 /** x-coordinate within the basis pixel, range [0.0;1.0] */
29 public double fx;
30 /** y-coordinate within the basis pixel, range [0.0;1.0] */
31 public double fy;
32 /** index of the HEALPix basis pixel, range [0;11] */
33 public int face;
34 public Fxyf (double x, double y, int f)
35 { fx=x; fy=y; face=f; }
36
37 protected Fxyf(Hploc loc)
38 {
39 double z=loc.z, phi=loc.phi;
40
41 double za = Math.abs(z);
42 double tt = HealpixUtils.fmodulo((phi*Constants.inv_halfpi),4.0);// in [0,4)
43
44 if (za<=Constants.twothird) // Equatorial region
45 {
46 double temp1 = 0.5+tt;
47 double temp2 = z*0.75;
48 double jp = temp1-temp2; // index of ascending edge line
49 double jm = temp1+temp2; // index of descending edge line
50 long ifp = (long)jp; // in {0,4}
51 long ifm = (long)jm;
52 long face_num = (ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8));
53 fx = HealpixUtils.fmodulo(jm,1.);
54 fy = 1.-HealpixUtils.fmodulo(jp,1.);
55 face = (int)face_num;
56 }
57 else // polar region, za > 2/3
58 {
59 int ntt = Math.min(3,(int)tt);
60 double tp = tt-ntt;
61 double tmp = ((za<0.99)||(!loc.have_sth)) ?
62 Math.sqrt(3*(1-za)) :
63 loc.sth/Math.sqrt((1.+za)/3.);
64
65 double jp = tp*tmp; // increasing edge line index
66 double jm = (1.0-tp)*tmp; // decreasing edge line index
67 if (jp>=1.) jp = 1.; // for points too close to the boundary
68 if (jm>=1.) jm = 1.;
69 if (z>=0)
70 { fx=1.-jm; fy=1.-jp; face=ntt; }
71 else
72 { fx=jp; fy=jm; face=ntt+8; }
73 }
74 }
75
76 public Fxyf(Vec3 v)
77 { this(new Hploc(v)); }
78
79 protected Hploc toHploc()
80 {
81 Hploc loc = new Hploc();
82 double jr = jrll[face] - fx - fy;
83
84 double nr;
85 if (jr<1)
86 {
87 nr = jr;
88 double tmp = nr*nr/3.;
89 loc.z = 1 - tmp;
90 if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
91 }
92 else if (jr>3)
93 {
94 nr = 4-jr;
95 double tmp = nr*nr/3.;
96 loc.z = tmp - 1;
97 if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
98 }
99 else
100 {
101 nr = 1;
102 loc.z = (2-jr)*2./3.;
103 }
104
105 double tmp=jpll[face]*nr+fx-fy;
106 if (tmp<0) tmp+=8;
107 if (tmp>=8) tmp-=8;
108 loc.phi = (nr<1e-15) ? 0 : (0.5*Constants.halfpi*tmp)/nr;
109 return loc;
110 }
111 public Vec3 toVec3()
112 { return toHploc().toVec3(); }
113 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 import java.util.Arrays;
23
24 /** Basic opersations related to the HEALPix pixelisation.
25 This class is conceptually very similar the the Healpix_Base class
26 of Healpix_cxx. It supports the NESTED scheme for nside parameters which are
27 powers of 2, and the RING scheme for arbitrary positive nside parameters.
28 The maximum supported nside parameter is 2^29.
29
30 @copyright 2011, 2012 Max-Planck-Society
31 @author Martin Reinecke */
32 public class HealpixBase extends HealpixTables
33 {
34 protected final class Xyf
35 {
36 public int ix, iy, face;
37 public Xyf () {}
38 public Xyf (int x, int y, int f)
39 { ix=x; iy=y; face=f; }
40 }
41
42 private final class RingInfoSmall
43 {
44 long startpix, ringpix;
45 boolean shifted;
46 }
47
48 /** Maximum order parameter */
49 public static final int order_max=29;
50 /** Maximum Nside parameter; equivalent to 2^{@code order_max}. */
51 public static final long ns_max=1L<<order_max;
52
53 /** The order of the map; -1 when {@code nside} is not a power of 2. */
54 protected int order;
55
56 /** The Nside parameter. */
57 protected long nside;
58
59 protected long nl2, nl3, nl4, npface, npix, ncap;
60 protected double fact1, fact2;
61
62 /** The ordering scheme. */
63 protected Scheme scheme;
64
65 private static long spread_bits (int v)
66 {
67 return (long)(utab[ v &0xff]) | ((long)(utab[(v>>> 8)&0xff])<<16)
68 | ((long)(utab[(v>>>16)&0xff])<<32) | ((long)(utab[(v>>>24)&0xff])<<48);
69 }
70 private static int compress_bits (long v)
71 {
72 long raw = v&0x5555555555555555L;
73 raw |= raw>>>15;
74 int raw1 = (int)(raw&0xffffL), raw2 = (int)((raw>>>32)&0xffffL);
75 return ctab[raw1&0xff] | (ctab[raw1>>>8]<< 4)
76 | (ctab[raw2&0xff]<<16) | (ctab[raw2>>>8]<<20);
77 }
78
79 private Xyf nest2xyf(long ipix)
80 {
81 long pix=ipix&(npface-1);
82 return new Xyf (compress_bits(pix), compress_bits(pix>>>1),
83 (int)(ipix>>>(2*order)));
84 }
85
86 private long xyf2nest(int ix, int iy, int face_num)
87 {
88 return ((long)(face_num)<<(2*order)) +
89 spread_bits(ix) + (spread_bits(iy)<<1);
90 }
91
92 private long xyf2ring(int ix, int iy, int face_num)
93 {
94 long jr = ((long)jrll[face_num]*nside) - (long)ix - (long)iy - 1L;
95
96 RingInfoSmall ris = get_ring_info_small(jr);
97 long nr=ris.ringpix>>>2, kshift=ris.shifted ? 0:1;
98
99 long jp = (jpll[face_num]*nr + (long)ix - (long)iy + 1L + kshift) / 2L;
100 if (jp>nl4)
101 jp-=nl4;
102 else
103 if (jp<1) jp+=nl4;
104
105 return ris.startpix + jp - 1L;
106 }
107
108 protected Xyf ring2xyf(long pix)
109 {
110 Xyf ret = new Xyf();
111 long iring, iphi, kshift, nr;
112
113 if (pix<ncap) // North Polar cap
114 {
115 iring = (1+HealpixUtils.isqrt(1L+2L*pix))>>>1; //counted from North pole
116 iphi = (pix+1) - 2*iring*(iring-1);
117 kshift = 0;
118 nr = iring;
119 ret.face=(int)((iphi-1)/nr);
120 }
121 else if (pix<(npix-ncap)) // Equatorial region
122 {
123 long ip = pix - ncap;
124 long tmp = (order>=0) ? ip>>>(order+2) : ip/nl4;
125 iring = tmp+nside;
126 iphi = ip-tmp*nl4 + 1;
127 kshift = (iring+nside)&1;
128 nr = nside;
129 long ire = iring-nside+1,
130 irm = nl2+2-ire;
131 long ifm = iphi - (ire>>>1) + nside -1,
132 ifp = iphi - (irm>>>1) + nside -1;
133 if (order>=0)
134 { ifm >>>= order; ifp >>>= order; }
135 else
136 { ifm /= nside; ifp /= nside; }
137 ret.face = (int)((ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8)));
138 }
139 else // South Polar cap
140 {
141 long ip = npix - pix;
142 iring = (1+HealpixUtils.isqrt(2L*ip-1L))>>>1; //counted from South pole
143 iphi = 4L*iring + 1 - (ip - 2L*iring*(iring-1L));
144 kshift = 0;
145 nr = iring;
146 iring = 2L*nl2-iring;
147 ret.face = 8 + (int)((iphi-1)/nr);
148 }
149
150 long irt = iring - ((long)jrll[ret.face]*nside) + 1L;
151 long ipt = 2L*iphi- (long)jpll[ret.face]*nr - kshift -1L;
152 if (ipt>=nl2) ipt-=8L*nside;
153
154 ret.ix = (int)(( ipt-irt)>>>1);
155 ret.iy = (int)((-ipt-irt)>>>1);
156
157 return ret;
158 }
159
160 protected Xyf pix2xyf (long pix)
161 { return (scheme==Scheme.RING) ? ring2xyf(pix) : nest2xyf(pix); }
162
163 protected long xyf2pix (int ix, int iy, int face_num)
164 {
165 return (scheme==Scheme.RING) ?
166 xyf2ring(ix,iy,face_num) : xyf2nest(ix,iy,face_num);
167 }
168 protected long xyf2pix (Xyf xyf)
169 {
170 return (scheme==Scheme.RING) ?
171 xyf2ring(xyf.ix,xyf.iy,xyf.face) : xyf2nest(xyf.ix,xyf.iy,xyf.face);
172 }
173
174 /** Calculates the map order from its Nside parameter.
175 @param nside the Nside parameter
176 @return the map order corresponding to {@code nside}; -1 if
177 {@code nside} is not a power of 2. */
178 public static int nside2order(long nside) throws Exception
179 {
180 HealpixUtils.check (nside>0,"nside must be positive");
181 return ((nside&(nside-1))!=0) ? -1 : HealpixUtils.ilog2(nside);
182 }
183
184 /** Calculates the Nside parameter from the number of pixels.
185 @param npix the number of pixels
186 @return the computed Nside parameter */
187 public static long npix2Nside(long npix) throws Exception
188 {
189 HealpixUtils.check (npix>0,"npix must be positive");
190 long nside = HealpixUtils.isqrt(npix/12);
191 HealpixUtils.check(12*nside*nside==npix,"npix is not 12*nside*nside");
192 HealpixUtils.check(nside<=ns_max,"nside is too large");
193 return nside;
194 }
195 /** Calculates the number of pixels from the Nside parameter.
196 @param nside the Nside parameter
197 @return the computed number of pixels */
198 public static long nside2Npix(long nside) throws Exception
199 {
200 HealpixUtils.check (nside>0,"nside must be positive");
201 HealpixUtils.check(nside<=ns_max,"nside is too large");
202 return 12*nside*nside;
203 }
204
205 /** Calculates the number of pixels from the order parameter.
206 @param order the order parameter
207 @return the computed number of pixels */
208 public static long order2Npix(int order) throws Exception
209 {
210 HealpixUtils.check (order>=0,"order must be nonnegative");
211 HealpixUtils.check(order<=order_max,"order is too large");
212 return 12*(1L<<(2*order));
213 }
214
215 /** Adjusts the object to nside_in.
216 @param nside_in the new Nside parameter */
217 public void setNside (long nside_in) throws Exception
218 {
219 if (nside==nside_in) return;
220 nside=nside_in;
221 HealpixUtils.check(nside<=ns_max && nside>0,
222 "Nside must be between 1 and " + ns_max);
223
224 order = nside2order(nside);
225 if (scheme==Scheme.NESTED && order<0)
226 throw new Exception("Nside must be a power of 2 for NESTED scheme");
227 nl2 = 2*nside;
228 nl3 = 3*nside;
229 nl4 = 4*nside;
230 npface = nside*nside;
231 ncap = 2*nside*(nside-1); // pixels in each polar cap
232 npix = 12*npface;
233 fact2 = 4.0/npix;
234 fact1 = (nside<<1)*fact2;
235 }
236
237 /** Adjusts the object to nside_in and scheme_in.
238 @param nside_in the new Nside parameter
239 @param scheme_in the new ordering scheme */
240 public void setNsideAndScheme (long nside_in, Scheme scheme_in)
241 throws Exception
242 {
243 if ((scheme==scheme_in) && (nside==nside_in)) return;
244 HealpixUtils.check (((nside_in&(nside_in-1))==0)||(scheme_in==Scheme.RING),
245 "Nside must be a power of 2 for NESTED scheme");
246 scheme=scheme_in;
247 setNside(nside_in);
248 }
249
250 /** Initializes the object to Nside=1 and scheme=NESTED. */
251 public HealpixBase()
252 {
253 try
254 { nside=0; setNsideAndScheme(1,Scheme.NESTED); }
255 catch(Exception Ex) {/*cannot happen*/}
256 }
257
258 /** Initializes the object to a user-supplied Nside and ordering scheme.
259 @param nside_in the Nside parameter
260 @param scheme_in the ordering scheme */
261 public HealpixBase(long nside_in, Scheme scheme_in) throws Exception
262 { nside=nside_in-1; setNsideAndScheme(nside_in, scheme_in); }
263
264 /** Returns the current ordering scheme.
265 @return the current ordering scheme */
266 public Scheme getScheme()
267 { return scheme; }
268
269 /** Returns the current Nside parameter.
270 @return the current Nside parameter */
271 public int getNside()
272 { return (int)nside; }
273
274 /** Returns the total number of pixels in the pixelisation.
275 @return the current total number of pixels */
276 public long getNpix()
277 { return npix; }
278
279 /** Adjusts the object to scheme.
280 @param scheme_in the new ordering scheme */
281 public void setScheme(Scheme scheme_in) throws Exception
282 {
283 if (scheme_in==Scheme.NESTED && order<0)
284 throw new Exception("Nside must be a power of 2 for NESTED scheme");
285 scheme = scheme_in;
286 }
287
288 /** Returns the current order parameter.
289 @return the current map order parameter. */
290 public int getOrder()
291 { return order; }
292
293 /** Returns the pixel which contains the supplied Pointing.
294 @param ptg the requested location on the sphere.
295 @return the pixel number containing the location. */
296 public long ang2pix(Pointing ptg) throws Exception
297 { return loc2pix(new Hploc(ptg)); }
298
299 /** Returns the Pointing corresponding to the center of the supplied pixel.
300 @param pix the requested pixel number.
301 @return the pixel's center coordinates. */
302 public Pointing pix2ang(long pix) throws Exception
303 { return pix2loc(pix).toPointing(); }
304
305 /** Returns the pixel which contains the supplied Vec3.
306 @param vec the requested location on the sphere (need not be normalized).
307 @return the pixel number containing the location. */
308 public long vec2pix(Vec3 vec) throws Exception
309 { return loc2pix(new Hploc(vec)); }
310
311 /** Returns the normalized 3-vector corresponding to the center of the
312 supplied pixel.
313 @param pix the requested pixel number.
314 @return the pixel's center coordinates. */
315 public Vec3 pix2vec(long pix) throws Exception
316 { return pix2loc(pix).toVec3(); }
317
318 /** Returns nested pixel number for the supplied ring pixel number.
319 @param ipring the requested pixel number in RING scheme.
320 @return the corresponding pixel number in NESTED scheme. */
321 public long ring2nest(long ipring) throws Exception
322 {
323 Xyf xyf = ring2xyf(ipring);
324 return xyf2nest (xyf.ix,xyf.iy, xyf.face);
325 }
326
327 /** Returns ring pixel number for the supplied nested pixel number.
328 @param ipnest the requested pixel number in NESTED scheme.
329 @return the corresponding pixel number in RING scheme. */
330 public long nest2ring(long ipnest) throws Exception
331 {
332 Xyf xyf = nest2xyf(ipnest);
333 return xyf2ring (xyf.ix,xyf.iy, xyf.face);
334 }
335
336 protected long loc2pix (Hploc loc)
337 {
338 double z=loc.z, phi=loc.phi;
339
340 double za = Math.abs(z);
341 double tt = HealpixUtils.fmodulo((phi*Constants.inv_halfpi),4.0);// in [0,4)
342
343 if (scheme==Scheme.RING)
344 {
345 if (za<=Constants.twothird) // Equatorial region
346 {
347 double temp1 = nside*(0.5+tt);
348 double temp2 = nside*z*0.75;
349 long jp = (long)(temp1-temp2); // index of ascending edge line
350 long jm = (long)(temp1+temp2); // index of descending edge line
351
352 // ring number counted from z=2/3
353 long ir = nside + 1 + jp - jm; // in {1,2n+1}
354 long kshift = 1-(ir&1); // kshift=1 if ir even, 0 otherwise
355
356 long t1 = jp+jm-nside+kshift+1+nl4+nl4;
357 long ip = (order>0) ?
358 (t1>>>1)&(nl4-1) : ((t1>>>1)%nl4); // in {0,4n-1}
359
360 return ncap + (ir-1)*nl4 + ip;
361 }
362 else // North & South polar caps
363 {
364 double tp = tt-(long)(tt);
365 double tmp = ((za<0.99)||(!loc.have_sth)) ?
366 nside*Math.sqrt(3*(1-za)) :
367 nside*loc.sth/Math.sqrt((1.+za)/3.);
368
369 long jp = (long)(tp*tmp); // increasing edge line index
370 long jm = (long)((1.0-tp)*tmp); // decreasing edge line index
371
372 long ir = jp+jm+1; // ring number counted from the closest pole
373 long ip = (long)(tt*ir); // in {0,4*ir-1}
374 assert((ip>=0)&&(ip<4*ir));
375
376 return (z>0) ? 2*ir*(ir-1) + ip : npix - 2*ir*(ir+1) + ip;
377 }
378 }
379 else // scheme_ == NEST
380 {
381 if (za<=Constants.twothird) // Equatorial region
382 {
383 double temp1 = nside*(0.5+tt);
384 double temp2 = nside*(z*0.75);
385 long jp = (long)(temp1-temp2); // index of ascending edge line
386 long jm = (long)(temp1+temp2); // index of descending edge line
387 long ifp = jp >>> order; // in {0,4}
388 long ifm = jm >>> order;
389 long face_num = (ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8));
390
391 long ix = jm & (nside-1),
392 iy = nside - (jp & (nside-1)) - 1;
393 return xyf2nest((int)ix,(int)iy,(int)face_num);
394 }
395 else // polar region, za > 2/3
396 {
397 int ntt = Math.min(3,(int)tt);
398 double tp = tt-ntt;
399 double tmp = ((za<0.99)||(!loc.have_sth)) ?
400 nside*Math.sqrt(3*(1-za)) :
401 nside*loc.sth/Math.sqrt((1.+za)/3.);
402
403 long jp = (long)(tp*tmp); // increasing edge line index
404 long jm = (long)((1.0-tp)*tmp); // decreasing edge line index
405 if (jp>=nside) jp = nside-1; // for points too close to the boundary
406 if (jm>=nside) jm = nside-1;
407 return (z>=0) ?
408 xyf2nest((int)(nside-jm -1),(int)(nside-jp-1),ntt) :
409 xyf2nest((int)jp,(int)jm,ntt+8);
410 }
411 }
412 }
413
414 /** Returns the pixel which contains the supplied Zphi.
415 @param zphi the requested location on the sphere.
416 @return the pixel number containing the location. */
417 public long zphi2pix (Zphi zphi)
418 { return loc2pix (new Hploc(zphi)); }
419
420 protected Hploc pix2loc (long pix)
421 {
422 Hploc loc = new Hploc();
423 if (scheme==Scheme.RING)
424 {
425 if (pix<ncap) // North Polar cap
426 {
427 long iring = (1+(HealpixUtils.isqrt(1+2*pix)))>>>1; //from North pole
428 long iphi = (pix+1) - 2*iring*(iring-1);
429
430 double tmp = (iring*iring)*fact2;
431 loc.z = 1.0 - tmp;
432 if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
433 loc.phi = (iphi-0.5) * Constants.halfpi/iring;
434 }
435 else if (pix<(npix-ncap)) // Equatorial region
436 {
437 long ip = pix - ncap;
438 long tmp = (order>=0) ? ip>>>(order+2) : ip/nl4;
439 long iring = tmp + nside,
440 iphi = ip-nl4*tmp+1;;
441 // 1 if iring+nside is odd, 1/2 otherwise
442 double fodd = ((iring+nside)&1)!=0 ? 1 : 0.5;
443
444 loc.z = (nl2-iring)*fact1;
445 loc.phi = (iphi-fodd) * Math.PI*0.75*fact1;
446 }
447 else // South Polar cap
448 {
449 long ip = npix - pix;
450 long iring = (1+HealpixUtils.isqrt(2*ip-1))>>>1; //from South pole
451 long iphi = 4*iring + 1 - (ip - 2*iring*(iring-1));
452
453 double tmp = (iring*iring)*fact2;
454 loc.z = tmp-1.0;
455 if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
456 loc.phi = (iphi-0.5) * Constants.halfpi/iring;
457 }
458 }
459 else
460 {
461 Xyf xyf= nest2xyf(pix);
462
463 long jr = ((long)(jrll[xyf.face])<<order) -xyf.ix - xyf.iy - 1;
464
465 long nr;
466 if (jr<nside)
467 {
468 nr = jr;
469 double tmp = (nr*nr)*fact2;
470 loc.z = 1 - tmp;
471 if (loc.z>0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
472 }
473 else if (jr>nl3)
474 {
475 nr = nl4-jr;
476 double tmp = (nr*nr)*fact2;
477 loc.z = tmp - 1;
478 if (loc.z<-0.99) { loc.sth=Math.sqrt(tmp*(2.-tmp)); loc.have_sth=true; }
479 }
480 else
481 {
482 nr = nside;
483 loc.z = (nl2-jr)*fact1;
484 }
485
486 long tmp=(long)(jpll[xyf.face])*nr+xyf.ix-xyf.iy;
487 assert(tmp<8*nr); // must not happen
488 if (tmp<0) tmp+=8*nr;
489 loc.phi = (nr==nside) ? 0.75*Constants.halfpi*tmp*fact1 :
490 (0.5*Constants.halfpi*tmp)/nr;
491 }
492 return loc;
493 }
494
495 /** Returns the Zphi corresponding to the center of the supplied pixel.
496 @param pix the requested pixel number.
497 @return the pixel's center coordinates. */
498 public Zphi pix2zphi (long pix)
499 { return pix2loc(pix).toZphi(); }
500
501 /** Returns the neighboring pixels of ipix.
502 This method works in both RING and NEST schemes, but is
503 considerably faster in the NEST scheme.
504 @param ipix the requested pixel number.
505 @return array with indices of the neighboring pixels.
506 The returned array contains (in this order)
507 the pixel numbers of the SW, W, NW, N, NE, E, SE and S neighbor
508 of ipix. If a neighbor does not exist (this can only happen
509 for the W, N, E and S neighbors), its entry is set to -1. */
510 public long[] neighbours(long ipix) throws Exception
511 {
512 long[] result = new long[8];
513 Xyf xyf = (scheme==Scheme.NESTED) ? nest2xyf(ipix) : ring2xyf(ipix);
514 int ix = xyf.ix, iy=xyf.iy, face_num=xyf.face;
515
516 long nsm1 = nside-1;
517 if ((ix>0)&&(ix<nsm1)&&(iy>0)&&(iy<nsm1))
518 {
519 if (scheme==Scheme.RING)
520 for (int m=0; m<8; ++m)
521 result[m]=(xyf2ring(ix+xoffset[m],iy+yoffset[m],face_num));
522 else
523 {
524 long fpix = (long)(face_num)<<(2*order),
525 px0=spread_bits(ix ), py0=spread_bits(iy )<<1,
526 pxp=spread_bits(ix+1), pyp=spread_bits(iy+1)<<1,
527 pxm=spread_bits(ix-1), pym=spread_bits(iy-1)<<1;
528
529 result[0]=fpix+pxm+py0; result[1]=fpix+pxm+pyp;
530 result[2]=fpix+px0+pyp; result[3]=fpix+pxp+pyp;
531 result[4]=fpix+pxp+py0; result[5]=fpix+pxp+pym;
532 result[6]=fpix+px0+pym; result[7]=fpix+pxm+pym;
533 }
534 }
535 else
536 {
537 for (int i=0; i<8; ++i)
538 {
539 int x=ix+xoffset[i];
540 int y=iy+yoffset[i];
541 int nbnum=4;
542 if (x<0)
543 { x+=nside; nbnum-=1; }
544 else if (x>=nside)
545 { x-=nside; nbnum+=1; }
546 if (y<0)
547 { y+=nside; nbnum-=3; }
548 else if (y>=nside)
549 { y-=nside; nbnum+=3; }
550
551 int f = facearray[nbnum][face_num];
552
553 if (f>=0)
554 {
555 int bits = swaparray[nbnum][face_num>>>2];
556 if ((bits&1)>0) x=(int)(nside-x-1);
557 if ((bits&2)>0) y=(int)(nside-y-1);
558 if ((bits&4)>0) { int tint=x; x=y; y=tint; }
559 result[i] = (scheme==Scheme.NESTED) ?
560 xyf2nest(x,y,f) : xyf2ring(x,y,f);
561 }
562 else
563 result[i]=-1;
564 }
565 }
566 return result;
567 }
568
569 /** Returns the maximum angular distance between a pixel center and its
570 corners.
571 @return maximum angular distance between a pixel center and its
572 corners. */
573 public double maxPixrad()
574 {
575 Vec3 va = new Vec3(new Zphi(2./3., Math.PI/nl4));
576 double t1 = 1.-1./nside;
577 t1*=t1;
578 Vec3 vb = new Vec3(new Zphi(1-t1/3, 0));
579 return va.angle(vb);
580 }
581
582 private RingInfoSmall get_ring_info_small (long ring)
583 {
584 RingInfoSmall ret = new RingInfoSmall();
585 if (ring<nside)
586 {
587 ret.shifted = true;
588 ret.ringpix = 4*ring;
589 ret.startpix = 2*ring*(ring-1);
590 }
591 else if (ring<nl3)
592 {
593 ret.shifted = ((ring-nside) & 1) == 0;
594 ret.ringpix = nl4;
595 ret.startpix = ncap + (ring-nside)*nl4;
596 }
597 else
598 {
599 ret.shifted = true;
600 long nr=nl4-ring;
601 ret.ringpix = 4*nr;
602 ret.startpix = npix-2*nr*(nr+1);
603 }
604 return ret;
605 }
606
607 private long ringAbove (double z)
608 {
609 double az=Math.abs(z);
610 if (az> Constants.twothird) // polar caps
611 {
612 long iring = (long)(nside*Math.sqrt(3*(1-az)));
613 return (z>0) ? iring : nl4-iring-1;
614 }
615 else // equatorial region
616 return (long)(nside*(2.0-1.5*z));
617 }
618
619 /** Returns the z-coordinate (equivalent to the cosine of the colatitude)
620 for the requested ring.
621 This method also accepts the not-really-existing ring indices 0 and
622 4*Nside, which correspond to North and South Poles, respectively.
623 @param ring ring index: the northernmost ring in the map has index 1;
624 ring indices are increasing towards the South pole.
625 @return z-coordinate of the ring. */
626 public double ring2z (long ring)
627 {
628 if (ring<nside)
629 return 1 - ring*ring*fact2;
630 if (ring <=nl3)
631 return (nl2-ring)*fact1;
632 ring=nl4 - ring;
633 return ring*ring*fact2 - 1;
634 }
635 /** Returns the colatitude for the requested ring.
636 This method also accepts the not-really-existing ring indices 0 and
637 4*Nside, which correspond to North and South Poles, respectively.
638 @param ring ring index: the northernmost ring in the map has index 1;
639 ring indices are increasing towards the South pole.
640 @return z-coordinate of the ring. */
641 public double ring2theta (long ring)
642 {
643 if (ring<nside)
644 {
645 double tmp=ring*ring*fact2;
646 return FastMath.atan2 (Math.sqrt(tmp*(2.-tmp)),1-tmp);
647 }
648 if (ring <=nl3)
649 {
650 double cth=(nl2-ring)*fact1;
651 return FastMath.atan2 (Math.sqrt(1.-cth*cth),cth);
652 }
653 ring=nl4 - ring;
654 double tmp=ring*ring*fact2;
655 return FastMath.atan2 (Math.sqrt(tmp*(2.-tmp)),tmp-1);
656 }
657
658 private final class pstack
659 {
660 private long[] p;
661 private int[] o;
662 private int s, m;
663
664 public pstack (int sz)
665 { p=new long[sz]; o=new int[sz]; s=m=0; }
666 public void push (long p_, int o_)
667 { p[s]=p_; o[s]=o_; ++s; }
668 public void pop ()
669 { --s; }
670 public void popToMark ()
671 { s=m; }
672 public int size ()
673 { return s; }
674 public void mark ()
675 { m=s; }
676 public int otop ()
677 { return o[s-1]; }
678 public long ptop ()
679 { return p[s-1]; }
680 }
681
682 private RangeSet queryStripInternal(double theta1, double theta2,
683 boolean inclusive) throws Exception
684 {
685 RangeSet pixset = new RangeSet(1);
686 if (scheme==Scheme.RING)
687 {
688 long ring1 = Math.max(1,1+ringAbove(FastMath.cos(theta1))),
689 ring2 = Math.min(4*nside-1,ringAbove(FastMath.cos(theta2)));
690 if (inclusive)
691 {
692 ring1 = Math.max(1,ring1-1);
693 ring2 = Math.min(4*nside-1,ring2+1);
694 }
695
696 RingInfoSmall ris1 = get_ring_info_small(ring1),
697 ris2 = get_ring_info_small(ring2);
698 long pix1 = ris1.startpix,
699 pix2 = ris2.startpix+ris2.ringpix;
700 if (pix1<pix2) pixset.append(pix1,pix2);
701 }
702 else
703 HealpixUtils.check(false,"queryStrip not yet implemented for NESTED");
704
705 return pixset;
706 }
707
708 /** Returns a range set of pixels whose centers lie within a given latitude
709 range (if {@code inclusive==false}), or which overlap with this range
710 (if {@code inclusive==true}).<p>
711 The latitude range is defined as follows:
712 <ul>
713 <li>if {@code theta1<theta2}, it is the range between {@code theta1}
714 and {@code theta2}</li>
715 <li>otherwise it is the range between 0 and {@code theta2}, and between
716 {@code theta1} and pi.</li>
717 </ul>
718 This method currently only works in the RING scheme. */
719 public RangeSet queryStrip(double theta1, double theta2,
720 boolean inclusive) throws Exception
721 {
722 if (theta1<theta2)
723 return queryStripInternal(theta1,theta2,inclusive);
724 RangeSet res = queryStripInternal(0.,theta2,inclusive);
725 return res.union(queryStripInternal(theta1,Math.PI,inclusive));
726 }
727
728 private boolean checkPixelRing (HealpixBase b2, long pix, long nr,
729 long ipix1, int fct, Zphi czphi, double cosrp2, long cpix)
730 {
731 if (pix>=nr) pix-=nr;
732 if (pix<0) pix+=nr;
733 pix+=ipix1;
734 if (pix==cpix) return false; // disk center in pixel => overlap
735 Xyf xyf=pix2xyf(pix);
736 for (int i=0; i<fct-1; ++i) // go along the 4 edges
737 {
738 int ox=fct*xyf.ix, oy=fct*xyf.iy;
739 Xyf xyf2 = new Xyf (ox,oy,xyf.face);
740 double pz,pphi;
741 xyf2.ix=ox+i; xyf2.iy=oy;
742 if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
743 return false; // overlap
744 xyf2.ix=ox+fct-1; xyf2.iy=oy+i;
745 if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
746 return false; // overlap
747 xyf2.ix=ox+fct-1-i; xyf2.iy=oy+fct-1;
748 if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
749 return false; // overlap
750 xyf2.ix=ox; xyf2.iy=oy+fct-1-i;
751 if (HealpixUtils.cosdist_zphi(czphi,b2.pix2zphi(b2.xyf2pix(xyf2)))>cosrp2)
752 return false; // overlap
753 }
754 return true;
755 }
756
757 private RangeSet queryDiscInternal(Pointing ptg, double radius, int fact)
758 throws Exception
759 {
760 boolean inclusive=(fact!=0);
761 RangeSet pixset = new RangeSet();
762 if (scheme==Scheme.RING)
763 {
764 int fct=1;
765 if (inclusive)
766 {
767 HealpixUtils.check ((1L<<order_max)/nside>=fact,
768 "invalid oversampling factor");
769 fct = fact;
770 }
771 HealpixBase b2=null;
772 double rsmall,rbig;
773 if (fct>1)
774 {
775 b2=new HealpixBase(fct*nside,Scheme.RING);
776 rsmall = radius+b2.maxPixrad();
777 rbig = radius+maxPixrad();
778 }
779 else
780 rsmall = rbig = inclusive ? radius+maxPixrad() : radius;
781
782 if (rsmall>=Math.PI)
783 { pixset.append(0,npix); return pixset; }
784
785 rbig = Math.min (Math.PI,rbig);
786
787 double cosrsmall = FastMath.cos(rsmall);
788 double cosrbig = FastMath.cos(rbig);
789
790 double z0 = FastMath.cos(ptg.theta);
791 double xa = 1./Math.sqrt((1-z0)*(1+z0));
792
793 Zphi czphi = new Zphi(z0,ptg.phi);
794 long cpix = zphi2pix(czphi);
795
796 double rlat1 = ptg.theta - rsmall;
797 double zmax = FastMath.cos(rlat1);
798 long irmin = ringAbove (zmax)+1;
799
800 if ((rlat1<=0) && (irmin>1)) // north pole in the disk
801 {
802 RingInfoSmall info =get_ring_info_small(irmin-1);
803 pixset.append(0,info.startpix+info.ringpix);
804 }
805
806 if ((fct>1) && (rlat1>0)) irmin=Math.max(1L,irmin-1);
807
808 double rlat2 = ptg.theta + rsmall;
809 double zmin = FastMath.cos(rlat2);
810 long irmax = ringAbove (zmin);
811
812 if ((fct>1) && (rlat2<Math.PI)) irmax=Math.min(nl4-1,irmax+1);
813
814 for (long iz=irmin; iz<=irmax; ++iz) // rings partially in the disk
815 {
816 double z=ring2z(iz);
817
818 double x = (cosrbig-z*z0)*xa;
819 double ysq = 1-z*z-x*x;
820 double dphi=-1;
821 if (ysq<=0) // no intersection, ring completely inside or outside
822 dphi = (fct==1) ? 0: Math.PI-1e-15;
823 else
824 dphi = FastMath.atan2(Math.sqrt(ysq),x);
825 if (dphi>0)
826 {
827 RingInfoSmall info =get_ring_info_small(iz);
828 long ipix1 = info.startpix, nr=info.ringpix, ipix2=ipix1+nr-1;
829 double shift = info.shifted ? 0.5 : 0.;
830
831 long ip_lo = (long)Math.floor
832 (nr*Constants.inv_twopi*(ptg.phi-dphi) - shift)+1;
833 long ip_hi = (long)Math.floor
834 (nr*Constants.inv_twopi*(ptg.phi+dphi) - shift);
835
836 if (fct>1)
837 {
838 while ((ip_lo<=ip_hi) && checkPixelRing
839 (b2,ip_lo,nr,ipix1,fct,czphi,cosrsmall,cpix))
840 ++ip_lo;
841 while ((ip_hi>ip_lo) && checkPixelRing
842 (b2,ip_hi,nr,ipix1,fct,czphi,cosrsmall,cpix))
843 --ip_hi;
844 }
845
846 if (ip_lo<=ip_hi)
847 {
848 if (ip_hi>=nr)
849 { ip_lo-=nr; ip_hi-=nr; }
850 if (ip_lo<0)
851 {
852 pixset.append(ipix1,ipix1+ip_hi+1);
853 pixset.append(ipix1+ip_lo+nr,ipix2+1);
854 }
855 else
856 pixset.append(ipix1+ip_lo,ipix1+ip_hi+1);
857 }
858 }
859 }
860
861 if ((rlat2>=Math.PI) && (irmax+1<nl4)) // south pole in the disk
862 {
863 RingInfoSmall info =get_ring_info_small(irmax+1);
864 pixset.append(info.startpix,npix);
865 }
866 }
867 else // scheme_==NEST
868 {
869 if (radius>=Math.PI) // disk covers the whole sphere
870 { pixset.append(0,npix); return pixset; }
871
872 int oplus=0;
873 if (inclusive)
874 {
875 HealpixUtils.check ((1L<<order_max)>=fact,"invalid oversampling factor");
876 HealpixUtils.check ((fact&(fact-1))==0,
877 "oversampling factor must be a power of 2");
878 oplus=HealpixUtils.ilog2(fact);
879 }
880 int omax=Math.min(order_max,order+oplus); // the order up to which we test
881
882 Vec3 vptg = new Vec3(ptg);
883
884 double[] crpdr = new double[omax+1];
885 double[] crmdr = new double[omax+1];
886
887 double cosrad=FastMath.cos(radius),
888 sinrad=FastMath.sin(radius);
889 for (int o=0; o<=omax; o++) // prepare data at the required orders
890 {
891 double dr = HealpixProc.mpr[o]; // safety distance
892 double cdr = HealpixProc.cmpr[o];
893 double sdr = HealpixProc.smpr[o];
894 crpdr[o] = (radius+dr>Math.PI) ? -1. : cosrad*cdr-sinrad*sdr;
895 crmdr[o] = (radius-dr<0.) ? 1. : cosrad*cdr+sinrad*sdr;
896 }
897
898 pstack stk=new pstack(12+3*omax);
899
900 /* Still experimental, therefore disabled
901 Fxyf fxyf=new Fxyf(vptg);
902 for (int o=order; o>=0; --o)
903 {
904 long nsd=HealpixProc.bn[o].nside;
905 double fx=nsd*fxyf.fx-(int)(nsd*fxyf.fx),
906 fy=nsd*fxyf.fy-(int)(nsd*fxyf.fy);
907 double fmin = Math.min(Math.min(fx,fy),Math.min(1-fx,1-fy));
908 if (fmin*0.7>nsd*radius)
909 {
910 System.out.println("contained completely at order "+o);
911 stk.push(HealpixProc.bn[o].vec2pix(vptg),o);
912 break;
913 }
914 }
915 if (stk.size()==0)
916 */
917
918 for (int i=0; i<12; i++) // insert the 12 base pixels in reverse order
919 stk.push(11-i,0);
920
921 while (stk.size()>0) {// as long as there are pixels on the stack
922 // pop current pixel number and order from the stack
923 long pix=stk.ptop();
924 int o=stk.otop();
925 stk.pop();
926
927 Zphi pos=HealpixProc.bn[o].pix2zphi(pix);
928 // cosine of angular distance between pixel center and disk center
929 double cangdist=HealpixUtils.cosdist_zphi(vptg.z,ptg.phi,pos.z,pos.phi);
930
931 if (cangdist>crpdr[o])
932 {
933 int zone = (cangdist<cosrad) ? 1 : ((cangdist<=crmdr[o]) ? 2 : 3);
934
935 check_pixel (o, omax, zone, pixset, pix, stk, inclusive);
936 }
937 }
938 }
939 return pixset;
940 }
941
942 /** Returns a range set of pixels whose centers lie within a given disk. <p>
943 This method is more efficient in the RING scheme.
944 @param ptg the angular coordinates of the disk center
945 @param radius the radius (in radians) of the disk
946 @return the requested set of pixel number ranges */
947 public RangeSet queryDisc(Pointing ptg, double radius)
948 throws Exception
949 { return queryDiscInternal (ptg, radius, 0); }
950 /** Returns a range set of pixels which overlap with a given disk. <p>
951 This method is more efficient in the RING scheme. <p>
952 This method may return some pixels which don't overlap with
953 the polygon at all. The higher {@code fact} is chosen, the fewer false
954 positives are returned, at the cost of increased run time.
955 @param ptg the angular coordinates of the disk center
956 @param radius the radius (in radians) of the disk
957 @param fact The overlapping test will be done at the resolution
958 {@code fact*nside}. For NESTED ordering, {@code fact} must be a power
959 of 2, else it can be any positive integer. A typical choice would be 4.
960 @return the requested set of pixel number ranges */
961 public RangeSet queryDiscInclusive (Pointing ptg, double radius, int fact)
962 throws Exception
963 { return queryDiscInternal (ptg, radius, fact); }
964
965 private RangeSet queryMultiDisc (Vec3[] norm, double[] rad,
966 int fact) throws Exception
967 {
968 boolean inclusive = (fact!=0);
969 int nv=norm.length;
970 HealpixUtils.check(nv==rad.length,"inconsistent input arrays");
971 RangeSet res = new RangeSet();
972
973 if (scheme==Scheme.RING)
974 {
975 int fct=1;
976 if (inclusive)
977 {
978 HealpixUtils.check (((1L<<order_max)/nside)>=fact,
979 "invalid oversampling factor");
980 fct = fact;
981 }
982 HealpixBase b2=null;
983 double rpsmall,rpbig;
984 if (fct>1)
985 {
986 b2=new HealpixBase(fct*nside,Scheme.RING);
987 rpsmall = b2.maxPixrad();
988 rpbig = maxPixrad();
989 }
990 else
991 rpsmall = rpbig = inclusive ? maxPixrad() : 0;
992
993 long irmin=1, irmax=nl4-1;
994 int nd=0;
995 double[] z0=new double[nv];
996 double[] xa=new double[nv];
997 double[] cosrsmall=new double[nv];
998 double[] cosrbig=new double[nv];
999 Pointing[] ptg=new Pointing[nv];
1000 long[] cpix=new long[nv];
1001 Zphi[] czphi=new Zphi[nv];
1002 for (int i=0; i<nv; ++i)
1003 {
1004 double rsmall=rad[i]+rpsmall;
1005 if (rsmall<Math.PI)
1006 {
1007 double rbig = Math.min(Math.PI,rad[i]+rpbig);
1008 Pointing pnt= new Pointing(norm[i]);
1009 cosrsmall[nd]=FastMath.cos(rsmall);
1010 cosrbig[nd]=FastMath.cos(rbig);
1011 double cth=FastMath.cos(pnt.theta);
1012 z0[nd]=cth;
1013 if (fct>1) cpix[nd]=zphi2pix(new Zphi(cth,pnt.phi));
1014 if (fct>1) czphi[nd]=new Zphi(cth,pnt.phi);
1015 xa[nd]=1./Math.sqrt((1-cth)*(1+cth));
1016 ptg[nd]=pnt;
1017
1018 double rlat1 = pnt.theta - rsmall;
1019 double zmax = FastMath.cos(rlat1);
1020 long irmin_t = (rlat1<=0) ? 1 : ringAbove (zmax)+1;
1021
1022 if ((fct>1) && (rlat1>0)) irmin_t=Math.max(1L,irmin_t-1);
1023
1024 double rlat2 = pnt.theta + rsmall;
1025 double zmin = FastMath.cos(rlat2);
1026 long irmax_t = (rlat2>=Math.PI) ? nl4-1 : ringAbove (zmin);
1027
1028 if ((fct>1) && (rlat2<Math.PI))
1029 irmax_t=Math.min(nl4-1,irmax_t+1);
1030 if (irmax_t < irmax) irmax=irmax_t;
1031 if (irmin_t > irmin) irmin=irmin_t;
1032
1033 ++nd;
1034 }
1035 }
1036
1037 for (long iz=irmin; iz<=irmax; ++iz)
1038 {
1039 double z=ring2z(iz);
1040 RingInfoSmall ris=get_ring_info_small(iz);
1041 long ipix1=ris.startpix, nr=ris.ringpix;
1042 long ipix2 = ipix1 + nr - 1; // highest pixel number in the ring
1043 double shift = ris.shifted ? 0.5 : 0.;
1044 RangeSet rstmp = new RangeSet();
1045 rstmp.append(ipix1,ipix2+1);
1046
1047 for (int j=0; (j<nd)&&(rstmp.nranges()>0); ++j)
1048 {
1049 double x = (cosrbig[j]-z*z0[j])*xa[j];
1050 double ysq = 1.-z*z-x*x;
1051 double dphi = (ysq<=0) ? Math.PI-1e-15 :
1052 FastMath.atan2(Math.sqrt(ysq),x);
1053
1054 long ip_lo = (long)Math.floor
1055 (nr*Constants.inv_twopi*(ptg[j].phi-dphi)-shift)+1;
1056 long ip_hi = (long)Math.floor
1057 (nr*Constants.inv_twopi*(ptg[j].phi+dphi)-shift);
1058
1059 if (fct>1)
1060 {
1061 while ((ip_lo<=ip_hi) && checkPixelRing
1062 (b2,ip_lo,nr,ipix1,fct,czphi[j],cosrsmall[j],cpix[j]))
1063 ++ip_lo;
1064 while ((ip_hi>ip_lo) && checkPixelRing
1065 (b2,ip_hi,nr,ipix1,fct,czphi[j],cosrsmall[j],cpix[j]))
1066 --ip_hi;
1067 }
1068
1069 if (ip_hi>=nr)
1070 { ip_lo-=nr; ip_hi-=nr;}
1071
1072 if (ip_lo<0)
1073 {
1074 if (ip_hi+1<=ip_lo+nr-1)
1075 rstmp.remove(ipix1+ip_hi+1,ipix1+ip_lo+nr);
1076 }
1077 else
1078 rstmp.intersect(ipix1+ip_lo,ipix1+ip_hi+1);
1079 }
1080 res.append(rstmp);
1081 }
1082 }
1083 else // scheme == NEST
1084 {
1085 int oplus = 0;
1086 if (inclusive)
1087 {
1088 HealpixUtils.check ((1L<<(order_max-order))>=fact,
1089 "invalid oversampling factor");
1090 HealpixUtils.check ((fact&(fact-1))==0,
1091 "oversampling factor must be a power of 2");
1092 oplus=HealpixUtils.ilog2(fact);
1093 }
1094 int omax=order+oplus; // the order up to which we test
1095
1096 // TODO: ignore all disks with radius>=pi
1097
1098 double[][][] crlimit=new double[omax+1][nv][3];
1099 for (int o=0; o<=omax; ++o) // prepare data at the required orders
1100 {
1101 double dr=HealpixProc.bn[o].maxPixrad(); // safety distance
1102 for (int i=0; i<nv; ++i)
1103 {
1104 crlimit[o][i][0] = (rad[i]+dr>Math.PI) ? -1: FastMath.cos(rad[i]+dr);
1105 crlimit[o][i][1] = (o==0) ? FastMath.cos(rad[i]) : crlimit[0][i][1];
1106 crlimit[o][i][2] = (rad[i]-dr<0.) ? 1. : FastMath.cos(rad[i]-dr);
1107 }
1108 }
1109
1110 pstack stk=new pstack(12+3*omax);
1111 for (int i=0; i<12; i++) // insert the 12 base pixels in reverse order
1112 stk.push(11-i,0);
1113
1114 while (stk.size()>0) { // as long as there are pixels on the stack
1115 // pop current pixel number and order from the stack
1116 long pix=stk.ptop();
1117 int o=stk.otop();
1118 stk.pop();
1119
1120 Vec3 pv = HealpixProc.bn[o].pix2vec(pix);
1121
1122 int zone=3;
1123 for (int i=0; (i<nv)&&(zone>0); ++i)
1124 {
1125 double crad=pv.dot(norm[i]);
1126 for (int iz=0; iz<zone; ++iz)
1127 if (crad<crlimit[o][i][iz])
1128 zone=iz;
1129 }
1130
1131 if (zone>0) check_pixel (o, omax, zone, res, pix, stk, inclusive);
1132 }
1133 }
1134 return res;
1135 }
1136
1137 private RangeSet queryPolygonInternal (Pointing[] vertex, int fact)
1138 throws Exception
1139 {
1140 boolean inclusive = (fact!=0);
1141 int nv=vertex.length;
1142 int ncirc = inclusive ? nv+1 : nv;
1143 HealpixUtils.check(nv>=3,"not enough vertices in polygon");
1144 Vec3[] vv = new Vec3[nv];
1145 for (int i=0; i<nv; ++i)
1146 vv[i] = new Vec3(vertex[i]);
1147 Vec3[] normal = new Vec3[ncirc];
1148 int flip=0;
1149 for (int i=0; i<nv; ++i)
1150 {
1151 normal[i]=vv[i].cross(vv[(i+1)%nv]).norm();
1152 double hnd=normal[i].dot(vv[(i+2)%nv]);
1153 HealpixUtils.check(Math.abs(hnd)>1e-10,"degenerate corner");
1154 if (i==0)
1155 flip = (hnd<0.) ? -1 : 1;
1156 else
1157 HealpixUtils.check(flip*hnd>0,"polygon is not convex");
1158 normal[i].scale(flip);
1159 }
1160 double[] rad = new double[ncirc];
1161 Arrays.fill(rad,Constants.halfpi);
1162 if (inclusive)
1163 {
1164 CircleFinder cf = new CircleFinder(vv);
1165 normal[nv]=cf.getCenter();
1166 rad[nv]=FastMath.acos(cf.getCosrad());
1167 }
1168 return queryMultiDisc(normal,rad,fact);
1169 }
1170 /** Returns a range set of pixels whose centers lie within the convex
1171 polygon defined by the {@code vertex} array. <p>
1172 This method is more efficient in the RING scheme.
1173 @param vertex an array containing the vertices of the requested convex
1174 polygon.
1175 @return the requested set of pixel number ranges */
1176 public RangeSet queryPolygon (Pointing[] vertex) throws Exception
1177 { return queryPolygonInternal (vertex, 0); }
1178 /** Returns a range set of pixels that overlap with the convex
1179 polygon defined by the {@code vertex} array. <p>
1180 This method is more efficient in the RING scheme.<p>
1181 This method may return some pixels which don't overlap with
1182 the polygon at all. The higher {@code fact} is chosen, the fewer false
1183 positives are returned, at the cost of increased run time.
1184 @param vertex an array containing the vertices of the requested convex
1185 polygon.
1186 @param fact The overlapping test will be done at the resolution
1187 {@code fact*nside}. For NESTED ordering, {@code fact} must be a power
1188 of 2, else it can be any positive integer. A typical choice would be 4.
1189 @return the requested set of pixel number ranges */
1190 public RangeSet queryPolygonInclusive (Pointing[] vertex, int fact)
1191 throws Exception
1192 { return queryPolygonInternal (vertex, fact); }
1193
1194 private void check_pixel (int o, int omax, int zone,
1195 RangeSet pixset, long pix, pstack stk, boolean inclusive)
1196 {
1197 if (zone==0) return;
1198
1199 if (o<order)
1200 {
1201 if (zone>=3) // output all subpixels
1202 {
1203 int sdist=2*(order-o); // the "bit-shift distance" between map orders
1204 pixset.append(pix<<sdist,((pix+1)<<sdist));
1205 }
1206 else // (zone>=1)
1207 for (int i=0; i<4; ++i)
1208 stk.push(4*pix+3-i,o+1); // add children
1209 }
1210 else if (o>order) // this implies that inclusive==true
1211 {
1212 if (zone>=2) // pixel center in shape
1213 {
1214 pixset.append(pix>>>(2*(o-order))); // output the parent pixel at order
1215 stk.popToMark(); // unwind the stack
1216 }
1217 else // (zone>=1): pixel center in safety range
1218 {
1219 if (o<omax) // check sublevels
1220 for (int i=0; i<4; ++i) // add children in reverse order
1221 stk.push(4*pix+3-i,o+1); // add children
1222 else // at resolution limit
1223 {
1224 pixset.append(pix>>>(2*(o-order)));// output the parent pixel at order
1225 stk.popToMark(); // unwind the stack
1226 }
1227 }
1228 }
1229 else // o==order
1230 {
1231 if (zone>=2)
1232 pixset.append(pix);
1233 else if (inclusive) // and (zone>=1)
1234 {
1235 if (order<omax) // check sublevels
1236 {
1237 stk.mark(); // remember current stack position
1238 for (int i=0; i<4; ++i) // add children in reverse order
1239 stk.push(4*pix+3-i,o+1); // add children
1240 }
1241 else // at resolution limit
1242 pixset.append(pix); // output the pixel
1243 }
1244 }
1245 }
1246
1247 /** Compute ring index from pixel number.
1248 Works in both RING and NESTED schemes
1249 @param pix pixel number
1250 @return ring index (1 to 4Nside-1) */
1251 public long pix2ring (long pix)
1252 {
1253 if (scheme==Scheme.RING)
1254 {
1255 if (pix<ncap) // North Polar cap
1256 return (1+HealpixUtils.isqrt(1+2*pix))>>>1; // counted from North pole
1257 else if (pix<(npix-ncap)) // Equatorial region
1258 return (pix-ncap)/nl4 + nside; // counted from North pole
1259 else // South Polar cap
1260 return nl4-((1+HealpixUtils.isqrt(2*(npix-pix)-1))>>>1);
1261 }
1262 else
1263 {
1264 Xyf xyf = nest2xyf(pix);
1265 return ((long)(jrll[xyf.face])<<order) - xyf.ix - xyf.iy - 1;
1266 }
1267 }
1268
1269 /** Returns a set of points along the boundary of the given pixel.
1270 * Step 1 gives 4 points on the corners. The first point corresponds
1271 * to the northernmost corner, the subsequent points follow the pixel
1272 * boundary through west, south and east corners.
1273 *
1274 * @param pix pixel index number
1275 * @param step the number of returned points is 4*step
1276 * @return {@link Vec3} for each point
1277 * @throws Exception
1278 */
1279 public Vec3[] boundaries(long pix, int step) throws Exception
1280 {
1281 HealpixUtils.check(step>0,"step must be positive");
1282 Vec3[] points = new Vec3[4*step];
1283 Xyf xyf = pix2xyf(pix);
1284 double dc=0.5/nside;
1285 double xc=(xyf.ix+0.5)/nside, yc=(xyf.iy+0.5)/nside;
1286 double d = 1./(step*nside);
1287 for (int i=0; i<step; ++i)
1288 {
1289 points[i ]=new Fxyf(xc+dc-i*d, yc+dc, xyf.face).toVec3();
1290 points[i+ step]=new Fxyf(xc-dc, yc+dc-i*d, xyf.face).toVec3();
1291 points[i+2*step]=new Fxyf(xc-dc+i*d, yc-dc, xyf.face).toVec3();
1292 points[i+3*step]=new Fxyf(xc+dc, yc-dc+i*d, xyf.face).toVec3();
1293 }
1294 return points;
1295 }
1296 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 import java.util.Arrays;
23
24 /** Class representing a full HEALPix map containing <type> values.
25 This class is conceptually very similar the the Healpix_Map&lt;<type>&gt;
26 class of Healpix_cxx.
27
28 @copyright 2011,2012 Max-Planck-Society
29 @author Martin Reinecke */
30 public class HealpixMap<Type> extends HealpixBase
31 {
32 private <type>[] data;
33
34 public static final <type> undef=(<type>)(-1.6375e30);
35
36 public HealpixMap<Type>() throws Exception
37 { this(1,Scheme.NESTED); }
38 public HealpixMap<Type>(long nside_in, Scheme scheme_in) throws Exception
39 {
40 super(nside_in,scheme_in);
41 HealpixUtils.check(nside<=(1<<13),"resolution too high");
42 data=new <type>[(int)getNpix()];
43 }
44 public HealpixMap<Type>(<type>[] data_in, Scheme scheme_in) throws Exception
45 {
46 super(npix2Nside(data_in.length),scheme_in);
47 HealpixUtils.check(nside<=(1<<13),"resolution too high");
48 data=data_in;
49 }
50
51 /** Adjusts the object to nside_in.
52 @param nside_in the new Nside parameter */
53 public void setNside (long nside_in) throws Exception
54 {
55 if (nside_in!=nside)
56 {
57 super.setNside(nside_in);
58 HealpixUtils.check(nside<=(1<<13),"resolution too high");
59 data=new <type>[(int)getNpix()];
60 }
61 }
62
63 /** Adjusts the object to nside_in and scheme_in.
64 @param nside_in the new Nside parameter
65 @param scheme_in the new ordering scheme */
66 public void setNsideAndScheme (long nside_in, Scheme scheme_in)
67 throws Exception
68 {
69 super.setNsideAndScheme(nside_in,scheme_in);
70 HealpixUtils.check(nside<=(1<<13),"resolution too high");
71 data=new <type>[(int)getNpix()];
72 }
73
74 /** Adjusts the object to scheme_in, and sets pixel data to data_in.
75 @param data_in pixel data; must have a valid length (12*nside^2)
76 @param scheme_in the new ordering scheme */
77 public void setDataAndScheme(<type>[] data_in, Scheme scheme_in)
78 throws Exception
79 {
80 super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
81 data=data_in;
82 }
83
84 /** Sets all map pixel to a specific value.
85 @param val pixel value to use */
86 public void fill(<type> val)
87 { Arrays.fill(data,val); }
88
89 /** Converts the map from NESTED to RING scheme or vice versa.
90 This operation is done in-place, i.e. it does not require additional
91 memory. */
92 public void swapScheme() throws Exception
93 {
94 HealpixUtils.check((order>=0) && (order<=13),
95 "swapping not supported for this Nside");
96 for (int m=0; m<swap_cycle[order].length; ++m)
97 {
98 int istart = swap_cycle[order][m];
99
100 <type> pixbuf = data[istart];
101 long iold = istart,
102 inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
103 while (inew != istart)
104 {
105 data[(int)iold] = data[(int)inew];
106 iold = inew;
107 inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
108 }
109 data[(int)iold] = pixbuf;
110 }
111 scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
112 }
113
114 /** Returns the value of the pixel with a given index.
115 @param ipix index of the requested pixel
116 @return pixel value */
117 public <type> getPixel(int ipix)
118 { return data[ipix]; }
119 /** Returns the value of the pixel with a given index.
120 @param ipix index of the requested pixel
121 @return pixel value */
122 public <type> getPixel(long ipix)
123 { return data[(int)ipix]; }
124 /** Sets the value of a specific pixel.
125 @param ipix index of the pixel
126 @param val new value for the pixel */
127 public void setPixel(int ipix, <type> val)
128 { data[ipix] = val; }
129 /** Sets the value of a specific pixel.
130 @param ipix index of the pixel
131 @param val new value for the pixel */
132 public void setPixel(long ipix, <type> val)
133 { data[(int)ipix] = val; }
134
135 /** Returns the array containing all map pixels.
136 @return the map array */
137 public <type>[] getData()
138 { return data; }
139
140 /** Imports the map "orig" to this object, adjusting pixel ordering.
141 @param orig map to import */
142 public void importNograde (HealpixMap<Type> orig) throws Exception
143 {
144 HealpixUtils.check (nside==orig.nside,
145 "importNograde: maps have different nside");
146 if (orig.scheme == scheme)
147 System.arraycopy(orig.data,0,data,0,(int)npix);
148 else
149 for (int m=0; m<npix; ++m)
150 data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
151 = orig.data[m];
152 }
153 /** Imports the map "orig" to this object, adjusting pixel ordering
154 and increasing resolution.
155 @param orig map to import */
156 public void importUpgrade (HealpixMap<Type> orig) throws Exception
157 {
158 HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
159 int fact = (int)(nside/orig.nside);
160 HealpixUtils.check(nside==orig.nside*fact,
161 "the larger Nside must be a multiple of the smaller one");
162
163 for (int m=0; m<orig.npix; ++m)
164 {
165 Xyf xyf = orig.pix2xyf(m);
166 int x=xyf.ix, y=xyf.iy, f=xyf.face;
167 for (int j=fact*y; j<fact*(y+1); ++j)
168 for (int i=fact*x; i<fact*(x+1); ++i)
169 {
170 long mypix = xyf2pix(i,j,f);
171 data[(int)mypix] = orig.data[m];
172 }
173 }
174 }
175 /** Imports the map "orig" to this object, adjusting pixel ordering
176 and reducing resolution.
177 @param orig map to import
178 @param pessimistic if true, set a pixel to undefined if at least one the
179 original subpixels was undefined; otherwise only set it to undefined if
180 all original subpixels were undefined. */
181 public void importDegrade (HealpixMap<Type> orig, boolean pessimistic)
182 throws Exception
183 {
184 HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
185 int fact = (int)(orig.nside/nside);
186 HealpixUtils.check(orig.nside==nside*fact,
187 "the larger Nside must be a multiple of the smaller one");
188
189 int minhits = pessimistic ? fact*fact : 1;
190 for (int m=0; m<npix; ++m)
191 {
192 Xyf xyf = pix2xyf(m);
193 int x=xyf.ix, y=xyf.iy, f=xyf.face;
194 int hits = 0;
195 double sum = 0;
196 for (int j=fact*y; j<fact*(y+1); ++j)
197 for (int i=fact*x; i<fact*(x+1); ++i)
198 {
199 int opix = (int)orig.xyf2pix(i,j,f);
200 if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
201 {
202 ++hits;
203 sum += orig.data[opix];
204 }
205 }
206 data[m] = (hits<minhits) ? undef : (<type>) (sum/hits);
207 }
208 }
209 /** Imports the map "orig" to this object, adjusting pixel ordering
210 and resolution if necessary.
211 @param orig map to import
212 @param pessimistic only used when resolution must be reduced: if true,
213 set a pixel to undefined if at least one the original subpixels
214 was undefined; otherwise only set it to undefined if all original
215 subpixels were undefined. */
216 public void importGeneral (HealpixMap<Type> orig, boolean pessimistic)
217 throws Exception
218 {
219 if (orig.nside==nside)
220 importNograde(orig);
221 else if (orig.nside<nside) // upgrading
222 importUpgrade(orig);
223 else
224 importDegrade(orig,pessimistic);
225 }
226 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 import java.util.Arrays;
23
24 /** Class representing a full HEALPix map containing double values.
25 This class is conceptually very similar the the Healpix_Map&lt;double&gt;
26 class of Healpix_cxx.
27
28 @copyright 2011,2012 Max-Planck-Society
29 @author Martin Reinecke */
30 public class HealpixMapDouble extends HealpixBase
31 {
32 private double[] data;
33
34 public static final double undef=-1.6375e30;
35
36 public HealpixMapDouble() throws Exception
37 { this(1,Scheme.NESTED); }
38 public HealpixMapDouble(long nside_in, Scheme scheme_in) throws Exception
39 {
40 super(nside_in,scheme_in);
41 HealpixUtils.check(nside<=(1<<13),"resolution too high");
42 data=new double[(int)getNpix()];
43 }
44 public HealpixMapDouble(double[] data_in, Scheme scheme_in) throws Exception
45 {
46 super(npix2Nside(data_in.length),scheme_in);
47 HealpixUtils.check(nside<=(1<<13),"resolution too high");
48 data=data_in;
49 }
50
51 /** Adjusts the object to nside_in.
52 @param nside_in the new Nside parameter */
53 public void setNside (long nside_in) throws Exception
54 {
55 if (nside_in!=nside)
56 {
57 super.setNside(nside_in);
58 HealpixUtils.check(nside<=(1<<13),"resolution too high");
59 data=new double[(int)getNpix()];
60 }
61 }
62
63 /** Adjusts the object to nside_in and scheme_in.
64 @param nside_in the new Nside parameter
65 @param scheme_in the new ordering scheme */
66 public void setNsideAndScheme (long nside_in, Scheme scheme_in)
67 throws Exception
68 {
69 super.setNsideAndScheme(nside_in,scheme_in);
70 HealpixUtils.check(nside<=(1<<13),"resolution too high");
71 data=new double[(int)getNpix()];
72 }
73
74 /** Adjusts the object to scheme_in, and sets pixel data to data_in.
75 @param data_in pixel data; must have a valid length (12*nside^2)
76 @param scheme_in the new ordering scheme */
77 public void setDataAndScheme(double[] data_in, Scheme scheme_in)
78 throws Exception
79 {
80 super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
81 data=data_in;
82 }
83
84 /** Sets all map pixel to a specific value.
85 @param val pixel value to use */
86 public void fill(double val)
87 { Arrays.fill(data,val); }
88
89 /** Converts the map from NESTED to RING scheme or vice versa.
90 This operation is done in-place, i.e. it does not require additional
91 memory. */
92 public void swapScheme() throws Exception
93 {
94 HealpixUtils.check((order>=0) && (order<=13),
95 "swapping not supported for this Nside");
96 for (int m=0; m<swap_cycle[order].length; ++m)
97 {
98 int istart = swap_cycle[order][m];
99
100 double pixbuf = data[istart];
101 long iold = istart,
102 inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
103 while (inew != istart)
104 {
105 data[(int)iold] = data[(int)inew];
106 iold = inew;
107 inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
108 }
109 data[(int)iold] = pixbuf;
110 }
111 scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
112 }
113
114 /** Returns the value of the pixel with a given index.
115 @param ipix index of the requested pixel
116 @return pixel value */
117 public double getPixel(int ipix)
118 { return data[ipix]; }
119 /** Returns the value of the pixel with a given index.
120 @param ipix index of the requested pixel
121 @return pixel value */
122 public double getPixel(long ipix)
123 { return data[(int)ipix]; }
124 /** Sets the value of a specific pixel.
125 @param ipix index of the pixel
126 @param val new value for the pixel */
127 public void setPixel(int ipix, double val)
128 { data[ipix] = val; }
129 /** Sets the value of a specific pixel.
130 @param ipix index of the pixel
131 @param val new value for the pixel */
132 public void setPixel(long ipix, double val)
133 { data[(int)ipix] = val; }
134
135 /** Returns the array containing all map pixels.
136 @return the map array */
137 public double[] getData()
138 { return data; }
139
140 /** Imports the map "orig" to this object, adjusting pixel ordering.
141 @param orig map to import */
142 public void importNograde (HealpixMapDouble orig) throws Exception
143 {
144 HealpixUtils.check (nside==orig.nside,
145 "importNograde: maps have different nside");
146 if (orig.scheme == scheme)
147 System.arraycopy(orig.data,0,data,0,(int)npix);
148 else
149 for (int m=0; m<npix; ++m)
150 data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
151 = orig.data[m];
152 }
153 /** Imports the map "orig" to this object, adjusting pixel ordering
154 and increasing resolution.
155 @param orig map to import */
156 public void importUpgrade (HealpixMapDouble orig) throws Exception
157 {
158 HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
159 int fact = (int)(nside/orig.nside);
160 HealpixUtils.check(nside==orig.nside*fact,
161 "the larger Nside must be a multiple of the smaller one");
162
163 for (int m=0; m<orig.npix; ++m)
164 {
165 Xyf xyf = orig.pix2xyf(m);
166 int x=xyf.ix, y=xyf.iy, f=xyf.face;
167 for (int j=fact*y; j<fact*(y+1); ++j)
168 for (int i=fact*x; i<fact*(x+1); ++i)
169 {
170 long mypix = xyf2pix(i,j,f);
171 data[(int)mypix] = orig.data[m];
172 }
173 }
174 }
175 /** Imports the map "orig" to this object, adjusting pixel ordering
176 and reducing resolution.
177 @param orig map to import
178 @param pessimistic if true, set a pixel to undefined if at least one the
179 original subpixels was undefined; otherwise only set it to undefined if
180 all original subpixels were undefined. */
181 public void importDegrade (HealpixMapDouble orig, boolean pessimistic)
182 throws Exception
183 {
184 HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
185 int fact = (int)(orig.nside/nside);
186 HealpixUtils.check(orig.nside==nside*fact,
187 "the larger Nside must be a multiple of the smaller one");
188
189 int minhits = pessimistic ? fact*fact : 1;
190 for (int m=0; m<npix; ++m)
191 {
192 Xyf xyf = pix2xyf(m);
193 int x=xyf.ix, y=xyf.iy, f=xyf.face;
194 int hits = 0;
195 double sum = 0;
196 for (int j=fact*y; j<fact*(y+1); ++j)
197 for (int i=fact*x; i<fact*(x+1); ++i)
198 {
199 int opix = (int)orig.xyf2pix(i,j,f);
200 if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
201 {
202 ++hits;
203 sum += orig.data[opix];
204 }
205 }
206 data[m] = (hits<minhits) ? undef : (sum/hits);
207 }
208 }
209 /** Imports the map "orig" to this object, adjusting pixel ordering
210 and resolution if necessary.
211 @param orig map to import
212 @param pessimistic only used when resolution must be reduced: if true,
213 set a pixel to undefined if at least one the original subpixels
214 was undefined; otherwise only set it to undefined if all original
215 subpixels were undefined. */
216 public void importGeneral (HealpixMapDouble orig, boolean pessimistic)
217 throws Exception
218 {
219 if (orig.nside==nside)
220 importNograde(orig);
221 else if (orig.nside<nside) // upgrading
222 importUpgrade(orig);
223 else
224 importDegrade(orig,pessimistic);
225 }
226 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 import java.util.Arrays;
23
24 /** Class representing a full HEALPix map containing float values.
25 This class is conceptually very similar the the Healpix_Map&lt;float&gt;
26 class of Healpix_cxx.
27
28 @copyright 2011,2012 Max-Planck-Society
29 @author Martin Reinecke */
30 public class HealpixMapFloat extends HealpixBase
31 {
32 private float[] data;
33
34 public static final float undef=(float)(-1.6375e30);
35
36 public HealpixMapFloat() throws Exception
37 { this(1,Scheme.NESTED); }
38 public HealpixMapFloat(long nside_in, Scheme scheme_in) throws Exception
39 {
40 super(nside_in,scheme_in);
41 HealpixUtils.check(nside<=(1<<13),"resolution too high");
42 data=new float[(int)getNpix()];
43 }
44 public HealpixMapFloat(float[] data_in, Scheme scheme_in) throws Exception
45 {
46 super(npix2Nside(data_in.length),scheme_in);
47 HealpixUtils.check(nside<=(1<<13),"resolution too high");
48 data=data_in;
49 }
50
51 /** Adjusts the object to nside_in.
52 @param nside_in the new Nside parameter */
53 public void setNside (long nside_in) throws Exception
54 {
55 if (nside_in!=nside)
56 {
57 super.setNside(nside_in);
58 HealpixUtils.check(nside<=(1<<13),"resolution too high");
59 data=new float[(int)getNpix()];
60 }
61 }
62
63 /** Adjusts the object to nside_in and scheme_in.
64 @param nside_in the new Nside parameter
65 @param scheme_in the new ordering scheme */
66 public void setNsideAndScheme (long nside_in, Scheme scheme_in)
67 throws Exception
68 {
69 super.setNsideAndScheme(nside_in,scheme_in);
70 HealpixUtils.check(nside<=(1<<13),"resolution too high");
71 data=new float[(int)getNpix()];
72 }
73
74 /** Adjusts the object to scheme_in, and sets pixel data to data_in.
75 @param data_in pixel data; must have a valid length (12*nside^2)
76 @param scheme_in the new ordering scheme */
77 public void setDataAndScheme(float[] data_in, Scheme scheme_in)
78 throws Exception
79 {
80 super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
81 data=data_in;
82 }
83
84 /** Sets all map pixel to a specific value.
85 @param val pixel value to use */
86 public void fill(float val)
87 { Arrays.fill(data,val); }
88
89 /** Converts the map from NESTED to RING scheme or vice versa.
90 This operation is done in-place, i.e. it does not require additional
91 memory. */
92 public void swapScheme() throws Exception
93 {
94 HealpixUtils.check((order>=0) && (order<=13),
95 "swapping not supported for this Nside");
96 for (int m=0; m<swap_cycle[order].length; ++m)
97 {
98 int istart = swap_cycle[order][m];
99
100 float pixbuf = data[istart];
101 long iold = istart,
102 inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
103 while (inew != istart)
104 {
105 data[(int)iold] = data[(int)inew];
106 iold = inew;
107 inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
108 }
109 data[(int)iold] = pixbuf;
110 }
111 scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
112 }
113
114 /** Returns the value of the pixel with a given index.
115 @param ipix index of the requested pixel
116 @return pixel value */
117 public float getPixel(int ipix)
118 { return data[ipix]; }
119 /** Returns the value of the pixel with a given index.
120 @param ipix index of the requested pixel
121 @return pixel value */
122 public float getPixel(long ipix)
123 { return data[(int)ipix]; }
124 /** Sets the value of a specific pixel.
125 @param ipix index of the pixel
126 @param val new value for the pixel */
127 public void setPixel(int ipix, float val)
128 { data[ipix] = val; }
129 /** Sets the value of a specific pixel.
130 @param ipix index of the pixel
131 @param val new value for the pixel */
132 public void setPixel(long ipix, float val)
133 { data[(int)ipix] = val; }
134
135 /** Returns the array containing all map pixels.
136 @return the map array */
137 public float[] getData()
138 { return data; }
139
140 /** Imports the map "orig" to this object, adjusting pixel ordering.
141 @param orig map to import */
142 public void importNograde (HealpixMapFloat orig) throws Exception
143 {
144 HealpixUtils.check (nside==orig.nside,
145 "importNograde: maps have different nside");
146 if (orig.scheme == scheme)
147 System.arraycopy(orig.data,0,data,0,(int)npix);
148 else
149 for (int m=0; m<npix; ++m)
150 data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
151 = orig.data[m];
152 }
153 /** Imports the map "orig" to this object, adjusting pixel ordering
154 and increasing resolution.
155 @param orig map to import */
156 public void importUpgrade (HealpixMapFloat orig) throws Exception
157 {
158 HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
159 int fact = (int)(nside/orig.nside);
160 HealpixUtils.check(nside==orig.nside*fact,
161 "the larger Nside must be a multiple of the smaller one");
162
163 for (int m=0; m<orig.npix; ++m)
164 {
165 Xyf xyf = orig.pix2xyf(m);
166 int x=xyf.ix, y=xyf.iy, f=xyf.face;
167 for (int j=fact*y; j<fact*(y+1); ++j)
168 for (int i=fact*x; i<fact*(x+1); ++i)
169 {
170 long mypix = xyf2pix(i,j,f);
171 data[(int)mypix] = orig.data[m];
172 }
173 }
174 }
175 /** Imports the map "orig" to this object, adjusting pixel ordering
176 and reducing resolution.
177 @param orig map to import
178 @param pessimistic if true, set a pixel to undefined if at least one the
179 original subpixels was undefined; otherwise only set it to undefined if
180 all original subpixels were undefined. */
181 public void importDegrade (HealpixMapFloat orig, boolean pessimistic)
182 throws Exception
183 {
184 HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
185 int fact = (int)(orig.nside/nside);
186 HealpixUtils.check(orig.nside==nside*fact,
187 "the larger Nside must be a multiple of the smaller one");
188
189 int minhits = pessimistic ? fact*fact : 1;
190 for (int m=0; m<npix; ++m)
191 {
192 Xyf xyf = pix2xyf(m);
193 int x=xyf.ix, y=xyf.iy, f=xyf.face;
194 int hits = 0;
195 double sum = 0;
196 for (int j=fact*y; j<fact*(y+1); ++j)
197 for (int i=fact*x; i<fact*(x+1); ++i)
198 {
199 int opix = (int)orig.xyf2pix(i,j,f);
200 if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
201 {
202 ++hits;
203 sum += orig.data[opix];
204 }
205 }
206 data[m] = (hits<minhits) ? undef : (float) (sum/hits);
207 }
208 }
209 /** Imports the map "orig" to this object, adjusting pixel ordering
210 and resolution if necessary.
211 @param orig map to import
212 @param pessimistic only used when resolution must be reduced: if true,
213 set a pixel to undefined if at least one the original subpixels
214 was undefined; otherwise only set it to undefined if all original
215 subpixels were undefined. */
216 public void importGeneral (HealpixMapFloat orig, boolean pessimistic)
217 throws Exception
218 {
219 if (orig.nside==nside)
220 importNograde(orig);
221 else if (orig.nside<nside) // upgrading
222 importUpgrade(orig);
223 else
224 importDegrade(orig,pessimistic);
225 }
226 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Procedural interface to the {@link HealpixBase} functionality.
23 This class is intended for users who prefer a procedural (instead of
24 object-oriented) interface to the HEALPix functionality. It should make
25 transition from packages like PixTools easier.
26
27 @copyright 2012 Max-Planck-Society
28 @author Martin Reinecke */
29 public abstract class HealpixProc extends HealpixBase
30 {
31 static final HealpixBase[] bn=new HealpixBase[HealpixBase.order_max+1],
32 br=new HealpixBase[HealpixBase.order_max+1];
33 static final double[] mpr =new double[HealpixBase.order_max+1],
34 cmpr=new double[HealpixBase.order_max+1],
35 smpr=new double[HealpixBase.order_max+1];
36
37 static
38 {
39 try {
40 for (int i=0; i<=HealpixBase.order_max; ++i)
41 {
42 bn[i]=new HealpixBase(1L<<i, Scheme.NESTED);
43 br[i]=new HealpixBase(1L<<i, Scheme.RING);
44 mpr[i]=bn[i].maxPixrad();
45 cmpr[i]=FastMath.cos(mpr[i]);
46 smpr[i]=FastMath.sin(mpr[i]);
47 }
48 }
49 catch (Exception Ex) {/*doesn't happen*/}
50 }
51
52 private HealpixProc() {} // this class should not be instantiated
53
54 public static double maxPixrad (int order)
55 { return bn[order].maxPixrad(); }
56
57 public static long ang2pixNest (int order, Pointing ptg) throws Exception
58 { return bn[order].ang2pix(ptg); }
59 public static long ang2pixRing (int order, Pointing ptg) throws Exception
60 { return br[order].ang2pix(ptg); }
61
62 public static Pointing pix2angNest (int order, long pix) throws Exception
63 { return bn[order].pix2ang(pix); }
64 public static Pointing pix2angRing (int order, long pix) throws Exception
65 { return br[order].pix2ang(pix); }
66
67 public static long vec2pixNest (int order, Vec3 vec) throws Exception
68 { return bn[order].vec2pix(vec); }
69 public static long vec2pixRing (int order, Vec3 vec) throws Exception
70 { return br[order].vec2pix(vec); }
71
72 public static Vec3 pix2vecNest (int order, long pix) throws Exception
73 { return bn[order].pix2vec(pix); }
74 public static Vec3 pix2vecRing (int order, long pix) throws Exception
75 { return br[order].pix2vec(pix); }
76
77 public static long ring2nest (int order, long pix) throws Exception
78 { return bn[order].ring2nest(pix); }
79 public static long nest2ring (int order, long pix) throws Exception
80 { return bn[order].nest2ring(pix); }
81
82 public static long[] neighboursNest (int order, long pix) throws Exception
83 { return bn[order].neighbours(pix); }
84 public static long[] neighboursRing (int order, long pix) throws Exception
85 { return br[order].neighbours(pix); }
86
87 public static Vec3[] boundariesNest(int order, long pix, int step)
88 throws Exception
89 { return bn[order].boundaries(pix,step); }
90 public static Vec3[] boundariesRing(int order, long pix, int step)
91 throws Exception
92 { return br[order].boundaries(pix,step); }
93
94 public static RangeSet queryDiscNest(int order, Pointing ptg, double radius)
95 throws Exception
96 { return bn[order].queryDisc(ptg,radius); }
97 public static RangeSet queryDiscRing(int order, Pointing ptg, double radius)
98 throws Exception
99 { return br[order].queryDisc(ptg,radius); }
100 public static RangeSet queryDiscInclusiveNest(int order, Pointing ptg,
101 double radius, int fact) throws Exception
102 { return bn[order].queryDiscInclusive(ptg,radius,fact); }
103 public static RangeSet queryDiscInclusiveRing(int order, Pointing ptg,
104 double radius, int fact) throws Exception
105 { return br[order].queryDiscInclusive(ptg,radius,fact); }
106
107 public static RangeSet queryPolygonNest(int order, Pointing[] vertex)
108 throws Exception
109 { return bn[order].queryPolygon(vertex); }
110 public static RangeSet queryPolygonRing(int order, Pointing[] vertex)
111 throws Exception
112 { return br[order].queryPolygon(vertex); }
113 public static RangeSet queryPolygonInclusiveNest(int order, Pointing[] vertex,
114 int fact) throws Exception
115 { return bn[order].queryPolygonInclusive(vertex,fact); }
116 public static RangeSet queryPolygonInclusiveRing(int order, Pointing[] vertex,
117 int fact) throws Exception
118 { return br[order].queryPolygonInclusive(vertex,fact); }
119
120 public static RangeSet queryStripNest(int order, double theta1, double theta2,
121 boolean inclusive) throws Exception
122 { return bn[order].queryStrip(theta1,theta2,inclusive); }
123 public static RangeSet queryStripRing(int order, double theta1, double theta2,
124 boolean inclusive) throws Exception
125 { return br[order].queryStrip(theta1,theta2,inclusive); }
126 };
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Various data tables needed by the {@link HealpixBase} class.
23
24 @copyright 2011, 2012 Max-Planck-Society
25 @author Martin Reinecke */
26 public class HealpixTables
27 {
28 static final protected short[] ctab={
29 0,1,256,257,2,3,258,259,512,513,768,769,514,515,770,771,4,5,260,261,6,7,262,
30 263,516,517,772,773,518,519,774,775,1024,1025,1280,1281,1026,1027,1282,1283,
31 1536,1537,1792,1793,1538,1539,1794,1795,1028,1029,1284,1285,1030,1031,1286,
32 1287,1540,1541,1796,1797,1542,1543,1798,1799,8,9,264,265,10,11,266,267,520,
33 521,776,777,522,523,778,779,12,13,268,269,14,15,270,271,524,525,780,781,526,
34 527,782,783,1032,1033,1288,1289,1034,1035,1290,1291,1544,1545,1800,1801,1546,
35 1547,1802,1803,1036,1037,1292,1293,1038,1039,1294,1295,1548,1549,1804,1805,
36 1550,1551,1806,1807,2048,2049,2304,2305,2050,2051,2306,2307,2560,2561,2816,
37 2817,2562,2563,2818,2819,2052,2053,2308,2309,2054,2055,2310,2311,2564,2565,
38 2820,2821,2566,2567,2822,2823,3072,3073,3328,3329,3074,3075,3330,3331,3584,
39 3585,3840,3841,3586,3587,3842,3843,3076,3077,3332,3333,3078,3079,3334,3335,
40 3588,3589,3844,3845,3590,3591,3846,3847,2056,2057,2312,2313,2058,2059,2314,
41 2315,2568,2569,2824,2825,2570,2571,2826,2827,2060,2061,2316,2317,2062,2063,
42 2318,2319,2572,2573,2828,2829,2574,2575,2830,2831,3080,3081,3336,3337,3082,
43 3083,3338,3339,3592,3593,3848,3849,3594,3595,3850,3851,3084,3085,3340,3341,
44 3086,3087,3342,3343,3596,3597,3852,3853,3598,3599,3854,3855 };
45 static final protected short[] utab={
46 0,1,4,5,16,17,20,21,64,65,68,69,80,81,84,85,256,257,260,261,272,273,276,277,
47 320,321,324,325,336,337,340,341,1024,1025,1028,1029,1040,1041,1044,1045,1088,
48 1089,1092,1093,1104,1105,1108,1109,1280,1281,1284,1285,1296,1297,1300,1301,
49 1344,1345,1348,1349,1360,1361,1364,1365,4096,4097,4100,4101,4112,4113,4116,
50 4117,4160,4161,4164,4165,4176,4177,4180,4181,4352,4353,4356,4357,4368,4369,
51 4372,4373,4416,4417,4420,4421,4432,4433,4436,4437,5120,5121,5124,5125,5136,
52 5137,5140,5141,5184,5185,5188,5189,5200,5201,5204,5205,5376,5377,5380,5381,
53 5392,5393,5396,5397,5440,5441,5444,5445,5456,5457,5460,5461,16384,16385,16388,
54 16389,16400,16401,16404,16405,16448,16449,16452,16453,16464,16465,16468,16469,
55 16640,16641,16644,16645,16656,16657,16660,16661,16704,16705,16708,16709,16720,
56 16721,16724,16725,17408,17409,17412,17413,17424,17425,17428,17429,17472,17473,
57 17476,17477,17488,17489,17492,17493,17664,17665,17668,17669,17680,17681,17684,
58 17685,17728,17729,17732,17733,17744,17745,17748,17749,20480,20481,20484,20485,
59 20496,20497,20500,20501,20544,20545,20548,20549,20560,20561,20564,20565,20736,
60 20737,20740,20741,20752,20753,20756,20757,20800,20801,20804,20805,20816,20817,
61 20820,20821,21504,21505,21508,21509,21520,21521,21524,21525,21568,21569,21572,
62 21573,21584,21585,21588,21589,21760,21761,21764,21765,21776,21777,21780,21781,
63 21824,21825,21828,21829,21840,21841,21844,21845 };
64
65 // coordinate of the lowest corner of each face
66 static final protected byte[] jrll = { 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
67 static final protected byte[] jpll = { 1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7 };
68
69 static final protected short[] xoffset = { -1,-1, 0, 1, 1, 1, 0,-1 };
70 static final protected short[] yoffset = { 0, 1, 1, 1, 0,-1,-1,-1 };
71 static final protected short[][] facearray =
72 { { 8, 9,10,11,-1,-1,-1,-1,10,11, 8, 9 }, // S
73 { 5, 6, 7, 4, 8, 9,10,11, 9,10,11, 8 }, // SE
74 { -1,-1,-1,-1, 5, 6, 7, 4,-1,-1,-1,-1 }, // E
75 { 4, 5, 6, 7,11, 8, 9,10,11, 8, 9,10 }, // SW
76 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 }, // center
77 { 1, 2, 3, 0, 0, 1, 2, 3, 5, 6, 7, 4 }, // NE
78 { -1,-1,-1,-1, 7, 4, 5, 6,-1,-1,-1,-1 }, // W
79 { 3, 0, 1, 2, 3, 0, 1, 2, 4, 5, 6, 7 }, // NW
80 { 2, 3, 0, 1,-1,-1,-1,-1, 0, 1, 2, 3 } }; // N
81 static final protected byte[][] swaparray =
82 { { 0,0,3 }, // S
83 { 0,0,6 }, // SE
84 { 0,0,0 }, // E
85 { 0,0,5 }, // SW
86 { 0,0,0 }, // center
87 { 5,0,0 }, // NE
88 { 0,0,0 }, // W
89 { 6,0,0 }, // NW
90 { 3,0,0 } }; // N
91
92 static final protected int swap_cycle[][] = {
93 {},
94 {0,1,8,12,16,21,40},
95 {0,1,2,40,114},
96 {0,4,160,263},
97 {0,4,30,49,51,87,526,1027,1105,1387,1807,2637},
98 {0,8,10,18,39,74,146,307,452,4737},
99 {0,1,2,7,9,17,80,410,1526,1921,32859,33566,38931},
100 {0,5,6,10,12,24,27,95,372,494,924,1409,3492,4248,9137,66043,103369,156899},
101 {0,1,2,3,4,45,125,351,697,24337,102940,266194,341855,419857},
102 {0,1,2,3,9,16,1705,2082,2126,8177,12753,15410,52642,80493,83235,88387,99444,
103 1675361,2495125},
104 {0,2,6,8,9,11,20,50,93,152,183,2137,13671,44794,486954,741908,4803258,
105 5692573},
106 {0,1,5,6,44,53,470,2847,3433,4906,13654,14710,400447,1797382,2744492,
107 18775974,23541521},
108 {0,4,9,10,16,33,83,117,318,451,5759,10015,128975,171834,211256,347608,
109 1278690,2154097,2590798,3427694,5581717,21012301,27023976,72522811,
110 95032729,139166747,171822389},
111 {0,5,10,267,344,363,2968,3159,9083,18437,76602,147614,1246902,1593138,
112 2035574,6529391,9511830,11340287,29565945,281666026,677946848} };
113 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Collection of utility functions.
23
24 @copyright 2011-2014 Max-Planck-Society
25 @author Martin Reinecke */
26 public class HealpixUtils
27 {
28 /** Evaluates cond; if it is false, throws an Exception containing errtxt. */
29 static public void check(boolean cond, String errtxt) throws Exception
30 { if (!cond) throw new Exception(errtxt); }
31
32 /** Integer base 2 logarithm.
33 @param arg
34 @return the largest integer {@code n} that fulfills {@code 2^n<=arg}.
35 For negative arguments and zero, 0 is returned. */
36 static public int ilog2(long arg)
37 {
38 return 63-Long.numberOfLeadingZeros(Math.max(arg,1L));
39 }
40
41 /** Integer square root.
42 @param arg
43 @return the integer {@code n} which fulfills {@code n^2<=arg<(n+1)^2} */
44 static public int isqrt(long arg)
45 {
46 long res = (long)Math.sqrt(((double)arg)+0.5);
47 if (arg<(1L<<50)) return (int)res;
48 if (res*res>arg)
49 --res;
50 else if ((res+1)*(res+1)<=arg)
51 ++res;
52 return (int)res;
53 }
54
55 /** Computes the cosine of the angular distance between two z, phi positions
56 on the unit sphere. */
57 static public double cosdist_zphi (double z1, double phi1,
58 double z2, double phi2)
59 {
60 return z1*z2+ FastMath.cos(phi1-phi2)* Math.sqrt((1.0-z1*z1)*(1.0-z2*z2));
61 }
62 /** Computes the cosine of the angular distance between two z, phi positions
63 on the unit sphere. */
64 static public double cosdist_zphi (Zphi zp1, Zphi zp2)
65 { return cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi); }
66
67 /** Returns the remainder of the division {@code v1/v2}.
68 The result is non-negative.
69 @param v1 dividend; can be positive or negative
70 @param v2 divisor; must be positive
71 @return remainder of the division; positive and smaller than {@code v2} */
72 static public double fmodulo (double v1, double v2)
73 {
74 if (v1>=0)
75 return (v1<v2) ? v1 : v1%v2;
76 double tmp=v1%v2+v2;
77 return (tmp==v2) ? 0. : tmp;
78 }
79
80 static public boolean approx (float a, float b, float epsilon)
81 { return Math.abs(a-b) < (epsilon*Math.abs(b)); }
82 static public boolean approx (double a, double b, double epsilon)
83 { return Math.abs(a-b) < (epsilon*Math.abs(b)); }
84
85 static public int uniq2order (long uniq)
86 { return ilog2(uniq>>>2)>>>1; }
87
88 static private long nest_peano_helper (long pix, int order, int dir)
89 {
90 final short arr2[] =
91 { 0, 35, 65, 66, 68, 5,103, 6,110,109, 15, 44, 72, 9,107, 10,
92 31,126, 60,125, 81, 16, 82, 51,123, 88, 26, 25,119, 84, 22, 21,
93 42, 75, 41,104, 12, 47, 77, 78, 38, 71, 37,100, 98, 97, 3, 32,
94 53, 54,116, 87, 57, 58,120, 91, 19,114, 48,113, 93, 28, 94, 63,
95 64, 1, 99, 2, 46, 79, 45,108, 4, 39, 69, 70, 8, 43, 73, 74,
96 85, 20, 86, 55,115, 80, 18, 17, 89, 24, 90, 59, 61, 62,124, 95,
97 106,105, 11, 40,102,101, 7, 36, 76, 13,111, 14, 34, 67, 33, 96,
98 127, 92, 30, 29, 27,122, 56,121, 49, 50,112, 83, 23,118, 52,117,
99 128,194,195,161,196,133,135,230,204,141,143,238,171,233,232,138,
100 149,212,214,183,221,159,158,252,217,155,154,248,178,243,241,144,
101 175,237,236,142,235,170,168,201,227,162,160,193,132,198,199,165,
102 186,251,249,152,242,176,177,211,246,180,181,215,157,220,222,191,
103 192,129,131,226,136,202,203,169,140,206,207,173,231,166,164,197,
104 213,151,150,244,145,208,210,179,153,216,218,187,254,188,189,223,
105 239,174,172,205,167,229,228,134,163,225,224,130,200,137,139,234,
106 250,184,185,219,190,255,253,156,182,247,245,148,209,147,146,240 };
107 final byte arr[] = { 16, 1,27, 2,31,20, 6, 5,10,19, 9,24,13,14,28,23,
108 0,11,17,18,21, 4,22,15,26,25, 3, 8, 7,30,12,29,
109 48,33,35,58,53,39,38,60,59,42,40,49,62,44,45,55,
110 32,50,51,41,37,52,54,47,43,57,56,34,46,63,61,36 };
111 final byte peano_face2path[][] =
112 { { 2,5,2,5,3,6,3,6,2,3,2,3 }, { 2,6,2,3,3,5,2,6,2,3,3,5 } };
113 final byte peano_face2face[][] =
114 { { 0,5,6,11,10,1,4,7,2,3,8,9 }, { 0,5,8,9,6,1,2,7,10,11,4,3 } };
115
116 int face = (int)(pix>>>(2*order));
117 long result = 0L;
118 int state = ((peano_face2path[dir][face]<<4))|(dir<<7);
119 int shift=2*order-4;
120 for (; shift>=0; shift-=4)
121 {
122 state=arr2[(state&0xF0) | (((int)(pix>>>shift))&0xF)];
123 result = (result<<4) | (state&0xF);
124 }
125 if (shift==-2)
126 {
127 state=arr[((state>>>2)&0xFC) | ((int)(pix)&0x3)];
128 result = (result<<2) | (state&0x3);
129 }
130
131 return result + (((long)peano_face2face[dir][face])<<(2*order));
132 }
133
134 static public long nest2peano(long pix, int order)
135 { return nest_peano_helper(pix,order,0); }
136 static public long peano2nest(long pix, int order)
137 { return nest_peano_helper(pix,order,1); }
138
139 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Healpix-internal class for specifying locations on the sphere.
23
24 @copyright 2011 Max-Planck-Society
25 @author Martin Reinecke */
26 final class Hploc
27 {
28 public double z, phi, sth;
29 public boolean have_sth;
30
31 /** Default constructor. */
32 public Hploc() {}
33 public Hploc (Vec3 v)
34 {
35 double xl = 1./v.length();
36 z = v.z*xl;
37 phi = FastMath.atan2(v.y,v.x);
38 if (Math.abs(z)>0.99)
39 {
40 sth = Math.sqrt(v.x*v.x+v.y*v.y)*xl;
41 have_sth=true;
42 }
43 }
44 public Hploc (Zphi zphi)
45 {
46 z = zphi.z;
47 phi = zphi.phi;
48 have_sth=false;
49 }
50 public Hploc (Pointing ptg) throws Exception
51 {
52 HealpixUtils.check((ptg.theta>=0.)&&(ptg.theta<=Math.PI),
53 "invalid theta value");
54 z = FastMath.cos(ptg.theta);
55 phi = ptg.phi;
56 if (Math.abs(z)>0.99)
57 {
58 sth = FastMath.sin(ptg.theta);
59 have_sth=true;
60 }
61 }
62
63 public Zphi toZphi()
64 { return new Zphi(z,phi); }
65 public Pointing toPointing()
66 {
67 double st = have_sth ? sth : Math.sqrt((1.0-z)*(1.0+z));
68 return new Pointing(FastMath.atan2(st,z),phi);
69 }
70 public Vec3 toVec3()
71 {
72 double st = have_sth ? sth : Math.sqrt((1.0-z)*(1.0+z));
73 return new Vec3(st*FastMath.cos(phi),st*FastMath.sin(phi),z);
74 }
75 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Support for MOC algorithms.
23 @copyright 2014-2015 Max-Planck-Society
24 @author Martin Reinecke */
25 public class Moc
26 {
27 private final static int maxorder=29;
28 private RangeSet rs;
29
30 /** Creates a new, empty Moc. */
31 public Moc()
32 { rs=new RangeSet(); }
33 /** Creates a new Moc, which is identical to "other". */
34 public Moc(Moc other)
35 { rs=new RangeSet(other.rs); }
36 /** Creates a new Moc from the range set of NESTED pixels at the given order.
37 */
38 public Moc(RangeSet rs2, int order)
39 {
40 rs=new RangeSet(rs2.nranges());
41 int shift=2*(maxorder-order);
42 for (int i=0; i<rs2.nranges(); ++i)
43 rs.append(rs2.ivbegin(i)<<shift,rs2.ivend(i)<<shift);
44 }
45
46 static private Moc fromNewRangeSet(RangeSet rngset)
47 {
48 Moc res = new Moc();
49 res.rs = rngset;
50 return res;
51 }
52
53 /** Returns the internal range set. */
54 public RangeSet getRangeSet()
55 { return new RangeSet(rs); }
56
57 /** Returns the maximum HEALPix order necessary to describe the Moc exactly.
58 */
59 public int maxOrder()
60 {
61 long combo=0;
62 for (int i=0; i<rs.nranges(); ++i)
63 combo|=rs.ivbegin(i)|rs.ivend(i);
64 return maxorder-(Long.numberOfTrailingZeros(combo)>>>1);
65 }
66
67 /** Returns a Moc with degraded resolution.
68 @param order the maximum HEALPix order used for the result
69 @param keepPartialCells if true, partially filled cells will be included
70 in the output Moc; if false, they will be ignored. */
71 public Moc degradedToOrder (int order, boolean keepPartialCells)
72 {
73 int shift=2*(maxorder-order);
74 long ofs=(1L<<shift)-1;
75 long mask = ~ofs;
76 long adda = keepPartialCells ? 0L : ofs,
77 addb = keepPartialCells ? ofs : 0L;
78 RangeSet rs2=new RangeSet();
79 for (int i=0; i<rs.nranges(); ++i)
80 {
81 long a=(rs.ivbegin(i)+adda)&mask;
82 long b=(rs.ivend (i)+addb)&mask;
83 if (b>a) rs2.append(a,b);
84 }
85 return fromNewRangeSet(rs2);
86 }
87
88 /** Adds a range of pixels at a given HEALPix order to the Moc.
89 @param order the HEALPix order of the added pixels
90 @param p1 the first pixel of the range
91 @param p2 the one-after-last pixel of the range */
92 public void addPixelRange (int order, long p1, long p2)
93 {
94 int shift=2*(maxorder-order);
95 rs.add(p1<<shift,p2<<shift);
96 }
97 public void addPixel (int order, long p)
98 { addPixelRange(order, p, p+1); }
99 /** Returns a new Moc that contains the union of this Moc and "other". */
100 public Moc union (Moc other)
101 { return fromNewRangeSet(rs.union(other.rs)); }
102 /** Returns a new Moc that contains the intersection of this Moc and "other".
103 */
104 public Moc intersection (Moc other)
105 { return fromNewRangeSet(rs.intersection(other.rs)); }
106 /** Returns a new Moc that contains all parts of this Moc that are not
107 contained in "other". */
108 public Moc subtraction (Moc other)
109 { return fromNewRangeSet(rs.difference(other.rs)); }
110 /** Returns the complement of this Moc. */
111 public Moc complement()
112 {
113 RangeSet full = new RangeSet(new long[]{0L,12L*(1L<<(2*maxorder))});
114 return fromNewRangeSet(full.difference(rs));
115 }
116 /** @return true, if "other" is a subset of this Moc, else false. */
117 public boolean contains(Moc other) // FIXME: needs optimization!
118 { return rs.contains(other.rs); }
119 /** @return true, if the intersection of this Moc and "other" is not empty. */
120 public boolean overlaps(Moc other) // FIXME: needs optimization!
121 { return rs.overlaps(other.rs); }
122 /** @return A RangeSet containing all HEALPix pixels (in NUNIQ order) covered
123 by this Moc. The result is well-formed in the sense that every pixel is
124 given at its lowest possible HEALPix order. */
125 public RangeSet toUniqRS() // should be tuned!
126 {
127 RangeSet r2 = new RangeSet(rs);
128 RangeSet r3 = new RangeSet();
129 RangeSet res= new RangeSet();
130 for (int o=0; o<=maxorder; ++o)
131 {
132 if (r2.isEmpty()) return res;
133
134 int shift = 2*(maxorder-o);
135 long ofs=(1L<<shift)-1;
136 long ofs2 = 1L<<(2*o+2);
137 r3.clear();
138 for (int iv=0; iv<r2.nranges(); ++iv)
139 {
140 long a=(r2.ivbegin(iv)+ofs)>>>shift,
141 b=r2.ivend(iv)>>>shift;
142 r3.append(a<<shift, b<<shift);
143 res.append(a+ofs2,b+ofs2);
144 }
145 if (!r3.isEmpty())
146 r2 = r2.difference(r3);
147 }
148 return res;
149 }
150 public long[] toUniq() // should be tuned!
151 { return toUniqRS().toArray(); }
152
153 /** @return A Moc built from the RangeSet of NUNIQ HEALPix pixels given in
154 "ru". "ru" need not be well-formed. */
155 public static Moc fromUniqRS (RangeSet ru) // should be tuned!
156 {
157 RangeSet r= new RangeSet();
158 RangeSet rtmp = new RangeSet();
159 int lastorder=0;
160 int shift=2*maxorder;
161 for (int i=0; i<ru.nranges(); ++i)
162 for (long j=ru.ivbegin(i); j<ru.ivend(i); ++j)
163 {
164 int order = HealpixUtils.uniq2order(j);
165 if (order!=lastorder)
166 {
167 r=r.union(rtmp);
168 rtmp.clear();
169 lastorder=order;
170 shift=2*(maxorder-order);
171 }
172 long pix = j-(1L<<(2*order+2));
173 rtmp.append (pix<<shift,(pix+1)<<shift);
174 }
175 r=r.union(rtmp);
176 return fromNewRangeSet(r);
177 }
178
179 public static Moc fromUniq (long []u) // should be tuned!
180 {
181 return fromUniqRS(RangeSet.fromArray(u));
182 }
183
184 /** @return A compressed representation of the Moc obtained by interpolative
185 coding. */
186 public byte[] toCompressed() throws Exception
187 { return rs.toCompressed(); }
188 /** @return A Moc built from the compressed representation given in "data". */
189 public static Moc fromCompressed(byte[] data) throws Exception
190 { return fromNewRangeSet(RangeSet.fromCompressed(data)); }
191
192 public boolean equals(Object obj)
193 {
194 if (this == obj)
195 return true;
196 if ((obj==null) || (!(obj instanceof Moc)))
197 return false;
198 Moc other = (Moc) obj;
199 return rs.equals(other.rs);
200 }
201 public int hashCode()
202 { return rs.hashCode(); }
203
204 public int nranges()
205 { return rs.nranges(); }
206 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 */
18 package healpix.essentials;
19
20 import java.io.*;
21 import nom.tam.fits.*;
22
23 /** Moc FITS I/O routines.
24 @copyright 2014-2015 Max-Planck-Society
25 @author Martin Reinecke */
26 public class MocFitsIO
27 {
28 /** Converts the contents of a FITS input stream to a MOC. */
29 public static Moc mocFromFits(InputStream inp) throws Exception
30 {
31 FitsFactory.setUseHierarch(true);
32 FitsFactory.setUseAsciiTables(false);
33 BasicHDU bhdu = (new Fits(inp)).getHDU(1);
34 Header head = bhdu.getHeader();
35 Header.setLongStringsEnabled(true);
36
37 Object tmp = ((BinaryTable)bhdu.getData()).getFlattenedColumn(0);
38 long[] data=null;
39 if (tmp instanceof long[])
40 data = (long[])tmp;
41 else if (tmp instanceof int[])
42 {
43 int[] tmp2 = (int[])tmp;
44 data = new long[tmp2.length];
45 for (int i=0; i<tmp2.length; ++i)
46 data[i] = (long)tmp2[i];
47 }
48 else if (tmp instanceof short[])
49 {
50 short[] tmp2 = (short[])tmp;
51 data = new long[tmp2.length];
52 for (int i=0; i<tmp2.length; ++i)
53 data[i] = (long)tmp2[i];
54 }
55 else
56 HealpixUtils.check(false,"unsupported data format");
57
58 RangeSet ru = new RangeSet();
59 for (int i=0; i<data.length; ++i)
60 ru.append(data[i]);
61 return Moc.fromUniqRS(ru);
62 }
63 /** Converts the contents of a FITS file to a MOC. */
64 public static Moc mocFromFits(String filename) throws Exception
65 {
66 FileInputStream inp = new FileInputStream(filename);
67 Moc moc = mocFromFits(inp);
68 inp.close();
69 return moc;
70 }
71
72 /** Writes the provided Moc to the stream in FITS format. */
73 public static void mocToFits(Moc moc, OutputStream out) throws Exception
74 {
75 FitsFactory.setUseHierarch(true);
76 FitsFactory.setUseAsciiTables(false);
77 Fits f = new Fits();
78 Object[] table = new Object[1];
79 long[] data=moc.toUniq();
80 long maxval=0;
81 if (data.length>0) maxval=data[data.length-1];
82 if (maxval<=0x7fff)
83 {
84 short[] dtmp = new short[data.length];
85 for (int i=0; i<data.length; ++i)
86 dtmp[i]=(short)data[i];
87 table[0]=dtmp;
88 }
89 else if (maxval<=0x7FFFFFFF)
90 {
91 int[] dtmp = new int[data.length];
92 for (int i=0; i<data.length; ++i)
93 dtmp[i]=(int)data[i];
94 table[0]=dtmp;
95 }
96 else
97 table[0] = data;
98
99 f.addHDU(Fits.makeHDU(table));
100 BinaryTableHDU bhdu = (BinaryTableHDU) f.getHDU(1);
101
102 bhdu.setColumnName(0, "PIXEL", "");
103 bhdu.addValue("PIXTYPE", "HEALPIX", "HEALPix magic value");
104 bhdu.addValue("ORDERING", "NUNIQ", "NUNIQ coding method");
105 bhdu.addValue("COORDSYS", "C", "mandated by MOC standard");
106 bhdu.addValue("MOCORDER", moc.maxOrder(), "MOC resolution (best order)");
107
108 f.write(new DataOutputStream(out));
109 out.flush();
110 }
111 /** Writes the provided Moc to the specified file in FITS format. */
112 public static void mocToFits(Moc moc, String filename) throws Exception
113 {
114 FileOutputStream out = new FileOutputStream(filename);
115 mocToFits(moc,out);
116 out.close();
117 }
118 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21 import java.util.ArrayList;
22
23 /** Support for MOC queries.
24 @copyright 2015 Max-Planck-Society
25 @author Martin Reinecke */
26 public class MocQuery
27 {
28 static public enum MocQueryOp { AND,OR,XOR,NOT,NONE }
29
30 static public class MocQueryComponent
31 {
32 public MocQueryOp op;
33 public Vec3 center;
34 public double radius;
35 public int nops;
36 public MocQueryComponent(MocQueryOp op_) throws Exception
37 {
38 op= op_;
39 HealpixUtils.check(op_!=MocQueryOp.NONE,"bad operator");
40 switch (op)
41 {
42 case AND:
43 case OR:
44 case XOR:
45 nops=2;
46 break;
47 case NOT:
48 nops=1;
49 break;
50 case NONE:
51 nops=0;
52 break;
53 }
54 }
55 public MocQueryComponent(MocQueryOp op_, int nops_) throws Exception
56 {
57 op= op_;
58 nops=nops_;
59 switch (op)
60 {
61 case AND:
62 case OR:
63 HealpixUtils.check(nops>=2,"bad nops");
64 break;
65 case XOR:
66 HealpixUtils.check(nops==2,"bad nops");
67 break;
68 case NOT:
69 HealpixUtils.check(nops==1,"bad nops");
70 break;
71 case NONE:
72 HealpixUtils.check(false,"bad operator");
73 break;
74 }
75 }
76 public MocQueryComponent(Vec3 cnt, double rad)
77 {
78 op = MocQueryOp.NONE;
79 center = new Vec3(cnt);
80 center.normalize();
81 radius = rad;
82 nops=0;
83 }
84 }
85
86 static private class queryHelper
87 {
88 private final class pstack
89 {
90 private long[] p;
91 private int[] o;
92 private int s, m;
93
94 public pstack (int sz)
95 { p=new long[sz]; o=new int[sz]; s=m=0; }
96 public void push (long p_, int o_)
97 { p[s]=p_; o[s]=o_; ++s; }
98 public void pop ()
99 { --s; }
100 public void popToMark ()
101 { s=m; }
102 public int size ()
103 { return s; }
104 public void mark ()
105 { m=s; }
106 public int otop ()
107 { return o[s-1]; }
108 public long ptop ()
109 { return p[s-1]; }
110 public void clear ()
111 { s=m=0; }
112 public boolean empty ()
113 { return s==0; }
114 }
115
116 private int order, omax, ncomp;
117 private boolean inclusive;
118 private HealpixBase base[];
119 private double cr[], crmin[][], crmax[][];
120 private int shortcut[];
121 private MocQueryOp op[];
122 private int nops[];
123 private Vec3 center[];
124
125 private pstack stk; // stack for pixel numbers and their orders
126 private long pix;
127 private int o;
128 private Vec3 pv;
129 private int loc;
130
131 private void check_pixel (int zone, Moc pixset)
132 {
133 if (zone==0) return;
134 if (o<order)
135 {
136 if (zone>=3)
137 pixset.addPixel(o,pix); // output all subpixels
138 else // (zone>=1)
139 for (int i=0; i<4; ++i)
140 stk.push(4*pix+3-i,o+1); // add children
141 }
142 else if (o>order) // this implies that inclusive==true
143 {
144 if (zone>=2) // pixel center in shape
145 {
146 pixset.addPixel(order,pix>>>(2*(o-order))); // output parent pixel
147 stk.popToMark(); // unwind the stack
148 }
149 else // (zone>=1): pixel center in safety range
150 {
151 if (o<omax) // check sublevels
152 for (int i=0; i<4; ++i) // add children in reverse order
153 stk.push(4*pix+3-i,o+1);
154 else // at resolution limit
155 {
156 pixset.addPixel(order,pix>>>(2*(o-order))); // output parent pixel
157 stk.popToMark(); // unwind the stack
158 }
159 }
160 }
161 else // o==order
162 {
163 if (zone>=2)
164 pixset.addPixel(order,pix);
165 else if (inclusive) // and (zone>=1)
166 {
167 if (order<omax) // check sublevels
168 {
169 stk.mark(); // remember current stack position
170 for (int i=0; i<4; ++i) // add children in reverse order
171 stk.push(4*pix+3-i,o+1);
172 }
173 else // at resolution limit
174 pixset.addPixel(order,pix); // output the pixel
175 }
176 }
177 }
178
179 void correctLoc() throws Exception
180 {
181 int myloc=loc--;
182 HealpixUtils.check((myloc>=0)&&(myloc<ncomp),"inconsistency");
183 for (int i=0; i<nops[myloc]; ++i)
184 correctLoc();
185 }
186 int getZone (int zmin, int zmax)
187 {
188 if (zmin==zmax) { loc=shortcut[loc]; return zmin; } // short-circuit
189 int myloc=loc--;
190 switch (op[myloc])
191 {
192 case AND:
193 {
194 int z1=zmax;
195 for (int i=0; i<nops[myloc]; ++i)
196 z1 = getZone(zmin,z1);
197 return z1;
198 }
199 case OR:
200 {
201 int z1=zmin;
202 for (int i=0; i<nops[myloc]; ++i)
203 z1 = getZone(z1,zmax);
204 return z1;
205 }
206 case XOR:
207 {
208 int z1=getZone(0,3);
209 int z2=getZone(0,3);
210 return Math.max(zmin,Math.min(zmax,
211 Math.max(Math.min(z1,3-z2),Math.min(3-z1,z2))));
212 }
213 case NOT:
214 return 3-getZone(3-zmax,3-zmin);
215 case NONE:
216 {
217 int res=zmax;
218 double crad=pv.dot(center[myloc]);
219 if (crad<=crmax[o][myloc]) res=0;
220 else if (crad<=cr[myloc]) res=1;
221 else if (crad<=crmin[o][myloc]) res=2;
222 return Math.max(zmin,Math.min(zmax,res));
223 }
224 }
225 return -1; // unreachable
226 }
227
228 public queryHelper (int order_, int omax_, boolean inclusive_,
229 ArrayList<MocQueryComponent> comp) throws Exception
230 {
231 order=order_;
232 omax=omax_;
233 ncomp=comp.size();
234 inclusive=inclusive_;
235 base=new HealpixBase[omax+1];
236 cr=new double[ncomp];
237 crmin=new double [omax+1][ncomp];
238 crmax=new double [omax+1][ncomp];
239 HealpixUtils.check(ncomp>=1,"bad query component ArrayList");
240 HealpixUtils.check(order<=omax,"order>omax");
241 if (!inclusive) HealpixUtils.check(order==omax,"inconsistency");
242 HealpixUtils.check(omax<=HealpixBase.order_max,"omax too high");
243
244 op=new MocQueryOp[ncomp];
245 nops=new int[ncomp];
246 center=new Vec3[ncomp];
247 for (int i=0; i<ncomp; ++i)
248 {
249 op[i]=comp.get(i).op;
250 nops[i]=comp.get(i).nops;
251 center[i]=comp.get(i).center;
252 if (op[i]==MocQueryOp.NONE) // it's a cap
253 cr[i]=Math.cos(comp.get(i).radius);
254 }
255 for (o=0; o<=omax; ++o) // prepare data at the required orders
256 {
257 base[o] = new HealpixBase(1<<o,Scheme.NESTED);
258 double dr=base[o].maxPixrad(); // safety distance
259 for (int i=0; i<ncomp; ++i)
260 if (op[i]==MocQueryOp.NONE) // it's a cap
261 {
262 double r=comp.get(i).radius;
263 crmax[o][i] = (r+dr>=Math.PI) ?
264 -1.01 : Math.cos(r+dr);
265 crmin[o][i] = (r-dr<=0.) ?
266 1.01 : Math.cos(r-dr);
267 }
268 }
269 stk=new pstack(12+3*omax); // reserve maximum size to avoid reallocation
270
271 shortcut=new int[ncomp];
272 for (int i=0; i<ncomp; ++i)
273 {
274 loc=i;
275 correctLoc();
276 shortcut[i]=loc;
277 }
278 }
279 Moc result() throws Exception
280 {
281 Moc pixset = new Moc();
282 stk.clear();
283 stk.mark();
284 for (int i=0; i<12; ++i) // insert the 12 base pixels in reverse order
285 stk.push(11-i,0);
286
287 while (!stk.empty()) // as long as there are pixels on the stack
288 {
289 // pop current pixel number and order from the stack
290 pix=stk.ptop();
291 o=stk.otop();
292 stk.pop();
293 pv = base[o].pix2vec(pix);
294
295 loc=ncomp-1;
296 int zone=getZone(0,3);
297 check_pixel (zone, pixset);
298 HealpixUtils.check(loc==-1,"stack not used up");
299 }
300 return pixset;
301 }
302 }
303
304 static public Moc doMocQuery (int order, ArrayList<MocQueryComponent> comp)
305 throws Exception
306 { return (new queryHelper(order,order,false,comp)).result(); }
307
308 static public Moc doMocQueryInclusive (int order, int omax,
309 ArrayList<MocQueryComponent> comp)
310 throws Exception
311 { return (new queryHelper(order,omax,true,comp)).result(); }
312
313 static private double isLeft (Vec3 a, Vec3 b, Vec3 c)
314 {
315 return (a.cross(b)).dot(c);
316 }
317
318 // adapted from code available at http://geomalgorithms.com/a12-_hull-3.html
319 // Original copyright notice follows:
320 // Copyright 2001 softSurfer, 2012 Dan Sunday
321 // This code may be freely used and modified for any purpose
322 // providing that this copyright notice is included with it.
323 // SoftSurfer makes no warranty for this code, and cannot be held
324 // liable for any real or imagined damage resulting from its use.
325 // Users of this code must verify correctness for their application.
326 static private int[] getHull (Vec3 vert[], int P[])
327 throws Exception
328 {
329 // initialize a deque D[] from bottom to top so that the
330 // 1st three vertices of P[] are a ccw triangle
331 int n = P.length;
332 int D[] = new int[2*n+1];
333 int bot = n-2, top = bot+3; // initial bottom and top deque indices
334 D[bot] = D[top] = P[2]; // 3rd vertex is at both bot and top
335 if (isLeft(vert[P[0]], vert[P[1]], vert[P[2]]) > 0)
336 {
337 D[bot+1] = P[0];
338 D[bot+2] = P[1]; // ccw vertices are: 2,0,1,2
339 }
340 else
341 {
342 D[bot+1] = P[1];
343 D[bot+2] = P[0]; // ccw vertices are: 2,1,0,2
344 }
345
346 // compute the hull on the deque D[]
347 for (int i=3; i<n; i++)
348 { // process the rest of vertices
349 // test if next vertex is inside the deque hull
350 if ((isLeft(vert[D[bot]], vert[D[bot+1]], vert[P[i]]) > 0) &&
351 (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) > 0) )
352 continue; // skip an interior vertex
353
354 // incrementally add an exterior vertex to the deque hull
355 // get the rightmost tangent at the deque bot
356 while (isLeft(vert[D[bot]], vert[D[bot+1]], vert[P[i]]) <= 0)
357 ++bot; // remove bot of deque
358 D[--bot] = P[i]; // insert P[i] at bot of deque
359
360 // get the leftmost tangent at the deque top
361 while (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) <= 0)
362 --top; // pop top of deque
363 D[++top] = P[i]; // push P[i] onto top of deque
364 }
365
366 // transcribe deque D[] to the output hull array H[]
367 int nout = top-bot;
368 int res[] = new int[nout];
369 for (int h=0; h<nout; h++)
370 res[h] = D[bot + h +1];
371
372 return res;
373 }
374
375 static public ArrayList<MocQueryComponent> prepPolyHelper (Vec3 vv[],
376 int P[], ArrayList<MocQueryComponent> comp, boolean doLast)
377 throws Exception
378 {
379 int hull[]=getHull(vv,P);
380 boolean addHull[]=new boolean[hull.length];
381
382 // sync both sequences at the first point of the convex hull
383 int ihull=0, ipoly=0, nhull=hull.length, npoly=P.length;
384 while (hull[ihull]!=P[ipoly]) ++ipoly;
385
386 // iterate over the pockets between the polygon and its convex hull
387 int npockets=0;
388 if (P.length==3)
389 for (int i=0; i<3; i++) addHull[i]=true;
390 else
391 {
392 do
393 {
394 int ihull_next = (ihull+1)%nhull,
395 ipoly_next = (ipoly+1)%npoly;
396 if (hull[ihull_next]==P[ipoly_next]) // no pocket found
397 { addHull[ihull]=true; ihull=ihull_next; ipoly=ipoly_next; }
398 else // query pocket
399 {
400 int nvpocket=2; // number of vertices for this pocket
401 while (P[ipoly_next]!=hull[ihull_next])
402 {
403 ipoly_next = (ipoly_next+1)%npoly;
404 ++nvpocket;
405 }
406 int ppocket[] = new int[nvpocket];
407 int idx=0;
408 int ipoly_bw=ipoly_next;
409 while (P[ipoly_bw]!=hull[ihull])
410 {
411 ppocket[idx++]=P[ipoly_bw];
412 ipoly_bw=(ipoly_bw+npoly-1)%npoly;
413 }
414 ppocket[idx]=hull[ihull];
415 // process pocket recursively
416 ++npockets;
417 comp=prepPolyHelper (vv, ppocket, comp, false);
418 ihull=ihull_next;
419 ipoly=ipoly_next;
420 }
421 } while (ihull!=0);
422 }
423 if (npockets>1)
424 comp.add(new MocQueryComponent(MocQueryOp.OR,npockets));
425 if (npockets>0)
426 comp.add(new MocQueryComponent(MocQueryOp.NOT));
427
428 if (!doLast)
429 addHull[hull.length-1]=false;
430
431 // add convex hull
432 for (int i=0; i<hull.length; ++i)
433 if (addHull[i])
434 comp.add(new MocQueryComponent
435 (vv[hull[i]].cross(vv[hull[(i+1)%hull.length]]).norm(),0.5*Math.PI));
436
437 int num_and = 0;
438 for (int i=0; i<hull.length; ++i)
439 if (addHull[i]) ++num_and;
440 if (npockets>0) ++num_and;
441 if (num_and>1)
442 comp.add(new MocQueryComponent(MocQueryOp.AND,num_and));
443
444 return comp;
445 }
446
447 static public ArrayList<MocQueryComponent> prepPolygon(ArrayList<Vec3> vertex)
448 throws Exception
449 {
450 HealpixUtils.check(vertex.size()>=3,"not enough vertices in polygon");
451 Vec3 vv[] = new Vec3[vertex.size()];
452 for (int i=0; i<vertex.size(); ++i)
453 vv[i]=vertex.get(i).norm();
454
455 int[] P=new int[vv.length];
456 for (int i=0; i<P.length; ++i)
457 P[i]=i;
458 ArrayList<MocQueryComponent> comp = new ArrayList<MocQueryComponent>();
459 return prepPolyHelper(vv,P,comp,true);
460 }
461
462 static public Moc queryGeneralPolygon (ArrayList<Vec3> vertex, int order)
463 throws Exception
464 { return doMocQuery (order, MocQuery.prepPolygon(vertex)); }
465 static public Moc queryGeneralPolygonInclusive (ArrayList<Vec3> vertex,
466 int order, int omax)
467 throws Exception
468 { return doMocQueryInclusive (order, omax, MocQuery.prepPolygon(vertex)); }
469 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 */
18 package healpix.essentials;
19
20 import java.io.*;
21
22 /** Moc string I/O routines.
23 @copyright 2014-2015 Max-Planck-Society
24 @author Martin Reinecke */
25 public class MocStringIO
26 {
27 /** Parses a string following either the basic ASCII or JSON syntax given in
28 the MOC standard document, and converts it into a MOC.
29 The string need not obey the rules for a well-formed MOC given in the
30 document. */
31 public static Moc mocFromString(String in)
32 {
33 in=in.replaceAll(",+"," "); // replace commas with spaces
34 in=in.replaceAll("[\\[\\]{}\"]+",""); // get rid of useless characters
35 in=in.replaceAll("\\s*[:/]\\s*","/ "); // stick order indicator to order
36 in=in.replaceAll("\\s*-\\s*","-"); // fuse ranges into one token
37 String[] tok = in.split("[\\s]+"); // split at whitespace
38 RangeSet ru = new RangeSet();
39 int order=0;
40 long ofs=0;
41 for (int i=0; i<tok.length; ++i)
42 {
43 if (tok[i].isEmpty()) continue;
44 if (tok[i].contains("/")) // new order
45 {
46 tok[i]=tok[i].split("/")[0];
47 order=Integer.parseInt(tok[i]);
48 ofs = 4*(1L<<(2*order));
49 }
50 else if (tok[i].contains("-")) // range of values
51 {
52 String [] lim=tok[i].split("-");
53 ru.add(Long.parseLong(lim[0])+ofs,
54 Long.parseLong(lim[1])+ofs+1);
55 }
56 else // single value
57 ru.add(Long.parseLong(tok[i])+ofs);
58 }
59 return Moc.fromUniqRS(ru);
60 }
61 private static String mocToStringGeneral(Moc moc, boolean json)
62 {
63 RangeSet ru = moc.toUniqRS();
64 StringBuilder s = new StringBuilder();
65 if (json) s.append("{");
66 boolean firstOrder=true;
67 int omax = moc.maxOrder();
68 for (int o=0; o<=omax; ++o)
69 {
70 RangeSet rt = new RangeSet();
71 long offset=4*(1L<<(2*o));
72 rt.append(offset, 4*offset);
73 rt=rt.intersection(ru);
74 boolean prefix=false;
75 if (!rt.isEmpty())
76 {
77 for (int iv=0; iv<rt.nranges(); ++iv)
78 {
79 long a=rt.ivbegin(iv)-offset,
80 b=rt.ivend(iv)-offset;
81 if (!prefix)
82 {
83 if (!firstOrder) s.append(json ? ", " : " ");
84 firstOrder=false;
85 if (json)
86 s.append("\"").append(o).append("\":[");
87 else
88 s.append(o).append("/");
89 prefix=true;
90 }
91 else
92 s.append(",");
93 if (json)
94 {
95 for (long i=a;i<b-1;++i)
96 s.append(i).append(",");
97 s.append(b-1);
98 }
99 else
100 {
101 s.append(a);
102 if (b>a+1) s.append("-").append(b-1);
103 }
104 }
105 }
106 if (json&&prefix)
107 s.append("]");
108 }
109 if (json) s.append("}");
110 return s.toString();
111 }
112 /** Converts the Moc to its basic ASCII representation as described in the MOC
113 standard document. The result is well-formed. */
114 public static String mocToStringASCII (Moc moc)
115 { return mocToStringGeneral(moc,false); }
116 /** Converts the Moc to its JSON representation as described in the MOC
117 standard document. The result is well-formed. */
118 public static String mocToStringJSON(Moc moc)
119 { return mocToStringGeneral(moc,true); }
120 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** An angular position on the unit sphere.
23
24 @copyright 2011 Max-Planck-Society
25 @author Martin Reinecke */
26 public class Pointing
27 {
28 /** Colatitude in radians (0 is North Pole; Pi is South Pole) */
29 public double theta;
30
31 /** Longitude in radians */
32 public double phi;
33
34 /** Default constructor */
35 public Pointing() {}
36
37 public Pointing(Pointing ptg)
38 { this.theta = ptg.theta; this.phi = ptg.phi; }
39
40 /** Simple constructor initializing both values.
41 @param theta in radians [0,Pi]
42 @param phi in radians [0,2*Pi] */
43 public Pointing(double theta, double phi)
44 { this.theta = theta; this.phi = phi; }
45
46 /** Conversion from {@link Vec3} */
47 public Pointing(Vec3 vec)
48 {
49 theta = FastMath.atan2(Math.sqrt(vec.x*vec.x+vec.y*vec.y),vec.z);
50 phi = FastMath.atan2 (vec.y,vec.x);
51 if (phi<0.) phi += 2*Math.PI;
52 if (phi>=2*Math.PI) phi -= 2*Math.PI;
53 }
54
55 /** Conversion from {@link Zphi} */
56 public Pointing (Zphi zphi)
57 {
58 double xy=Math.sqrt((1.-zphi.z)*(1.+zphi.z));
59 theta = FastMath.atan2(xy,zphi.z); phi=zphi.phi;
60 }
61 // for some reason, the alternative below is much slower...
62 //{ theta=FastMath.acos(zphi.z); phi=zphi.phi; }
63
64 /** Normalize theta range */
65 public void normalizeTheta()
66 {
67 theta=HealpixUtils.fmodulo(theta,2*Math.PI);
68 if (theta>Math.PI)
69 {
70 phi+=Math.PI;
71 theta=2*Math.PI-theta;
72 }
73 }
74
75 /** Normalize theta and phi ranges */
76 public void normalize()
77 {
78 normalizeTheta();
79 phi=HealpixUtils.fmodulo(phi,2*Math.PI);
80 }
81
82 public String toString()
83 {
84 StringBuilder s = new StringBuilder();
85 s.append("ptg(");s.append(theta);
86 s.append(",");s.append(phi);
87 s.append(")");
88 return s.toString();
89 }
90
91 public boolean equals(Object o)
92 {
93 if (this==o) return true;
94 if ((o==null) || (getClass()!=o.getClass())) return false;
95 Pointing pointing = (Pointing) o;
96 if (Double.compare(pointing.phi, phi) != 0) return false;
97 if (Double.compare(pointing.theta, theta) != 0) return false;
98 return true;
99 }
100
101 public int hashCode()
102 {
103 int result = Double.valueOf(theta).hashCode();
104 result = 31 * result + Double.valueOf(phi).hashCode();
105 return result;
106 }
107 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21 import java.util.NoSuchElementException;
22
23 /** Class for dealing with sets of integer ranges.
24 Ranges are described by the first element and the one-past-last element.
25 This code was inspired by Jan Kotek's "LongRangeSet" class, but has been
26 completely reimplemented.
27
28 @copyright 2011-2015 Max-Planck-Society
29 @author Martin Reinecke */
30 public class RangeSet
31 {
32 /** Interface describing an iterator for going through all values in
33 a RangeSet object. */
34 public interface ValueIterator {
35 public boolean hasNext();
36 public long next();
37 }
38
39 private static final ValueIterator EMPTY_ITER = new ValueIterator()
40 {
41 public boolean hasNext() { return false; }
42 public long next() { throw new NoSuchElementException(); }
43 };
44
45 /** Sorted list of interval boundaries. */
46 protected long[] r;
47 /** Current number of active entries. */
48 protected int sz;
49
50 /** Construct new object with initial space for 4 ranges. */
51 public RangeSet() { this(4); }
52 /** Construct new object with initial capacity for a given number of ranges.
53 @param cap number of initially reserved ranges. */
54 public RangeSet(int cap)
55 {
56 if (cap<0) throw new IllegalArgumentException("capacity must be positive");
57 r = new long[cap<<1];
58 sz=0;
59 }
60 /** Construct new object from an array of longs.
61 @param data */
62 public RangeSet(long[] data)
63 {
64 sz=data.length;
65 r = new long[sz];
66 System.arraycopy(data,0,r,0,sz);
67 checkConsistency();
68 }
69 /** Construct new object from another RangeSet
70 @param other */
71 public RangeSet(RangeSet other)
72 {
73 sz=other.sz;
74 r = new long[sz];
75 System.arraycopy(other.r,0,r,0,sz);
76 }
77
78 /** Checks the object for internal consistency. If a problem is detected,
79 an IllegalArgumentException is thrown. */
80 public void checkConsistency()
81 {
82 if ((sz&1)!=0)
83 throw new IllegalArgumentException("invalid number of entries");
84 for (int i=1; i<sz; ++i)
85 if (r[i]<=r[i-1])
86 throw new IllegalArgumentException("inconsistent entries");
87 }
88
89 private void resize(int newsize)
90 {
91 if (newsize<sz)
92 throw new IllegalArgumentException("requested array size too small");
93 if (newsize==r.length) return;
94 long[] rnew = new long[newsize];
95 System.arraycopy(r,0,rnew,0,sz);
96 r = rnew;
97 }
98
99 /** Make sure the object can hold at least the given number of entries. */
100 public void ensureCapacity(int cap)
101 { if (r.length<cap) resize (Math.max(2*r.length,cap)); }
102 /** Shrinks the array for the entries to minimum size. */
103 public void trimSize()
104 { resize(sz); }
105 /** Shrinks the array for the entries to minimum size, if it is more than
106 twice the minimum size */
107 public void trimIfTooLarge()
108 { if (r.length-sz>=sz) resize(sz); }
109
110 /** Returns an internal representation of the interval a number belongs to.
111 @param val number whose interval is requested
112 @return interval number, starting with -1 (smaller than all numbers in the
113 RangeSet), 0 (first "on" interval), 1 (first "off" interval etc.), up to
114 (and including) sz-1 (larger than all numbers in the RangeSet). */
115 private int iiv (long val)
116 {
117 int count=sz, first=0;
118 while (count>0)
119 {
120 int step=count>>>1, it = first+step;
121 if (r[it]<=val)
122 { first=++it; count-=step+1; }
123 else
124 count=step;
125 }
126 return first-1;
127 }
128
129 /** Append a single-value range to the object.
130 @param val value to append */
131 public void append(long val)
132 { append(val,val+1); }
133
134 /** Append a range to the object.
135 @param a first long in range
136 @param b one-after-last long in range */
137 public void append (long a, long b)
138 {
139 if (a>=b) return;
140 if ((sz>0) && (a<=r[sz-1]))
141 {
142 if (a<r[sz-2]) throw new IllegalArgumentException("bad append operation");
143 if (b>r[sz-1]) r[sz-1]=b;
144 return;
145 }
146 ensureCapacity(sz+2);
147
148 r[sz] = a;
149 r[sz+1] = b;
150 sz+=2;
151 }
152
153 /** Append an entire range set to the object. */
154 public void append (RangeSet other)
155 {
156 for (int i=0; i<other.sz; i+=2)
157 append(other.r[i],other.r[i+1]);
158 }
159
160 /** @return number of ranges in the set. */
161 public int nranges()
162 { return sz>>>1; }
163
164 /** @return true if no entries are stored, else false. */
165 public boolean isEmpty()
166 { return sz==0; }
167
168 /** @return first number in range iv. */
169 public long ivbegin(int iv)
170 { return r[2*iv]; }
171 /** @return one-past-last number in range iv. */
172 public long ivend(int iv)
173 { return r[2*iv+1]; }
174
175 /** Remove all entries in the set. */
176 public void clear()
177 { sz=0; }
178
179 /** Push a single entry at the end of the entry vector. */
180 private void pushv(long v)
181 { ensureCapacity(sz+1); r[sz++]=v; }
182
183 /** Estimate a good strategy for set operations involving two RangeSets. */
184 private static int strategy (int sza, int szb)
185 {
186 final double fct1 = 1.;
187 final double fct2 = 1.;
188 int slo = sza<szb ? sza : szb,
189 shi = sza<szb ? szb : sza;
190 double cost1 = fct1 * (sza+szb);
191 double cost2 = fct2 * slo * Math.max(1.,HealpixUtils.ilog2(shi));
192 return (cost1<=cost2) ? 1 : (slo==sza) ? 2 : 3;
193 }
194
195 private static boolean generalAllOrNothing1 (RangeSet a, RangeSet b,
196 boolean flip_a, boolean flip_b)
197 {
198 boolean state_a=flip_a, state_b=flip_b, state_res=state_a||state_b;
199 int ia=0, ea=a.sz, ib=0, eb=b.sz;
200 boolean runa = ia!=ea, runb = ib!=eb;
201 while(runa||runb)
202 {
203 long va = runa ? a.r[ia] : 0L,
204 vb = runb ? b.r[ib] : 0L;
205 boolean adv_a = runa && (!runb || (va<=vb)),
206 adv_b = runb && (!runa || (vb<=va));
207 if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
208 if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
209 if ((state_a||state_b)!=state_res)
210 return false;
211 }
212 return true;
213 }
214
215 private static boolean generalAllOrNothing2 (RangeSet a, RangeSet b,
216 boolean flip_a, boolean flip_b)
217 {
218 int iva = flip_a ? 0 : -1;
219 while (iva<a.sz)
220 {
221 if (iva==-1) // implies that flip_a==false
222 { if ((!flip_b)||(b.r[0]<a.r[0])) return false; }
223 else if (iva==a.sz-1) // implies that flip_a==false
224 { if ((!flip_b)||(b.r[b.sz-1]>a.r[a.sz-1])) return false; }
225 else
226 {
227 int ivb=b.iiv(a.r[iva]);
228 if ((ivb!=b.sz-1)&&(b.r[ivb+1]<a.r[iva+1])) return false;
229 if (flip_b==((ivb&1)==0)) return false;
230 }
231 iva+=2;
232 }
233 return true;
234 }
235
236 private static boolean generalAllOrNothing (RangeSet a, RangeSet b,
237 boolean flip_a, boolean flip_b)
238 {
239 if (a.isEmpty())
240 return flip_a ? true : b.isEmpty();
241 if (b.isEmpty())
242 return flip_b ? true : a.isEmpty();
243 int strat = strategy (a.nranges(), b.nranges());
244 return (strat==1) ? generalAllOrNothing1(a,b,flip_a,flip_b) :
245 ((strat==2) ? generalAllOrNothing2(a,b,flip_a,flip_b)
246 : generalAllOrNothing2(b,a,flip_b,flip_a));
247 }
248
249 /** Internal helper function for constructing unions, intersections
250 and differences of two RangeSets. */
251 private static RangeSet generalUnion1 (RangeSet a, RangeSet b,
252 boolean flip_a, boolean flip_b)
253 {
254 RangeSet res = new RangeSet();
255
256 boolean state_a=flip_a, state_b=flip_b, state_res=state_a||state_b;
257 int ia=0, ea=a.sz, ib=0, eb=b.sz;
258 boolean runa = ia!=ea, runb = ib!=eb;
259 while(runa||runb)
260 {
261 long va = runa ? a.r[ia] : 0L,
262 vb = runb ? b.r[ib] : 0L;
263 boolean adv_a = runa && (!runb || (va<=vb)),
264 adv_b = runb && (!runa || (vb<=va));
265 if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
266 if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
267 if ((state_a||state_b)!=state_res)
268 { res.pushv(adv_a ? va : vb); state_res = !state_res; }
269 }
270 return res;
271 }
272 /** Internal helper function for constructing unions, intersections
273 and differences of two RangeSets. */
274 private static RangeSet generalUnion2 (RangeSet a, RangeSet b,
275 boolean flip_a, boolean flip_b)
276 {
277 RangeSet res = new RangeSet();
278 int iva = flip_a ? 0 : -1;
279 while (iva<a.sz)
280 {
281 int ivb = (iva==-1) ? -1 : b.iiv(a.r[iva]);
282 boolean state_b = flip_b^((ivb&1)==0);
283 if ((iva>-1) && (!state_b)) res.pushv(a.r[iva]);
284 while((ivb<b.sz-1)&&((iva==a.sz-1)||(b.r[ivb+1]<a.r[iva+1])))
285 { ++ivb; state_b=!state_b; res.pushv(b.r[ivb]); }
286 if ((iva<a.sz-1)&&(!state_b)) res.pushv(a.r[iva+1]);
287 iva+=2;
288 }
289 return res;
290 }
291 private static RangeSet generalUnion (RangeSet a, RangeSet b,
292 boolean flip_a, boolean flip_b)
293 {
294 if (a.isEmpty())
295 return flip_a ? new RangeSet() : new RangeSet(b);
296 if (b.isEmpty())
297 return flip_b ? new RangeSet() : new RangeSet(a);
298 int strat = strategy (a.nranges(), b.nranges());
299 return (strat==1) ? generalUnion1(a,b,flip_a,flip_b) :
300 ((strat==2) ? generalUnion2(a,b,flip_a,flip_b)
301 : generalUnion2(b,a,flip_b,flip_a));
302 }
303
304 /** Return the union of this RangeSet and other. */
305 public RangeSet union (RangeSet other)
306 { return generalUnion (this,other,false,false); }
307 /** Return the intersection of this RangeSet and other. */
308 public RangeSet intersection (RangeSet other)
309 { return generalUnion (this,other,true,true); }
310 /** Return the difference of this RangeSet and other. */
311 public RangeSet difference (RangeSet other)
312 { return generalUnion (this,other,true,false); }
313
314 /** Returns true if a is contained in the set, else false. */
315 public boolean contains (long a)
316 { return ((iiv(a)&1)==0); }
317 /** Returns true if all numbers [a;b[ are contained in the set, else false. */
318 public boolean contains (long a,long b)
319 {
320 int res=iiv(a);
321 if ((res&1)!=0) return false;
322 return (b<=r[res+1]);
323 }
324 @Deprecated
325 public boolean containsAll (long a,long b)
326 { return contains(a,b); }
327 /** Returns true if any of the numbers [a;b[ are contained in the set,
328 else false. */
329 public boolean overlaps (long a,long b)
330 {
331 int res=iiv(a);
332 if ((res&1)==0) return true;
333 if (res==sz-1) return false; // beyond the end of the set
334 return (r[res+1]<b);
335 }
336 @Deprecated
337 public boolean containsAny (long a,long b)
338 { return overlaps(a,b); }
339 /** Returns true if the set completely contains "other", else false. */
340 public boolean contains (RangeSet other)
341 { return generalAllOrNothing(this,other,false,true); }
342 @Deprecated
343 public boolean containsAll (RangeSet other)
344 { return contains(other); }
345 /** Returns true if there is overlap between the set and "other",
346 else false. */
347 public boolean overlaps (RangeSet other)
348 { return !generalAllOrNothing(this,other,true,true); }
349 @Deprecated
350 public boolean containsAny (RangeSet other)
351 { return overlaps(other); }
352 /** Returns true the object represents an identical set of ranges as obj. */
353 public boolean equals(Object obj) {
354 if (this == obj)
355 return true;
356 if ((obj==null) || (!(obj instanceof RangeSet)))
357 return false;
358 RangeSet other = (RangeSet) obj;
359 if (other.sz!=sz) return false;
360 for (int i=0; i<sz; ++i)
361 if (other.r[i]!=r[i]) return false;
362 return true;
363 }
364 public int hashCode()
365 {
366 int result = Integer.valueOf(sz).hashCode();
367 for (int i=0; i<sz; ++i)
368 result = 31 * result + Long.valueOf(r[sz]).hashCode();
369 return result;
370 }
371
372 /** @return total number of values (not ranges) in the set. */
373 public long nval()
374 {
375 long res = 0;
376 for (int i=0; i<sz; i+=2)
377 res+=r[i+1]-r[i];
378 return res;
379 }
380
381 /** Internal helper function for building unions and differences of the
382 RangeSet with a single range. */
383 private void addRemove (long a, long b, int v)
384 {
385 int pos1=iiv(a), pos2=iiv(b);
386 if ((pos1>=0) && (r[pos1]==a)) --pos1;
387 // first to delete is at pos1+1; last is at pos2
388 boolean insert_a = (pos1&1)==v;
389 boolean insert_b = (pos2&1)==v;
390 int rmstart=pos1+1+(insert_a ? 1 : 0);
391 int rmend =pos2-(insert_b?1:0);
392
393 if (((rmend-rmstart)&1)==0)
394 throw new IllegalArgumentException("cannot happen: "+rmstart+" "+rmend);
395
396 if (insert_a && insert_b && (pos1+1>pos2)) // insert
397 {
398 ensureCapacity(sz+2);
399 System.arraycopy(r,pos1+1,r,pos1+3,sz-pos1-1); // move to right
400 r[pos1+1]=a;
401 r[pos1+2]=b;
402 sz+=2;
403 }
404 else
405 {
406 if (insert_a) r[pos1+1]=a;
407 if (insert_b) r[pos2]=b;
408 if (rmstart!=rmend+1)
409 System.arraycopy(r,rmend+1,r,rmstart,sz-rmend-1); // move to left
410 sz-=rmend-rmstart+1;
411 }
412 }
413
414 /** After this operation, the RangeSet contains the intersection of itself and
415 [a;b[. */
416 public void intersect (long a, long b)
417 {
418 int pos1=iiv(a), pos2=iiv(b);
419 if ((pos2>=0) && (r[pos2]==b)) --pos2;
420 // delete all up to pos1 (inclusive); and starting from pos2+1
421 boolean insert_a = (pos1&1)==0;
422 boolean insert_b = (pos2&1)==0;
423
424 // cut off end
425 sz=pos2+1;
426 if (insert_b) r[sz++]=b;
427
428 // erase start
429 if (insert_a) r[pos1--]=a;
430 if (pos1>=0)
431 System.arraycopy(r,pos1+1,r,0,sz-pos1-1); // move to left
432
433 sz-=pos1+1;
434 if ((sz&1)!=0)
435 throw new IllegalArgumentException("cannot happen");
436 }
437
438 /** After this operation, the RangeSet contains the union of itself and
439 [a;b[. */
440 public void add (long a, long b)
441 { if ((sz==0)||(a>=r[sz-1])) append(a,b); else addRemove(a,b,1); }
442 /** After this operation, the RangeSet contains the union of itself and
443 [a;a+1[. */
444 public void add (long a)
445 { if ((sz==0)||(a>=r[sz-1])) append(a,a+1); else addRemove(a,a+1,1); }
446 /** After this operation, the RangeSet contains the difference of itself and
447 [a;b[. */
448 public void remove (long a, long b)
449 { addRemove(a,b,0); }
450 /** After this operation, the RangeSet contains the difference of itself and
451 [a;a+1[. */
452 public void remove (long a)
453 { addRemove(a,a+1,0); }
454
455 /** Creates an array containing all the numbers in the RangeSet.
456 Not recommended, because the arrays can become prohibitively large.
457 It is preferrable to use a ValueIterator or explicit loops. */
458 public long[] toArray(){
459 long[] res = new long[(int)nval()];
460 int ofs=0;
461 for (int i=0; i<sz; i+=2)
462 for (long j=r[i]; j<r[i+1]; ++j)
463 res[ofs++]=j;
464 return res;
465 }
466 public static RangeSet fromArray(long[]v){
467 RangeSet res = new RangeSet();
468 for (int i=0; i<v.length; i++)
469 res.append(v[i]);
470 return res;
471 }
472
473 public String toString()
474 {
475 StringBuilder s = new StringBuilder();
476 s.append("{ ");
477 for (int i=0; i<sz; i+=2)
478 {
479 s.append("[").append(r[i]).append(";").append(r[i + 1]).append("[");
480 if (i<sz-2) s.append(",");
481 }
482 s.append(" }");
483 return s.toString();
484 }
485
486 /** Returns a ValueIterator, which iterates over all individual numbers
487 in the RangeSet. */
488 public ValueIterator valueIterator()
489 {
490 if(sz == 0) return EMPTY_ITER;
491 return new ValueIterator()
492 {
493 int pos = 0;
494 long value = (sz>0) ? r[0] : 0;
495
496 public boolean hasNext()
497 { return (pos<sz); }
498
499 public long next() {
500 if (pos>sz)
501 throw new NoSuchElementException();
502 long ret = value;
503 if (++value==r[pos+1])
504 {
505 pos+=2;
506 if (pos<sz)
507 value = r[pos];
508 }
509 return ret;
510 }
511 };
512 }
513
514 /** Returns a compressed representation of the RangeSet, using interpolative
515 coding. */
516 public byte[] toCompressed() throws Exception
517 { return Compressor.interpol_encode (r, 0, sz); }
518 /** Returns a RangeSet obtained by decompressing a byte array which was
519 originally generated by toCompressed(). */
520 public static RangeSet fromCompressed (byte[] data) throws Exception
521 { return new RangeSet(Compressor.interpol_decode(data)); }
522 }
0 package healpix.essentials;
1
2 /** The Healpix pixel ordering scheme. */
3 public enum Scheme {
4 /** RING ordering. */
5 RING,
6 /** NESTED ordering. */
7 NESTED
8 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Cartesian 3-vector.
23 Instead of using the javax.vecmath.Vector3d class, this separate class was
24 implemented for two reasons: first, to avoid the external dependency from
25 vecmath.jar, and also because the function Vector3d.angle(Vector3d v1) is
26 too inaccurate for usage in Healpix for very small angles.
27
28 @copyright (C) 2011-2015 Max-Planck-Society
29 @author Martin Reinecke */
30 public class Vec3
31 {
32 public double x, y, z;
33
34 /** Default constructor. */
35 public Vec3() {}
36
37 public Vec3 (Vec3 v)
38 { x=v.x; y=v.y; z=v.z; }
39 /** Creation from individual components */
40 public Vec3 (double x1, double y1, double z1)
41 { x=x1; y=y1; z=z1; }
42 /** Conversion from {@link Pointing} */
43 public Vec3 (Pointing ptg)
44 {
45 double sth = FastMath.sin(ptg.theta);
46 x=sth*FastMath.cos(ptg.phi);
47 y=sth*FastMath.sin(ptg.phi);
48 z=FastMath.cos(ptg.theta);
49 }
50 /** Conversion from {@link Zphi} */
51 public Vec3 (Zphi zphi)
52 {
53 double sth = Math.sqrt((1.0-zphi.z)*(1.0+zphi.z));
54 x=sth*FastMath.cos(zphi.phi);
55 y=sth*FastMath.sin(zphi.phi);
56 z=zphi.z;
57 }
58
59 public Vec3 (double[] arr)
60 {
61 if(arr.length!=3) throw new IllegalArgumentException("Wrong array size");
62 x = arr[0]; y = arr[1]; z = arr[2];
63 }
64
65 /** Vector length
66 @return the length of the vector. */
67 public final double length()
68 { return Math.sqrt(lengthSquared()); }
69
70 /** Squared vector length
71 @return the squared length of the vector. */
72 public final double lengthSquared()
73 { return x*x + y*y + z*z; }
74
75 /** Normalize the vector */
76 public void normalize()
77 {
78 double d = 1./length();
79 x *= d; y *= d; z *= d;
80 }
81 /** Return normalized vector */
82 public Vec3 norm()
83 {
84 double d = 1./length();
85 return new Vec3(x*d,y*d,z*d);
86 }
87
88 /** Angle between two vectors.
89 @param v1 another vector
90 @return the angle in radians between this vector and {@code v1};
91 constrained to the range [0,PI]. */
92 public final double angle(Vec3 v1)
93 { return FastMath.atan2(cross(v1).length(), dot(v1)); }
94
95 /** Vector cross product.
96 @param v another vector
97 @return the vector cross product between this vector and {@code v} */
98 public Vec3 cross(Vec3 v)
99 { return new Vec3(y*v.z - v.y*z, z*v.x - v.z*x, x*v.y - v.x*y); }
100
101 /** Vector scaling.
102 * @param n the scale number to be multiply to the coordinates {@code x,y,z}
103 * @return the vector with coordinates multiplied by {@code n}
104 */
105 public Vec3 mul(double n)
106 { return new Vec3(n*x, n*y, n*z); }
107
108 /** Invert the signs of all components */
109 public void flip()
110 { x=-x; y=-y; z=-z; }
111 public Vec3 flipped()
112 { return new Vec3(-x,-y,-z); }
113
114 /** Scale the vector by a given factor
115 @param n the scale factor */
116 public void scale(double n)
117 { x*=n; y*=n; z*=n; }
118
119 /** Computes the dot product of the this vector and {@code v1}.
120 * @param v1 another vector
121 * @return dot product */
122 public final double dot(Vec3 v1)
123 { return x*v1.x + y*v1.y + z*v1.z; }
124
125 /** Vector addition
126 * @param v the vector to be added
127 * @return addition result */
128 public Vec3 add(Vec3 v)
129 { return new Vec3(x+v.x, y+v.y, z+v.z); }
130
131 /** Vector subtraction
132 * @param v the vector to be subtracted
133 * @return subtraction result */
134 public Vec3 sub(Vec3 v)
135 { return new Vec3(x-v.x, y-v.y, z-v.z); }
136
137 public String toString()
138 {
139 StringBuilder s = new StringBuilder();
140 s.append("vec3(");s.append(x);
141 s.append(",");s.append(y);
142 s.append(",");s.append(z);
143 s.append(")");
144 return s.toString();
145 }
146
147 public double[] toArray()
148 { return new double[]{x,y,z}; }
149
150 public void toArray(double[] arr)
151 {
152 if(arr.length!=3) throw new IllegalArgumentException("wrong array size");
153 arr[0] = x; arr[1] = y; arr[2] = z;
154 }
155
156 public boolean equals(Object o)
157 {
158 if (this == o) return true;
159 if (o == null || getClass() != o.getClass()) return false;
160 Vec3 vec3 = (Vec3) o;
161 if (Double.compare(vec3.x, x) != 0) return false;
162 if (Double.compare(vec3.y, y) != 0) return false;
163 if (Double.compare(vec3.z, z) != 0) return false;
164 return true;
165 }
166
167 public int hashCode()
168 {
169 int result = Double.valueOf(x).hashCode();
170 result = 31 * result + Double.valueOf(y).hashCode();
171 result = 31 * result + Double.valueOf(z).hashCode();
172 return result;
173 }
174 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19
20 package healpix.essentials;
21
22 /** Class for storing a position on the unit sphere as a (z,phi)-tuple.
23
24 @copyright (C) 2011 Max-Planck-Society
25 @author Martin Reinecke */
26 public final class Zphi
27 {
28 /** Cosine of the colatitude, or z component of unit vector; Range [-1;1]. */
29 public double z;
30
31 /** Longitude in radians; Range [0; 2Pi]. */
32 public double phi;
33
34 /** Default constructor */
35 public Zphi() {}
36
37 /** Creation from individual components */
38 public Zphi (double z_, double phi_)
39 { z=z_; phi=phi_; }
40
41 /** Conversion from {@link Vec3} */
42 public Zphi (Vec3 v)
43 { z = v.z/v.length(); phi = FastMath.atan2(v.y,v.x); }
44
45 /** Conversion from {@link Pointing} */
46 public Zphi (Pointing ptg)
47 { z = FastMath.cos(ptg.theta); phi=ptg.phi; }
48
49 public String toString()
50 {
51 StringBuilder s = new StringBuilder();
52 s.append("zphi(");s.append(z);
53 s.append(",");s.append(phi);
54 s.append(")");
55 return s.toString();
56 }
57
58 public boolean equals(Object o)
59 {
60 if (this == o) return true;
61 if (o == null || getClass() != o.getClass()) return false;
62 Zphi zphi = (Zphi) o;
63 if (Double.compare(zphi.phi, phi) != 0) return false;
64 if (Double.compare(zphi.z, z) != 0) return false;
65 return true;
66 }
67
68 public int hashCode()
69 {
70 long temp = z != +0.0d ? Double.doubleToLongBits(z) : 0L;
71 int result = (int) (temp ^ (temp >>> 32));
72 temp = phi != +0.0d ? Double.doubleToLongBits(phi) : 0L;
73 result = 31 * result + (int) (temp ^ (temp >>> 32));
74 return result;
75 }
76 }
0 /**
1 Package implementing essential HEALPix functionality.<br>
2 healpix.essentials is a Java package aiming to combine the advantages
3 of other Java HEALPix libraries like
4 the gov.fnal.eag.healpix package by N. Kuropatkin
5 (<a href="http://home.fnal.gov/~kuropat/HEALPIX/PixTools.html">http://home.fnal.gov/~kuropat/HEALPIX/PixTools.html</a>),
6 Jan Kotek's org.asterope.healpix package
7 (<a href="https://github.com/jankotek/HEALPix">https://github.com/jankotek/HEALPix</a>),
8 and the healpix.core package developed at ESO.
9 <br>
10 Current features include:
11 <ul>
12 <li>close similarities with Healpix_Base_T class from Healpix C++, which allows
13 simultaneous development and bug fixes for both.
14 <li>support for arbitrary positive Nside values in RING scheme; no longer
15 limited to powers of 2
16 <li>maximum supported Nside value: 2^29
17 <li>significant performance improvements: most methods have been accelerated
18 by integral factors, some by more than an order of magnitude.
19 <li>re-implementation of queryDisc and queryPolygon:
20 <ul>
21 <li> query methods return RangeSet objects which allow much more compact
22 storage of the result
23 <li> new native query methods for NESTED ordering; these are slower than those
24 for RING ordering, but much quicker than converting all pixels from a RING
25 result to NESTED.
26 <li> inclusive queries have been improved: several bugs were fixed, and the
27 number of false positives in the result has been reduced. Users can now
28 choose between quick inclusive queries returning more false positives,
29 and slower ones returning fewer false positives.
30 </ul>
31 <li> the HealpixProc class offers a procedural (instead of object-oriented)
32 interface to the HealpixBase functionality, which simplifies transition
33 for users of the "Healpix" and "PixTools" classes.
34 NOTE: this only works for Nside parameters which are powers of 2
35 <li> many bug fixes
36 <li> no external library dependencies, except for "nom.tam.fits" if FITS I/O is
37 required
38 <li> the code base is thread-safe in the following sense:
39 <ul>
40 <li> HealpixProc methods can be called concurrently
41 <li> HealpixBase methods can be called concurrently on different objects
42 </ul>
43 </ul>
44 @copyright 2011, 2012 Max-Planck-Society
45 @author Martin Reinecke
46 */
47 package healpix.essentials;
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import healpix.essentials.Compressor;
22 import junit.framework.TestCase;
23 import java.io.*;
24 import java.util.Random;
25
26 /** Tests for the linear interpolative coding compression
27
28 @copyright 2015 Max-Planck-Society
29 @author Martin Reinecke */
30 public class CompressorTest extends TestCase {
31
32 public void testCompressDecompress() throws Exception
33 {
34 int num=100000;
35 Random randomGenerator = new Random();
36 long[] input=new long[num];
37 input[0]=0;
38 for (int i=1; i<num; ++i) input[i]=input[i-1]+1+randomGenerator.nextInt(100);
39 byte[] compressed=Compressor.interpol_encode(input,0,input.length);
40 long[] output=Compressor.interpol_decode(compressed);
41 assertEquals("inconsistency",input.length,output.length);
42 for (int i=0; i<output.length; ++i)
43 assertEquals("inconsistency",input[i],output[i]);
44 }
45 }
0 package healpix.essentials.test;
1
2 import junit.framework.TestCase;
3 import java.text.DecimalFormat;
4 import static healpix.essentials.FastMath.*;
5
6 /** FastMath benchmarking code
7
8 @copyright 2014 Max-Planck-Society
9 @author Martin Reinecke */
10 public class FastMathPerfTest extends TestCase
11 {
12 static private final DecimalFormat form = new DecimalFormat("##0.00");
13 final int ncomp=10000000;
14
15 public void test_perf_math()
16 {
17 System.out.println("Rough performance test of math functions");
18 long cnt, tstart;
19 double dummy=0, di, time;
20 di=1./ncomp;
21 tstart = System.nanoTime();
22 cnt=0;
23 for (double i=0; i<1; i+=di)
24 { dummy+=Math.sqrt(i); ++cnt; }
25 time = 1e-9*(System.nanoTime()-tstart);
26 System.out.println("sqrt: " + form.format(cnt/time*1e-6) + "MOps/s");
27 di=4*Math.PI/ncomp;
28 tstart = System.nanoTime();
29 cnt=0;
30 for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
31 { dummy+=Math.sin(i); ++cnt; }
32 time = 1e-9*(System.nanoTime()-tstart);
33 System.out.println("sin : " + form.format(cnt/time*1e-6) + "MOps/s");
34 tstart = System.nanoTime();
35 cnt=0;
36 for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
37 { dummy+=Math.cos(i); ++cnt; }
38 time = 1e-9*(System.nanoTime()-tstart);
39 System.out.println("cos : " + form.format(cnt/time*1e-6) + "MOps/s");
40 di=2./ncomp;
41 tstart = System.nanoTime();
42 cnt=0;
43 for (double i=-1; i<1; i+=di)
44 { dummy+=Math.acos(i); ++cnt; }
45 time = 1e-9*(System.nanoTime()-tstart);
46 System.out.println("acos: " + form.format(cnt/time*1e-6) + "MOps/s");
47 di=1000./ncomp;
48 tstart = System.nanoTime();
49 cnt=0;
50 for (double i=-500; i<500; i+=di)
51 { dummy+=Math.atan(i); ++cnt; }
52 time = 1e-9*(System.nanoTime()-tstart);
53 System.out.println("atan: " + form.format(cnt/time*1e-6) + "MOps/s");
54 di=1000./ncomp;
55 tstart = System.nanoTime();
56 cnt=0;
57 for (double i=-500; i<500; i+=di)
58 { dummy+=Math.atan2(i,2.9); ++cnt; }
59 time = 1e-9*(System.nanoTime()-tstart);
60 System.out.println("atan2: " + form.format(cnt/time*1e-6) + "MOps/s");
61 di=1000./ncomp;
62 }
63 public void test_perf_fastmath()
64 {
65 System.out.println("Rough performance test of fast math functions");
66 long cnt,tstart;
67 double dummy=0, di, time;
68 di=4*Math.PI/ncomp;
69 tstart = System.nanoTime();
70 cnt=0;
71 for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
72 { dummy+=sin(i); ++cnt; }
73 time = 1e-9*(System.nanoTime()-tstart);
74 System.out.println("sin : " + form.format(cnt/time*1e-6) + "MOps/s");
75 tstart = System.nanoTime();
76 cnt=0;
77 for (double i=-2*Math.PI; i<2*Math.PI; i+=di)
78 { dummy+=cos(i); ++cnt; }
79 time = 1e-9*(System.nanoTime()-tstart);
80 System.out.println("cos : " + form.format(cnt/time*1e-6) + "MOps/s");
81 di=2./ncomp;
82 tstart = System.nanoTime();
83 cnt=0;
84 for (double i=-1; i<1; i+=di)
85 { dummy+=acos(i); ++cnt; }
86 time = 1e-9*(System.nanoTime()-tstart);
87 System.out.println("acos: " + form.format(cnt/time*1e-6) + "MOps/s");
88 di=1000./ncomp;
89 tstart = System.nanoTime();
90 cnt=0;
91 for (double i=-500; i<500; i+=di)
92 { dummy+=atan(i); ++cnt; }
93 time = 1e-9*(System.nanoTime()-tstart);
94 System.out.println("atan: " + form.format(cnt/time*1e-6) + "MOps/s");
95 di=1000./ncomp;
96 tstart = System.nanoTime();
97 cnt=0;
98 for (double i=-500; i<500; i+=di)
99 { dummy+=atan2(i,2.9); ++cnt; }
100 time = 1e-9*(System.nanoTime()-tstart);
101 System.out.println("atan2: " + form.format(cnt/time*1e-6) + "MOps/s");
102 }
103 }
0 package healpix.essentials.test;
1
2 import junit.framework.TestCase;
3 import java.text.DecimalFormat;
4 import static healpix.essentials.FastMath.*;
5
6 /** A class to perform correctness and speed tests for FastMath class
7 *
8 * @author Naoki Shibata
9 */
10 public class FastMathTest extends TestCase
11 {
12 private static final double p0=+0.0, m0=-0.0, pinf=Double.POSITIVE_INFINITY,
13 minf=Double.NEGATIVE_INFINITY, nan=Double.NaN;
14
15 private static boolean isPlusZero(double x)
16 { return x == 0 && Math.copySign(1, x) == 1; }
17 private static boolean isMinusZero(double x)
18 { return x == 0 && Math.copySign(1, x) == -1; }
19
20 private static boolean cmpDenorm(double x, double y) {
21 if (Double.isNaN(x) && Double.isNaN(y)) return true;
22 if (x == pinf && y == pinf) return true;
23 if (x == minf && y == minf) return true;
24 if (!Double.isNaN(x) && !Double.isNaN(y) &&
25 !Double.isInfinite(x) && !Double.isInfinite(y))
26 return true;
27 return false;
28 }
29
30 private static void ulptest (double v1, double v2, double ulp)
31 { assertTrue ("inconsistency",Math.abs((v1-v2)/Math.ulp(v2))<=ulp); }
32
33 private static void check1 (double d)
34 {
35 ulptest (sin(d),Math.sin(d),2.);
36 ulptest (cos(d),Math.cos(d),2.);
37 ulptest (atan(d),Math.atan(d),2.);
38 }
39 private static void check2 (double d)
40 {
41 ulptest (asin(d),Math.asin(d),3.);
42 ulptest (acos(d),Math.acos(d),2.);
43 }
44
45 public void testmain() throws Exception
46 {
47 assertEquals("inconsistency", Math.PI,(atan2(p0, m0)));
48 assertEquals("inconsistency",-Math.PI,(atan2(m0, m0)));
49 assertTrue("inconsistency",isPlusZero(atan2(p0, p0)));
50 assertTrue("inconsistency",isMinusZero(atan2(m0, p0)));
51 assertEquals("inconsistency",3*Math.PI/4,atan2(pinf, minf));
52 assertEquals("inconsistency",-3*Math.PI/4,atan2(minf, minf));
53 assertEquals("inconsistency",Math.PI/4,atan2(pinf, pinf));
54 assertEquals("inconsistency",-Math.PI/4,atan2(minf, pinf));
55 assertTrue("inconsistency",Double.isNaN(atan2(nan,nan)));
56
57 double[] a = { 100000.5, 100000, 3, 2.5, 2, 1.5, 1.0, 0.5 };
58 double[] b = { nan, pinf, minf };
59 double[] c = { nan, pinf, minf, 2, -2 };
60
61 for(int i=0;i<a.length;i++)
62 {
63 assertEquals("inconsistency",Math.PI,atan2(p0, -a[i]));
64 assertEquals("inconsistency",-Math.PI,atan2(m0, -a[i]));
65 assertEquals("inconsistency",-Math.PI/2,atan2(-a[i], p0));
66 assertEquals("inconsistency",-Math.PI/2,atan2(-a[i], m0));
67 assertEquals("inconsistency",Math.PI/2,atan2(a[i], p0));
68 assertEquals("inconsistency",Math.PI/2,atan2(a[i], m0));
69 assertEquals("inconsistency",Math.PI/2,atan2(pinf,a[i]));
70 assertEquals("inconsistency",Math.PI/2,atan2(pinf,-a[i]));
71 assertEquals("inconsistency",-Math.PI/2,atan2(minf,a[i]));
72 assertEquals("inconsistency",-Math.PI/2,atan2(minf,-a[i]));
73 assertEquals("inconsistency",Math.PI,atan2(a[i],minf));
74 assertEquals("inconsistency",-Math.PI,atan2(-a[i],minf));
75 assertEquals("inconsistency",p0,atan2(a[i],pinf));
76 assertEquals("inconsistency",m0,atan2(-a[i],pinf));
77 assertTrue("inconsistency",Double.isNaN(atan2(a[i],nan)));
78 assertTrue("inconsistency",Double.isNaN(atan2(-a[i],nan)));
79 assertTrue("inconsistency",Double.isNaN(atan2(nan,a[i])));
80 assertTrue("inconsistency",Double.isNaN(atan2(nan,-a[i])));
81 }
82
83 for(int i=0;i<b.length;i++)
84 {
85 assertTrue("inconsistency",cmpDenorm(sin(b[i]), Math.sin(b[i])));
86 assertTrue("inconsistency",cmpDenorm(cos(b[i]), Math.cos(b[i])));
87 assertTrue("inconsistency",cmpDenorm(atan(b[i]), Math.atan(b[i])));
88 }
89 for(int i=0;i<c.length;i++)
90 {
91 assertTrue("inconsistency",cmpDenorm(asin(c[i]), Math.asin(c[i])));
92 assertTrue("inconsistency",cmpDenorm(acos(c[i]), Math.acos(c[i])));
93 }
94
95 for(double d = -10;d < 10;d += 0.000001)
96 check1(d);
97 for(double d = -10000;d < 10000;d += 0.001)
98 check1(d);
99
100 for(double d = -1;d < 1;d += 0.0000001)
101 check2(d);
102
103 for(double y = -10;y < 10;y += 0.01)
104 for(double x = -10;x < 10;x += 0.01)
105 ulptest (atan2(y,x),Math.atan2(y,x),2.);
106 for(double y = -1000;y < 1000;y += 1.01)
107 for(double x = -1000;x < 1000;x += 1.01)
108 ulptest (atan2(y,x),Math.atan2(y,x),2.);
109 }
110 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import healpix.essentials.*;
22
23 import junit.framework.TestCase;
24 import java.util.UUID;
25 import java.io.File;
26
27 /** Tests for the FitsUtil class
28
29 @copyright 2014 Max-Planck-Society
30 @author Martin Reinecke */
31 public class FitsUtilTest extends TestCase
32 {
33 public void testHPmapf() throws Exception
34 {
35 String name = UUID.randomUUID().toString()+".fits";
36 HealpixMapFloat hpmf = new HealpixMapFloat(128,Scheme.NESTED);
37 for (long i=0; i<hpmf.getNpix(); ++i)
38 hpmf.setPixel(i,(float)i);
39 FitsUtil.writeFloatMap(hpmf,name);
40 hpmf.setNsideAndScheme (64, Scheme.RING);
41 hpmf=FitsUtil.getFloatMap(name,2,1);
42 new File(name).delete();
43 assertEquals("Scheme problem",Scheme.NESTED,hpmf.getScheme());
44 assertEquals("Nside problem",128,hpmf.getNside());
45 for (long i=0; i<hpmf.getNpix(); ++i)
46 assertEquals("Value problem",(float)i,hpmf.getPixel(i));
47 }
48 public void testHPmapd() throws Exception
49 {
50 String name = UUID.randomUUID().toString()+".fits";
51 HealpixMapDouble hpmd = new HealpixMapDouble(128,Scheme.NESTED);
52 for (long i=0; i<hpmd.getNpix(); ++i)
53 hpmd.setPixel(i,(double)i);
54 FitsUtil.writeDoubleMap(hpmd,name);
55 hpmd.setNsideAndScheme (64, Scheme.RING);
56 hpmd=FitsUtil.getDoubleMap(name,2,1);
57 new File(name).delete();
58 assertEquals("Scheme problem",Scheme.NESTED,hpmd.getScheme());
59 assertEquals("Nside problem",128,hpmd.getNside());
60 for (long i=0; i<hpmd.getNpix(); ++i)
61 assertEquals("Value problem",(double)i,hpmd.getPixel(i));
62 }
63 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import junit.framework.TestCase;
22 import java.util.Random;
23
24 import healpix.essentials.*;
25
26 /** Tests for the Fxyf class
27
28 @copyright 2015 Max-Planck-Society
29 @author Martin Reinecke */
30 public class FxyfTest extends TestCase {
31
32 public void testFxyf() throws Exception
33 {
34 System.out.println("Testing Fxyf");
35 for (int i=0; i<12; ++i)
36 for (int j=0; j<=100; ++j)
37 for (int k=0; k<=100; ++k)
38 {
39 double fx=(0.01*j)*(1-1e-14)+.5e-14,
40 fy=(0.01*k)*(1-1e-14)+.5e-14;
41 Fxyf res=new Fxyf(new Fxyf(fx,fy,i).toVec3());
42 assertEquals (res.face,i);
43 assertEquals (res.fx,fx,5e-15);
44 assertEquals (res.fy,fy,5e-15);
45 }
46 }
47
48 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import junit.framework.TestCase;
22 import java.text.DecimalFormat;
23
24 import healpix.essentials.*;
25
26 /** Benchmarks for the HealpixBase class
27
28 @copyright 2014 Max-Planck-Society
29 @author Martin Reinecke */
30 public class HealpixBasePerfTest extends TestCase
31 {
32 static private final DecimalFormat form = new DecimalFormat("##0.00");
33 static private final int nsteps=100000; // influences number of performance tests
34
35 private double subtest_perf_neighbours(String name, Scheme scheme)
36 throws Exception
37 {
38 long cnt=0;
39 double dummy=0;
40 long tstart = System.nanoTime();
41 int omax=HealpixBase.order_max;
42 for (int order=0; order<=omax; ++order)
43 {
44 HealpixBase base = new HealpixBase (1L<<order,scheme);
45 long dpix=Math.max(base.getNpix()/nsteps,1L);
46 for (long pix=0; pix<base.getNpix(); pix+=dpix)
47 {
48 long nres[] = base.neighbours(pix);
49 dummy+=nres[0];
50 ++cnt;
51 }
52 }
53 double time = 1e-9*(System.nanoTime()-tstart);
54 System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
55 return dummy;
56 }
57
58 private double subtest_perf_pix2ang(String name, Scheme scheme)
59 throws Exception
60 {
61 long cnt=0;
62 double dummy=0;
63 long tstart = System.nanoTime();
64 int omax=HealpixBase.order_max;
65 for (int order=0; order<=omax; ++order)
66 {
67 HealpixBase base = new HealpixBase (1L<<order,scheme);
68 long dpix=Math.max(base.getNpix()/nsteps,1L);
69 for (long pix=0; pix<base.getNpix(); pix+=dpix)
70 {
71 Pointing p=base.pix2ang(pix);
72 dummy+=p.theta+p.phi;
73 ++cnt;
74 }
75 }
76 double time = 1e-9*(System.nanoTime()-tstart);
77 System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
78 return dummy;
79 }
80
81 private double subtest_perf_pix2vec(String name, Scheme scheme)
82 throws Exception
83 {
84 long cnt=0;
85 double dummy=0;
86 long tstart = System.nanoTime();
87 int omax=HealpixBase.order_max;
88 for (int order=0; order<=omax; ++order)
89 {
90 HealpixBase base = new HealpixBase (1L<<order,scheme);
91 long dpix=Math.max(base.getNpix()/nsteps,1L);
92 for (long pix=0; pix<base.getNpix(); pix+=dpix)
93 {
94 Vec3 v=base.pix2vec(pix);
95 dummy+=v.x+v.y+v.z;
96 ++cnt;
97 }
98 }
99 double time = 1e-9*(System.nanoTime()-tstart);
100 System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
101 return dummy;
102 }
103
104 private double subtest_perf_pix2zphi(String name, Scheme scheme)
105 throws Exception
106 {
107 long cnt=0;
108 double dummy=0;
109 long tstart = System.nanoTime();
110 int omax=HealpixBase.order_max;
111 for (int order=0; order<=omax; ++order)
112 {
113 HealpixBase base = new HealpixBase (1L<<order,scheme);
114 long dpix=Math.max(base.getNpix()/nsteps,1L);
115 for (long pix=0; pix<base.getNpix(); pix+=dpix)
116 {
117 Zphi blah=base.pix2zphi(pix);
118 dummy+=blah.z;
119 ++cnt;
120 }
121 }
122 double time = 1e-9*(System.nanoTime()-tstart);
123 System.out.println(name + ": " + form.format(cnt/time*1e-6) + "MOps/s");
124 return dummy;
125 }
126
127 private double subtest_perf_ring2nest() throws Exception
128 {
129 long cnt=0;
130 double dummy=0;
131 long tstart = System.nanoTime();
132 int omax=HealpixBase.order_max;
133 for (int order=0; order<=omax; ++order)
134 {
135 HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
136 long dpix=Math.max(base.getNpix()/nsteps,1L);
137 for (long pix=0; pix<base.getNpix(); pix+=dpix)
138 {
139 dummy+=base.ring2nest(pix);
140 ++cnt;
141 }
142 }
143 double time = 1e-9*(System.nanoTime()-tstart);
144 System.out.println("ring2nest : " + form.format(cnt/time*1e-6) + "MOps/s");
145 return dummy;
146 }
147
148 private double subtest_perf_nest2ring() throws Exception
149 {
150 long cnt=0;
151 double dummy=0;
152 long tstart = System.nanoTime();
153 int omax=HealpixBase.order_max;
154 for (int order=0; order<=omax; ++order)
155 {
156 HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
157 long dpix=Math.max(base.getNpix()/nsteps,1L);
158 for (long pix=0; pix<base.getNpix(); pix+=dpix)
159 {
160 dummy+=base.nest2ring(pix);
161 ++cnt;
162 }
163 }
164 double time = 1e-9*(System.nanoTime()-tstart);
165 System.out.println("nest2ring : " + form.format(cnt/time*1e-6) + "MOps/s");
166 return dummy;
167 }
168
169 private double subtest_perf_ang2pix(String name, Scheme scheme)
170 throws Exception
171 {
172 long cnt=0;
173 double dummy=0;
174 long tstart = System.nanoTime();
175 int omax=HealpixBase.order_max;
176 double dth=Math.PI/Math.sqrt(nsteps);
177 double dph=Constants.twopi/Math.sqrt(nsteps);
178 for (int order=0; order<=omax; ++order)
179 {
180 HealpixBase base = new HealpixBase (1L<<order,scheme);
181 for (double theta=0; theta<Math.PI; theta+=dth)
182 for (double phi=0; phi<2*Math.PI; phi+=dph)
183 {
184 dummy+=base.ang2pix(new Pointing(theta+1e-15*phi,phi));
185 ++cnt;
186 }
187 }
188 double time = 1e-9*(System.nanoTime()-tstart);
189 System.out.println(name+": " + form.format(cnt/time*1e-6) + "MOps/s");
190 return dummy;
191 }
192
193 private double subtest_perf_zphi2pix(String name, Scheme scheme)
194 throws Exception
195 {
196 long cnt=0;
197 double dummy=0;
198 long tstart = System.nanoTime();
199 int omax=HealpixBase.order_max;
200 double dz=2./Math.sqrt(nsteps);
201 double dph=Constants.twopi/Math.sqrt(nsteps);
202 for (int order=0; order<=omax; ++order)
203 {
204 HealpixBase base = new HealpixBase (1L<<order,scheme);
205 for (double z=-1; z<1; z+=dz)
206 for (double phi=0; phi<Constants.twopi; phi+=dph)
207 {
208 dummy+=base.zphi2pix(new Zphi(z,phi));
209 ++cnt;
210 }
211 }
212 double time = 1e-9*(System.nanoTime()-tstart);
213 System.out.println(name+": " + form.format(cnt/time*1e-6) + "MOps/s");
214 return dummy;
215 }
216
217 private double subtest_perf_query_disc(String name,
218 Scheme scheme) throws Exception
219 {
220 long cnt=0;
221 double dummy=0;
222 HealpixBase base = new HealpixBase (1024,scheme);
223 long tstart = System.nanoTime();
224 for (int m=0; m<1000; ++m)
225 {
226 RangeSet lrs=base.queryDisc(new Pointing(new Vec3(1,0,0)),Constants.halfpi/9.);
227 dummy+=lrs.nranges();
228 ++cnt;
229 }
230 double time = 1e-9*(System.nanoTime()-tstart);
231 System.out.println(name+": " + form.format(cnt/time*1e-3) + "kOps/s");
232 return dummy;
233 }
234
235 private double subtest_perf_query_polygon(String name,
236 Scheme scheme) throws Exception
237 {
238 long cnt=0;
239 double dummy=0;
240 HealpixBase base = new HealpixBase (1024,scheme);
241 Pointing[] corner = new Pointing[4];
242 corner[0]=new Pointing(new Vec3(1,0.01,0.01));
243 corner[1]=new Pointing(new Vec3(1,1,-0.3));
244 corner[2]=new Pointing(new Vec3(0.01,1,0.01));
245 corner[3]=new Pointing(new Vec3(0.01,0.01,1));
246 long tstart = System.nanoTime();
247 for (int m=0; m<1000; ++m)
248 {
249 RangeSet lrs=base.queryPolygon(corner);
250 dummy+=lrs.nranges();
251 ++cnt;
252 }
253 double time = 1e-9*(System.nanoTime()-tstart);
254 System.out.println(name+": " + form.format(cnt/time*1e-3) + "kOps/s");
255 return dummy;
256 }
257
258 public void test_perf() throws Exception
259 {
260 System.out.println("Performance tests of HealpixBase methods");
261 double d=0;
262 d+=subtest_perf_neighbours("neighbours(NEST)",Scheme.NESTED);
263 d+=subtest_perf_neighbours("neighbours(RING)",Scheme.RING);
264 d+=subtest_perf_pix2ang ("pix2ang (NEST)",Scheme.NESTED);
265 d+=subtest_perf_pix2ang ("pix2ang (RING)",Scheme.RING);
266 d+=subtest_perf_ang2pix ("ang2pix (NEST)",Scheme.NESTED);
267 d+=subtest_perf_ang2pix ("ang2pix (RING)",Scheme.RING);
268 d+=subtest_perf_pix2vec ("pix2vec (NEST)",Scheme.NESTED);
269 d+=subtest_perf_pix2vec ("pix2vec (RING)",Scheme.RING);
270 d+=subtest_perf_pix2zphi ("pix2zphi (NEST)",Scheme.NESTED);
271 d+=subtest_perf_pix2zphi ("pix2zphi (RING)",Scheme.RING);
272 d+=subtest_perf_zphi2pix ("zphi2pix (NEST)",Scheme.NESTED);
273 d+=subtest_perf_zphi2pix ("zphi2pix (RING)",Scheme.RING);
274 d+=subtest_perf_ring2nest();
275 d+=subtest_perf_nest2ring();
276 d+=subtest_perf_query_disc("disc (NEST)",Scheme.NESTED);
277 d+=subtest_perf_query_disc("disc (RING)",Scheme.RING);
278 d+=subtest_perf_query_polygon("polygon (NEST)",Scheme.NESTED);
279 d+=subtest_perf_query_polygon("polygon (RING)",Scheme.RING);
280 }
281 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import junit.framework.TestCase;
22 import java.util.Random;
23 import java.text.DecimalFormat;
24
25 import healpix.essentials.*;
26
27 /** @author Martin Reinecke */
28 public class HealpixBaseTest extends TestCase {
29
30 static private final int nsamples=10000; // influences number of correctness tests
31 static private final DecimalFormat form = new DecimalFormat("##0.00");
32
33 private Zphi random_zphi(Random rng)
34 { return new Zphi(2*rng.nextDouble()-1,2*Math.PI*rng.nextDouble()); }
35
36 private Pointing random_dir(Random rng)
37 { return new Pointing(Math.acos(2*rng.nextDouble()-1),2*Math.PI*rng.nextDouble()); }
38
39 public void test_boundaries()throws Exception
40 {
41 System.out.println("Testing whether the boundary shapes look sane");
42
43 for (int nside=1; nside<=5; ++nside)
44 {
45 HealpixBase base=new HealpixBase(nside,Scheme.RING);
46 for (int pix=0; pix<base.getNpix(); ++pix)
47 {
48 for (int res=1; res<=50; res+=7)
49 {
50 Vec3[] points = base.boundaries(pix,res);
51 double dmin=1e30, dmax=-1e30;
52 for (int i=0; i<points.length; ++i)
53 {
54 double dv=(points[i].sub(points[(i+1)%points.length])).length();
55 assertTrue("error in boundaries",dv!=0);
56 dmin = Math.min(dv,dmin);
57 dmax = Math.max(dv,dmax);
58 }
59 assertTrue("error in boundaries",dmax/dmin<=2);
60 }
61 }
62 }
63 }
64
65 public void test_accuracy()throws Exception
66 {
67 System.out.println("Testing accuracy near the poles");
68
69 for (int order=0; order<=HealpixBase.order_max; ++order)
70 {
71 HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
72 assertTrue("incorrect pix2ang",base.pix2ang(1).theta>0.0);
73 }
74 }
75
76 public void test_ringnestring()throws Exception
77 {
78 System.out.println("Testing identity ring2nest(nest2ring(i))==i");
79 Random rng = new Random(5);
80
81 for (int order=0; order<=HealpixBase.order_max; ++order)
82 {
83 HealpixBase base = new HealpixBase (1L<<order,Scheme.RING);
84 for (int m=0; m<nsamples; ++m)
85 {
86 long pix = (long)(rng.nextDouble()*base.getNpix());
87 assertEquals ("ringnestring problem",
88 base.ring2nest(base.nest2ring(pix)),pix);
89 }
90 }
91 }
92
93 public void test_pixzphipix()throws Exception
94 {
95 System.out.println("Testing identity pix2zphi(zphi2pix(i))==i");
96 int omax=HealpixBase.order_max;
97 Random rng = new Random(5);
98 for (int order=0; order<=omax; ++order)
99 {
100 HealpixBase base1 = new HealpixBase (1L<<order,Scheme.RING),
101 base2 = new HealpixBase (1L<<order,Scheme.NESTED);
102 for (int m=0; m<nsamples; ++m)
103 {
104 long pix = (long)(rng.nextDouble()*base1.getNpix());
105 assertEquals ("pixzphipix problem",
106 pix, base1.zphi2pix(base1.pix2zphi(pix)));
107 assertEquals ("pixzphipix problem",
108 pix, base2.zphi2pix(base2.pix2zphi(pix)));
109 }
110 }
111 for (long nside=3; nside<(1L<<omax); nside+=nside/2+1)
112 {
113 HealpixBase base = new HealpixBase (nside,Scheme.RING);
114 for (int m=0; m<nsamples; ++m)
115 {
116 long pix = (long)(rng.nextDouble()*base.getNpix());
117 assertEquals ("pixzphipix problem",
118 pix, base.zphi2pix(base.pix2zphi(pix)));
119 }
120 }
121 }
122
123 public void test_zphipixzphi() throws Exception
124 {
125 System.out.println
126 ("Testing near-identity zphi2pix(pix2zphi(i))approx i");
127 int omax=HealpixBase.order_max;
128 Random rng = new Random(5);
129 for (int order=0; order<=omax; ++order)
130 {
131 HealpixBase base1 = new HealpixBase (1L<<order,Scheme.RING),
132 base2 = new HealpixBase (1L<<order,Scheme.NESTED);
133 double mincos = Math.min (Math.cos(base1.maxPixrad()),0.999999999999999);
134 for (int m=0; m<nsamples; ++m)
135 {
136 Zphi zp1 = random_zphi(rng);
137 Zphi zp2 = base1.pix2zphi(base1.zphi2pix(zp1));
138 double cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi);
139 assertTrue("zphipixzphi problem "+cd1+" "+mincos,cd1>=mincos);
140 zp2 = base2.pix2zphi(base2.zphi2pix(zp1));
141 cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi);
142 assertTrue("zphipixzphi problem",cd1>=mincos);
143 }
144 }
145 for (long nside=3; nside<(1L<<omax); nside+=nside/2+1)
146 {
147 HealpixBase base = new HealpixBase (nside,Scheme.RING);
148 double mincos = Math.min (Math.cos(base.maxPixrad()),0.999999999999999);
149 for (int m=0; m<nsamples; ++m)
150 {
151 Zphi zp1 = random_zphi(rng);
152 Zphi zp2 = base.pix2zphi(base.zphi2pix(zp1));
153 double cd1 = HealpixUtils.cosdist_zphi(zp1.z,zp1.phi,zp2.z,zp2.phi);
154 assertTrue("zphipixzphi problem",cd1>=mincos);
155 }
156 }
157 }
158
159 public void test_neighbours() throws Exception
160 {
161 System.out.println("Testing neighbour function");
162 int omax=HealpixBase.order_max;
163 Random rng = new Random(5);
164 for (int order=0; order<=omax; ++order)
165 {
166 HealpixBase base1 = new HealpixBase (1L<<order,Scheme.RING),
167 base2 = new HealpixBase (1L<<order,Scheme.NESTED);
168 double maxang = 2.01*base1.maxPixrad();
169 for (int m=0; m<nsamples; ++m)
170 {
171 long pix = (long)(rng.nextDouble()*base1.getNpix());
172 Vec3 v = base1.pix2vec(pix);
173 long [] nb = base1.neighbours(pix);
174 long [] nb2 = base2.neighbours(base2.ring2nest(pix));
175 int nnb=0;
176 for (int n=0; n<8; ++n)
177 {
178 if (nb[n]<0)
179 assertTrue("neighbour problem 1",nb2[n]<0);
180 else
181 {
182 ++nnb;
183 assertEquals("neighbour problem 2",base1.ring2nest(nb[n]),nb2[n]);
184 assertTrue("neighbour problem 3",base1.pix2vec(nb[n]).angle(v)<maxang);
185 }
186 }
187 assertTrue("neighbour problem 4 "+order+" "+nnb,(nnb>=7)||((order==0)&&(nnb>=6)));
188 }
189 }
190 for (long nside=3; nside<(1L<<omax); nside+=nside/2+1)
191 {
192 HealpixBase base = new HealpixBase (nside,Scheme.RING);
193 double maxang = 2.01*base.maxPixrad();
194 for (int m=0; m<nsamples; ++m)
195 {
196 long pix = (long)(rng.nextDouble()*base.getNpix());
197 Vec3 v = base.pix2vec(pix);
198 long[] nb = base.neighbours(pix);
199 int nnb=0;
200 for (int n=0; n<8; ++n)
201 if (nb[n]>=0)
202 {
203 ++nnb;
204 assertTrue("neighbour problem 5",base.pix2vec(nb[n]).angle(v)<maxang);
205 }
206 assertTrue("neighbour problem 6",nnb>=7);
207 }
208 }
209 }
210 public void test_query_disc_strict() throws Exception
211 {
212 System.out.println("Testing non-inclusive queryDisc()");
213 Random rng = new Random(5);
214 for (int order=0; order<=5; ++order)
215 {
216 HealpixBase base = new HealpixBase (1L<<order,Scheme.NESTED);
217 boolean[] map = new boolean[(int)base.getNpix()];
218 Vec3[] vmap = new Vec3[(int)base.getNpix()];
219 for (int m=0; m<base.getNpix(); ++m)
220 {
221 map[m]=false;
222 vmap[m]=base.pix2vec(m);
223 }
224 for (int m=0; m<nsamples; ++m)
225 {
226 Pointing ptg = random_dir (rng);
227 double rad = Math.PI * rng.nextDouble();
228 RangeSet rs = base.queryDisc(ptg,rad);
229 Vec3 vptg = new Vec3(ptg);
230 double cosrad=Math.cos(rad);
231 for (int i=0; i<rs.nranges(); ++i)
232 for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
233 map[(int)j]=true;
234 for (int i=0; i<base.getNpix(); ++i)
235 {
236 boolean inside = vmap[i].dot(vptg)>cosrad;
237 assertFalse ("query_disc_strict problem",inside^map[i]);
238 }
239 for (int i=0; i<rs.nranges(); ++i)
240 for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
241 map[(int)j]=false;
242 }
243 }
244 }
245
246 public void test_query_disc() throws Exception
247 {
248 System.out.println("Testing queryDisc() empirically");
249 int omax=17;
250 Random rng = new Random(5);
251 for (int order=0; order<=omax; ++order)
252 {
253 HealpixBase rbase = new HealpixBase (1L<<order,Scheme.RING),
254 nbase = new HealpixBase (1L<<order,Scheme.NESTED);
255 int niter=Math.max(1,Math.min(nsamples/1000,100000>>order));
256 for (int m=0; m<niter; ++m)
257 {
258 Pointing ptg = random_dir (rng);
259 double rad = Math.PI * rng.nextDouble();
260 RangeSet rs = rbase.queryDisc(ptg,rad);
261 long nval = rs.nval();
262 rs = nbase.queryDisc(ptg,rad);
263 assertEquals("queryDisc problem 1", nval,rs.nval());
264 rs = rbase.queryDiscInclusive(ptg,rad,4);
265 long nv1 = rs.nval();
266 rs = nbase.queryDiscInclusive(ptg,rad,4);
267 long nv2 = rs.nval();
268 assertTrue("queryDisc problem 2", nv1>=nv2);
269 assertTrue("queryDisc problem 3", nv2>=nval);
270 }
271 }
272 }
273
274 public void testQueryPolygon() throws Exception
275 {
276 System.out.println("Testing queryPolygon()");
277 HealpixBase base = new HealpixBase(1024,Scheme.NESTED);
278 Pointing[] corner = new Pointing[4];
279 corner[0]=new Pointing(new Vec3(1,0.01,0.01));
280 corner[1]=new Pointing(new Vec3(1,1,-0.3));
281 corner[2]=new Pointing(new Vec3(0.01,1,0.01));
282 corner[3]=new Pointing(new Vec3(0.01,0.01,1));
283 RangeSet lrs=base.queryPolygon(corner);
284 assertEquals("QueryPolygon problem",lrs.nval(),1696714);
285 lrs=base.queryPolygonInclusive(corner,4);
286 assertEquals("QueryPolygon problem",lrs.nval(),1700206);
287 base = new HealpixBase(1024,Scheme.RING);
288 lrs=base.queryPolygon(corner);
289 assertEquals("QueryPolygon problem",lrs.nval(),1696714);
290 lrs=base.queryPolygonInclusive(corner,4);
291 assertEquals("QueryPolygon problem",lrs.nval(),1700206);
292 }
293
294 public void testQueryPolygon2() throws Exception
295 {
296 System.out.println("Testing queryPolygon() empirically");
297 int omax=17;
298 Random rng = new Random(5);
299 for (int order=0; order<=omax; ++order)
300 {
301 HealpixBase rbase = new HealpixBase (1L<<order,Scheme.RING),
302 nbase = new HealpixBase (1L<<order,Scheme.NESTED);
303 int niter=Math.max(1,Math.min(nsamples/1000,100000>>order));
304 for (int m=0; m<niter; ++m)
305 {
306 Pointing[] corner = new Pointing[3];
307 corner[0]=random_dir(rng);
308 corner[1]=random_dir(rng);
309 corner[2]=random_dir(rng);
310 RangeSet rs = rbase.queryPolygon(corner);
311 long nval = rs.nval();
312 rs = nbase.queryPolygon(corner);
313 assertEquals("queryPolygon problem 1", nval,rs.nval());
314 rs = rbase.queryPolygonInclusive(corner,4);
315 long nv1 = rs.nval();
316 rs = nbase.queryPolygonInclusive(corner,4);
317 long nv2 = rs.nval();
318 assertTrue("queryPolygon problem 2", nv1>=nv2);
319 assertTrue("queryPolygon problem 3", nv2>=nval);
320 }
321 }
322 }
323
324 public void testSmallPoly() throws Exception
325 {
326 System.out.println("Testing small polygon");
327 HealpixBase base = new HealpixBase(1024,Scheme.NESTED);
328 Pointing[] corner = new Pointing[4];
329 corner[0]=new Pointing(2.7190983373838,1.50840508184223);
330 corner[1]=new Pointing(2.7190980835706067,1.5084057923700163);
331 corner[2]=new Pointing(2.719101654815075,1.5084144044115078);
332 corner[3]=new Pointing(2.719101908630556,1.5084136938829422);
333 RangeSet lrs=base.queryPolygon(corner);
334 }
335
336 public void test() throws Exception
337 {
338 int nside=256;
339 HealpixBase base = new HealpixBase(nside,Scheme.NESTED);
340 HealpixBase base2 = new HealpixBase(nside,Scheme.RING);
341 for (int i=0; i<12*nside*nside; ++i)
342 {
343 assertEquals ("pixel mismatch_nest",i,base.ang2pix(base.pix2ang(i)));
344 assertEquals ("pixel mismatch_nest",i,base.vec2pix(base.pix2vec(i)));
345 assertEquals ("pixel mismatch_ring",i,base2.ang2pix(base2.pix2ang(i)));
346 assertEquals ("pixel mismatch_ring",i,base2.vec2pix(base2.pix2vec(i)));
347 assertEquals ("pixel mismatch",i,base.ring2nest(base2.ang2pix(base.pix2ang(i))));
348 assertEquals ("pixel mismatch_ringnestring",i,base.ring2nest(base.nest2ring(i)));
349 }
350 }
351
352 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import junit.framework.TestCase;
22 import java.util.Random;
23 import java.text.DecimalFormat;
24
25 import healpix.essentials.*;
26
27 /** Tests for the HealpixMap class
28
29 @copyright 2014 Max-Planck-Society
30 @author Martin Reinecke */
31 public class HealpixMapTest extends TestCase {
32
33 public void test_swapScheme()throws Exception
34 {
35 System.out.println("Testing swapScheme()");
36
37 for (int order=0; order<=8; ++order)
38 {
39 HealpixMapFloat map = new HealpixMapFloat (1L<<order,Scheme.RING);
40 for (int i=0; i<map.getNpix(); ++i)
41 map.setPixel(i,i);
42 map.swapScheme();
43 for (int i=0; i<map.getNpix(); ++i)
44 assertEquals("inconsistency",map.nest2ring(i),(int)map.getPixel(i));
45 map.swapScheme();
46 for (int i=0; i<map.getNpix(); ++i)
47 assertEquals("inconsistency",i,(int)map.getPixel(i));
48 }
49 }
50 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import junit.framework.TestCase;
22 import java.util.Random;
23 import java.text.DecimalFormat;
24
25 import healpix.essentials.*;
26
27 /** Tests for the HealpixProc class
28
29 @copyright 2014 Max-Planck-Society
30 @author Martin Reinecke */
31 public class HealpixProcTest extends TestCase {
32
33 static private final int nsamples=10000; // influences number of correctness tests
34 static private final DecimalFormat form = new DecimalFormat("##0.00");
35
36 private Zphi random_zphi(Random rng)
37 { return new Zphi(2*rng.nextDouble()-1,2*Math.PI*rng.nextDouble()); }
38
39 private Pointing random_dir(Random rng)
40 { return new Pointing(Math.acos(2*rng.nextDouble()-1),2*Math.PI*rng.nextDouble()); }
41
42 public void test_accuracy()throws Exception
43 {
44 System.out.println("Testing accuracy near the poles");
45
46 for (int order=0; order<=HealpixBase.order_max; ++order)
47 assertTrue("incorrect pix2ang",
48 HealpixProc.pix2angRing(order,1).theta>0.0);
49 }
50
51 public void test_ringnestring()throws Exception
52 {
53 System.out.println("Testing identity ring2nest(nest2ring(i))==i");
54 Random rng = new Random(5);
55
56 for (int o=0; o<=HealpixBase.order_max; ++o)
57 {
58 for (int m=0; m<nsamples; ++m)
59 {
60 long pix = (long)(rng.nextDouble()*HealpixProc.order2Npix(o));
61 assertEquals ("ringnestring problem",
62 HealpixProc.ring2nest(o,HealpixProc.nest2ring(o,pix)),pix);
63 }
64 }
65 }
66
67 public void test_pixangpix()throws Exception
68 {
69 System.out.println("Testing identity pix2ang(ang2pix(i))==i");
70 int omax=HealpixBase.order_max;
71 Random rng = new Random(5);
72 for (int o=0; o<=omax; ++o)
73 {
74 for (int m=0; m<nsamples; ++m)
75 {
76 long pix = (long)(rng.nextDouble()*HealpixProc.order2Npix(o));
77 assertEquals ("pixangpix problem",
78 pix, HealpixProc.ang2pixNest(o,HealpixProc.pix2angNest(o,pix)));
79 assertEquals ("pixangpix problem",
80 pix, HealpixProc.ang2pixRing(o,HealpixProc.pix2angRing(o,pix)));
81 }
82 }
83 }
84
85 public void test_neighbours() throws Exception
86 {
87 System.out.println("Testing neighbour function");
88 int omax=HealpixBase.order_max;
89 Random rng = new Random(5);
90 for (int o=0; o<=omax; ++o)
91 {
92 double maxang = 2.01*HealpixProc.maxPixrad(o);
93 for (int m=0; m<nsamples; ++m)
94 {
95 long pix = (long)(rng.nextDouble()*HealpixProc.order2Npix(o));
96 Vec3 v = HealpixProc.pix2vecRing(o,pix);
97 long [] nb = HealpixProc.neighboursRing(o,pix);
98 long [] nb2 = HealpixProc.neighboursNest(o,HealpixProc.ring2nest(o,pix));
99 int nnb=0;
100 for (int n=0; n<8; ++n)
101 {
102 if (nb[n]<0)
103 assertTrue("neighbour problem 1",nb2[n]<0);
104 else
105 {
106 ++nnb;
107 assertEquals("neighbour problem 2",HealpixProc.ring2nest(o,nb[n]),nb2[n]);
108 assertTrue("neighbour problem 3",HealpixProc.pix2vecRing(o,nb[n]).angle(v)<maxang);
109 }
110 }
111 assertTrue("neighbour problem 4 "+o+" "+nnb,(nnb>=7)||((o==0)&&(nnb>=6)));
112 }
113 }
114 }
115
116 public void test_query_disc_strict() throws Exception
117 {
118 System.out.println("Testing non-inclusive queryDisc()");
119 Random rng = new Random(5);
120 for (int o=0; o<=5; ++o)
121 {
122 int npix=(int)HealpixProc.order2Npix(o);
123 boolean[] map = new boolean[npix];
124 Vec3[] vmap = new Vec3[npix];
125 for (int m=0; m<npix; ++m)
126 {
127 map[m]=false;
128 vmap[m]=HealpixProc.pix2vecRing(o,m);
129 }
130 for (int m=0; m<nsamples; ++m)
131 {
132 Pointing ptg = random_dir (rng);
133 double rad = Math.PI * rng.nextDouble();
134 RangeSet rs = HealpixProc.queryDiscRing(o,ptg,rad);
135 Vec3 vptg = new Vec3(ptg);
136 double cosrad=Math.cos(rad);
137 for (int i=0; i<rs.nranges(); ++i)
138 for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
139 map[(int)j]=true;
140 for (int i=0; i<npix; ++i)
141 {
142 boolean inside = vmap[i].dot(vptg)>cosrad;
143 assertFalse ("query_disc_strict problem",inside^map[i]);
144 }
145 for (int i=0; i<rs.nranges(); ++i)
146 for (long j=rs.ivbegin(i); j<rs.ivend(i); ++j)
147 map[(int)j]=false;
148 }
149 }
150 }
151
152 public void test_query_disc() throws Exception
153 {
154 System.out.println("Testing queryDisc() empirically");
155 int omax=17;
156 Random rng = new Random(5);
157 for (int o=0; o<=omax; ++o)
158 {
159 int niter=Math.max(1,Math.min(nsamples/1000,100000>>o));
160 for (int m=0; m<niter; ++m)
161 {
162 Pointing ptg = random_dir (rng);
163 double rad = Math.PI * rng.nextDouble();
164 RangeSet rs = HealpixProc.queryDiscRing(o,ptg,rad);
165 long nval = rs.nval();
166 rs = HealpixProc.queryDiscNest(o,ptg,rad);
167 assertEquals("queryDisc problem 1", nval,rs.nval());
168 rs = HealpixProc.queryDiscInclusiveRing(o,ptg,rad,4);
169 long nv1 = rs.nval();
170 rs = HealpixProc.queryDiscInclusiveNest(o,ptg,rad,4);
171 long nv2 = rs.nval();
172 assertTrue("queryDisc problem 2", nv1>=nv2);
173 assertTrue("queryDisc problem 3", nv2>=nval);
174 }
175 }
176 }
177
178 public void testQueryPolygon() throws Exception
179 {
180 System.out.println("Testing queryPolygon()");
181 Pointing[] corner = new Pointing[4];
182 corner[0]=new Pointing(new Vec3(1,0.01,0.01));
183 corner[1]=new Pointing(new Vec3(1,1,-0.3));
184 corner[2]=new Pointing(new Vec3(0.01,1,0.01));
185 corner[3]=new Pointing(new Vec3(0.01,0.01,1));
186 RangeSet lrs=HealpixProc.queryPolygonNest(10,corner);
187 assertEquals("QueryPolygon problem",lrs.nval(),1696714);
188 lrs=HealpixProc.queryPolygonInclusiveNest(10,corner,4);
189 assertEquals("QueryPolygon problem",lrs.nval(),1700206);
190 lrs=HealpixProc.queryPolygonRing(10,corner);
191 assertEquals("QueryPolygon problem",lrs.nval(),1696714);
192 lrs=HealpixProc.queryPolygonInclusiveRing(10,corner,4);
193 assertEquals("QueryPolygon problem",lrs.nval(),1700206);
194 }
195
196 public void testQueryPolygon2() throws Exception
197 {
198 System.out.println("Testing queryPolygon() empirically");
199 int omax=17;
200 Random rng = new Random(5);
201 for (int o=0; o<=omax; ++o)
202 {
203 int niter=Math.max(1,Math.min(nsamples/1000,100000>>o));
204 for (int m=0; m<niter; ++m)
205 {
206 Pointing[] corner = new Pointing[3];
207 corner[0]=random_dir(rng);
208 corner[1]=random_dir(rng);
209 corner[2]=random_dir(rng);
210 RangeSet rs = HealpixProc.queryPolygonRing(o,corner);
211 long nval = rs.nval();
212 rs = HealpixProc.queryPolygonNest(o,corner);
213 assertEquals("queryPolygon problem 1", nval,rs.nval());
214 rs = HealpixProc.queryPolygonInclusiveRing(o,corner,4);
215 long nv1 = rs.nval();
216 rs = HealpixProc.queryPolygonInclusiveNest(o,corner,4);
217 long nv2 = rs.nval();
218 assertTrue("queryPolygon problem 2", nv1>=nv2);
219 assertTrue("queryPolygon problem 3", nv2>=nval);
220 }
221 }
222 }
223
224 public void test() throws Exception
225 {
226 int o=8;
227 for (int i=0; i<HealpixProc.order2Npix(o); ++i)
228 {
229 assertEquals ("pixel mismatch_nest",i,HealpixProc.ang2pixNest(o,HealpixProc.pix2angNest(o,i)));
230 assertEquals ("pixel mismatch_nest",i,HealpixProc.vec2pixNest(o,HealpixProc.pix2vecNest(o,i)));
231 assertEquals ("pixel mismatch_ring",i,HealpixProc.ang2pixRing(o,HealpixProc.pix2angRing(o,i)));
232 assertEquals ("pixel mismatch_ring",i,HealpixProc.vec2pixRing(o,HealpixProc.pix2vecRing(o,i)));
233 assertEquals ("pixel mismatch",i,HealpixProc.ring2nest(o,HealpixProc.ang2pixRing(o,HealpixProc.pix2angNest(o,i))));
234 assertEquals ("pixel mismatch_ringnestring",i,HealpixProc.ring2nest(o,HealpixProc.nest2ring(o,i)));
235 }
236 }
237 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import healpix.essentials.*;
22 import junit.framework.TestCase;
23 import java.io.*;
24 import java.util.Arrays;
25 import java.util.ArrayList;
26
27 /** Tests for the MocQuery class
28
29 @copyright 2015 Max-Planck-Society
30 @author Martin Reinecke */
31 public class MocQueryTest extends TestCase
32 {
33 private ArrayList<Vec3> rawToPoly(double[] inp) throws Exception
34 {
35 HealpixUtils.check((inp.length>=6)&&((inp.length&1)==0),
36 "bad input array");
37 ArrayList<Vec3> res = new ArrayList<Vec3>();
38 for (int i=0; i<inp.length; i+=2)
39 res.add(new Vec3(new Pointing(Math.PI/2 - Math.toRadians(inp[i+1]),
40 Math.toRadians(inp[i]))));
41 return res;
42 }
43 private void checkPoly(ArrayList<Vec3> poly, int o1, int o2, String out)
44 throws Exception
45 {
46 Moc moc = MocQuery.queryGeneralPolygonInclusive (poly,o1,o1);
47 if (out!="")
48 MocFitsIO.mocToFits(moc,out+"_inc_"+o1+".fits");
49 for (int o=o1+1; o<=o2; ++o)
50 {
51 Moc moc2 = MocQuery.queryGeneralPolygonInclusive (poly,o1,o2);
52 assertTrue("inconsistency",moc.contains(moc2));
53 if (out!="")
54 MocFitsIO.mocToFits(moc2,out+"_inc_"+o+".fits");
55 moc=moc2;
56 }
57 Moc moc2 = MocQuery.queryGeneralPolygon(poly,o1);
58 if (out!="")
59 MocFitsIO.mocToFits(moc2,out+".fits");
60 assertTrue("inconsistency",moc.contains(moc2));
61 }
62 public void test1() throws Exception
63 {
64 double[] polyraw=new double[]{
65 83.6479647404001, 22.06796566083695,
66 83.57919759304697, 22.014902754311912,
67 83.54565527259793, 22.05666932013043,
68 83.54535325267885, 22.05666728060237,
69 83.54535545323692, 22.056387364445676,
70 83.54535985432697, 22.05582753212609,
71 83.54536865640274, 22.05470786746255,
72 83.54537525786826, 22.05386811894398,
73 83.53952949498002, 21.952773396955234,
74 83.63157603991105, 21.995362438376056,
75 83.64144959973622, 21.965751089665403,
76 83.69912966373616, 22.00612703969729 };
77
78 checkPoly(rawToPoly(polyraw),13,15,"");
79 }
80 public void test2() throws Exception
81 {
82 double[] polyraw=new double[]{
83 83.69572488226052, 22.01842407483951,
84 83.66469321144844, 22.05155150183524,
85 83.66439120028902, 22.051549680680765,
86 83.62952475535761, 22.02838142338798,
87 83.58771024980035, 22.04715033027345,
88 83.5874082491367, 22.04714836793211,
89 83.58741036646086, 22.0468684509572,
90 83.58741671838312, 22.046028700022926,
91 83.57147626994606, 21.99805614401068,
92 83.59369254263831, 21.934377044862455,
93 83.59369043939574, 21.93465696148893,
94 83.59368833614487, 21.934936878119167,
95 83.59338236664615, 21.935494760357145,
96 83.59338026277467, 21.93577467699384,
97 83.64687451268995, 21.966904215256918,
98 83.60550939897153, 22.00919444338953,
99 83.66653272555045, 22.004534367269507,
100 83.69542484507058, 22.018142392123163 };
101
102 checkPoly(rawToPoly(polyraw),13,15,"");
103 }
104
105 public void test3() throws Exception
106 {
107 ArrayList<Vec3> vert=new ArrayList<Vec3>();
108 vert.add(new Vec3(new Pointing(1.1523428941043317,1.000795791041251)));
109 vert.add(new Vec3(new Pointing(1.1523106929911657,1.0008281306683644)));
110 vert.add(new Vec3(new Pointing(1.1521818924889993,1.0009574985526972)));
111 vert.add(new Vec3(new Pointing(1.1519887035905163,1.001151578519077)));
112 vert.add(new Vec3(new Pointing(1.151859918897493,1.0012809839336458)));
113 vert.add(new Vec3(new Pointing(1.1514894198468866,1.001263637028638)));
114 vert.add(new Vec3(new Pointing(1.1513659202048774,1.0012578536443903)));
115 vert.add(new Vec3(new Pointing(1.1511859573237597,1.0011139425394953)));
116 vert.add(new Vec3(new Pointing(1.1510060020113047,1.0009700085527964)));
117 vert.add(new Vec3(new Pointing(1.1508556031353578,1.0008613172356937)));
118 vert.add(new Vec3(new Pointing(1.150673007120061,1.0007849744501682)));
119 vert.add(new Vec3(new Pointing(1.1503938085112773,1.0008057187152946)));
120 vert.add(new Vec3(new Pointing(1.150205908484378,1.0008646491036832)));
121 vert.add(new Vec3(new Pointing(1.149953611594119,1.000988341677547)));
122 vert.add(new Vec3(new Pointing(1.1497335179693469,1.0010796806589697)));
123 vert.add(new Vec3(new Pointing(1.1494247698862567,1.0010651879076278)));
124 vert.add(new Vec3(new Pointing(1.1492448165599576,1.0009211385295873)));
125 vert.add(new Vec3(new Pointing(1.149000469199188,1.0008418420185987)));
126 vert.add(new Vec3(new Pointing(1.1485894925444542,1.000279935669881)));
127 vert.add(new Vec3(new Pointing(1.1486539077047668,1.0002151640462313)));
128 vert.add(new Vec3(new Pointing(1.1490324086471566,1.0000296562389843)));
129 vert.add(new Vec3(new Pointing(1.1492203271505665,0.9999707639528252)));
130 vert.add(new Vec3(new Pointing(1.1495639559481354,0.9998853760122856)));
131 vert.add(new Vec3(new Pointing(1.149848517849616,0.9997294255486839)));
132 vert.add(new Vec3(new Pointing(1.1499773768285775,0.9995999921162992)));
133 vert.add(new Vec3(new Pointing(1.1501062421175312,0.9994705737522844)));
134 vert.add(new Vec3(new Pointing(1.1501733657022064,0.9993382245815566)));
135 vert.add(new Vec3(new Pointing(1.150157309455921,0.9989646985587307)));
136 vert.add(new Vec3(new Pointing(1.1502783613271745,0.9982588937208289)));
137 vert.add(new Vec3(new Pointing(1.150367358658019,0.9975854875791592)));
138 vert.add(new Vec3(new Pointing(1.1503145561122339,0.9966002329829549)));
139 vert.add(new Vec3(new Pointing(1.1501837017642849,0.9960177261452899)));
140 vert.add(new Vec3(new Pointing(1.1500880289072624,0.9953352142578803)));
141 vert.add(new Vec3(new Pointing(1.1498339618638964,0.9947464292684306)));
142 vert.add(new Vec3(new Pointing(1.1496599663238942,0.9944665891792631)));
143 vert.add(new Vec3(new Pointing(1.1495211017074738,0.9940867625529576)));
144 vert.add(new Vec3(new Pointing(1.1494032633666398,0.993945254823653)));
145 vert.add(new Vec3(new Pointing(1.1492854324600088,0.9938037321908275)));
146 vert.add(new Vec3(new Pointing(1.1491647775622915,0.9937298631728655)));
147 vert.add(new Vec3(new Pointing(1.1489093237140704,0.9939204821489465)));
148 vert.add(new Vec3(new Pointing(1.1487240963858985,0.9939111896936369)));
149 vert.add(new Vec3(new Pointing(1.148418211419246,0.9938280074878991)));
150 vert.add(new Vec3(new Pointing(1.148203527561705,0.9937833060402974)));
151 vert.add(new Vec3(new Pointing(1.1480562505373242,0.9936062948138628)));
152 vert.add(new Vec3(new Pointing(1.1479678899060295,0.9935000768652547)));
153 vert.add(new Vec3(new Pointing(1.1479089851456499,0.9934292602260698)));
154 vert.add(new Vec3(new Pointing(1.1478263164713338,0.9931876107503619)));
155 vert.add(new Vec3(new Pointing(1.147658188833066,0.9927719711268423)));
156 vert.add(new Vec3(new Pointing(1.147605019627341,0.9925656960713723)));
157 vert.add(new Vec3(new Pointing(1.147513838399067,0.9925271325090353)));
158 vert.add(new Vec3(new Pointing(1.1469790356795493,0.9927375232998785)));
159 vert.add(new Vec3(new Pointing(1.1467586597155184,0.9928281691313717)));
160 vert.add(new Vec3(new Pointing(1.1466646212864107,0.9928573452285496)));
161 vert.add(new Vec3(new Pointing(1.146570583168876,0.9928865238140747)));
162 vert.add(new Vec3(new Pointing(1.1464822508174166,0.9927802065018877)));
163 vert.add(new Vec3(new Pointing(1.1464233649158908,0.9927093236024059)));
164 vert.add(new Vec3(new Pointing(1.1463350395636842,0.9926029922143758)));
165 vert.add(new Vec3(new Pointing(1.1464082297063476,0.9923351250888106)));
166 vert.add(new Vec3(new Pointing(1.1465403155639036,0.9921381737414078)));
167 vert.add(new Vec3(new Pointing(1.146801650920068,0.9918120793817878)));
168 vert.add(new Vec3(new Pointing(1.146992632145478,0.9916860897831967)));
169 vert.add(new Vec3(new Pointing(1.147336526500701,0.9916018945040467)));
170 vert.add(new Vec3(new Pointing(1.1475540582351127,0.991579108720834)));
171 vert.add(new Vec3(new Pointing(1.148297344412475,0.9908370227283142)));
172 vert.add(new Vec3(new Pointing(1.14831771135701,0.9903631889078771)));
173 vert.add(new Vec3(new Pointing(1.1483410904887272,0.9898216751345671)));
174 vert.add(new Vec3(new Pointing(1.14817642568152,0.9893381849506938)));
175 vert.add(new Vec3(new Pointing(1.1478619397258643,0.9887449725688633)));
176 vert.add(new Vec3(new Pointing(1.1476621504872502,0.9883612311158905)));
177 vert.add(new Vec3(new Pointing(1.1473389454791498,0.987970892009681)));
178 vert.add(new Vec3(new Pointing(1.1470745474697959,0.9876514390156884)));
179 vert.add(new Vec3(new Pointing(1.1467220762850698,0.9872253830842613)));
180 vert.add(new Vec3(new Pointing(1.1465134990729606,0.9870445283107344)));
181 vert.add(new Vec3(new Pointing(1.1463576636239432,0.9870701715700294)));
182 vert.add(new Vec3(new Pointing(1.1461311065061512,0.987295784658764)));
183 vert.add(new Vec3(new Pointing(1.145969291549504,0.9874569649988388)));
184 vert.add(new Vec3(new Pointing(1.1456780489082319,0.9877471487418389)));
185 vert.add(new Vec3(new Pointing(1.1453544826095992,0.9880696643744283)));
186 vert.add(new Vec3(new Pointing(1.1451309779989192,0.9882276968098427)));
187 vert.add(new Vec3(new Pointing(1.1449223325837785,0.9880468062013319)));
188 vert.add(new Vec3(new Pointing(1.144684321314146,0.9878303468533963)));
189 vert.add(new Vec3(new Pointing(1.1444786880119573,0.9875815784705101)));
190 vert.add(new Vec3(new Pointing(1.1444055321874065,0.9871359210384268)));
191 vert.add(new Vec3(new Pointing(1.1443527978610553,0.9869292081606309)));
192 vert.add(new Vec3(new Pointing(1.1443588066568586,0.9867935954286845)));
193 vert.add(new Vec3(new Pointing(1.1443294428641322,0.9867580408743656)));
194 vert.add(new Vec3(new Pointing(1.1441178863108807,0.9866447588708069)));
195 vert.add(new Vec3(new Pointing(1.143627025593574,0.9865504721602422)));
196 vert.add(new Vec3(new Pointing(1.1430714198687517,0.9865206748900628)));
197 vert.add(new Vec3(new Pointing(1.142486453971728,0.9864552736851653)));
198 vert.add(new Vec3(new Pointing(1.1421130353865951,0.9865032583536448)));
199 vert.add(new Vec3(new Pointing(1.1418013514800418,0.9865545719393494)));
200 vert.add(new Vec3(new Pointing(1.1415280685012117,0.9864378231638371)));
201 vert.add(new Vec3(new Pointing(1.1413195436592867,0.9862564662025781)));
202 vert.add(new Vec3(new Pointing(1.1411140566169835,0.9860071695710151)));
203 vert.add(new Vec3(new Pointing(1.1410583793726072,0.9858680266790968)));
204 vert.add(new Vec3(new Pointing(1.1411585594318707,0.9857032675075046)));
205 vert.add(new Vec3(new Pointing(1.1415471911174158,0.9853159421723982)));
206 vert.add(new Vec3(new Pointing(1.1417091373202277,0.9851545968685336)));
207 vert.add(new Vec3(new Pointing(1.141935878135893,0.9849287531836823)));
208 vert.add(new Vec3(new Pointing(1.1421919741278386,0.9847385729150904)));
209 vert.add(new Vec3(new Pointing(1.1427212823451636,0.9846653708690231)));
210 vert.add(new Vec3(new Pointing(1.1429388730086534,0.9846432208437782)));
211 vert.add(new Vec3(new Pointing(1.1431888603402285,0.9845888377168718)));
212 vert.add(new Vec3(new Pointing(1.143221257341095,0.9845566013231962)));
213 vert.add(new Vec3(new Pointing(1.1431393920272823,0.9843141087835374)));
214 vert.add(new Vec3(new Pointing(1.142940242012983,0.9839291446460309)));
215 vert.add(new Vec3(new Pointing(1.1427704685698539,0.9835797337470248)));
216 vert.add(new Vec3(new Pointing(1.1426917873195213,0.9832693018292363)));
217 vert.add(new Vec3(new Pointing(1.142613142293535,0.9829588475331977)));
218 vert.add(new Vec3(new Pointing(1.1426935245487904,0.9825551447276581)));
219 vert.add(new Vec3(new Pointing(1.1428587549013667,0.9823262384230973)));
220 vert.add(new Vec3(new Pointing(1.1432802997807938,0.9819076068355195)));
221 vert.add(new Vec3(new Pointing(1.1435428818201463,0.981582241584326)));
222 vert.add(new Vec3(new Pointing(1.1438023569877103,0.9813247693528765)));
223 vert.add(new Vec3(new Pointing(1.1440879942426359,0.981170799141964)));
224 vert.add(new Vec3(new Pointing(1.1443087617014966,0.9810812052364875)));
225 vert.add(new Vec3(new Pointing(1.1444939405572025,0.9810915890969772)));
226 vert.add(new Vec3(new Pointing(1.1446435321631656,0.9812019262076423)));
227 vert.add(new Vec3(new Pointing(1.1449657419610033,0.9815937325674373)));
228 vert.add(new Vec3(new Pointing(1.145170814762998,0.9818430040096161)));
229 vert.add(new Vec3(new Pointing(1.145405212420505,0.9821278286770655)));
230 vert.add(new Vec3(new Pointing(1.1455810307686392,0.982341407316913)));
231 vert.add(new Vec3(new Pointing(1.1456396407122253,0.9824125926080799)));
232 vert.add(new Vec3(new Pointing(1.1457568663384885,0.9825549518114552)));
233 vert.add(new Vec3(new Pointing(1.1458447905784235,0.982661711260155)));
234 vert.add(new Vec3(new Pointing(1.146056176224855,0.9827752848212115)));
235 vert.add(new Vec3(new Pointing(1.1464203363305736,0.982931223860804)));
236 vert.add(new Vec3(new Pointing(1.1465700046565381,0.983041338988599)));
237 vert.add(new Vec3(new Pointing(1.146931084242241,0.9832649203344934)));
238 vert.add(new Vec3(new Pointing(1.147304554977569,0.983217580321881)));
239 vert.add(new Vec3(new Pointing(1.14755456833011,0.983163460791517)));
240 vert.add(new Vec3(new Pointing(1.1476518102952684,0.9830670054161794)));
241 vert.add(new Vec3(new Pointing(1.147911138996274,0.9828098319777566)));
242 vert.add(new Vec3(new Pointing(1.1480146153175843,0.9825780284118409)));
243 vert.add(new Vec3(new Pointing(1.1478512630860116,0.982093928824457)));
244 vert.add(new Vec3(new Pointing(1.1477465895705665,0.981680894029768)));
245 vert.add(new Vec3(new Pointing(1.1477037064890643,0.9812712698299393)));
246 vert.add(new Vec3(new Pointing(1.1476901713851657,0.980897208503522)));
247 vert.add(new Vec3(new Pointing(1.147738413955949,0.9805266127850084)));
248 vert.add(new Vec3(new Pointing(1.1479718818582025,0.9801664735990022)));
249 vert.add(new Vec3(new Pointing(1.148205397839398,0.9798064091969002)));
250 vert.add(new Vec3(new Pointing(1.1483708576902831,0.9795782695316553)));
251 vert.add(new Vec3(new Pointing(1.1487928200059858,0.9791611823574279)));
252 vert.add(new Vec3(new Pointing(1.1493382912635042,0.9787512843635041)));
253 vert.add(new Vec3(new Pointing(1.1502609222180684,0.9788716216588957)));
254 vert.add(new Vec3(new Pointing(1.1504396821178993,0.9790173766494347)));
255 vert.add(new Vec3(new Pointing(1.1507908399518807,0.9794440181022032)));
256 vert.add(new Vec3(new Pointing(1.1509893471305994,0.9798280210118206)));
257 vert.add(new Vec3(new Pointing(1.1511815695494167,0.9803471360053592)));
258 vert.add(new Vec3(new Pointing(1.1513477656945341,0.9807630544316528)));
259 vert.add(new Vec3(new Pointing(1.1516604798024512,0.98135646536512)));
260 vert.add(new Vec3(new Pointing(1.1517033801181038,0.981765361770002)));
261 vert.add(new Vec3(new Pointing(1.1517170406506425,0.9821387451013951)));
262 vert.add(new Vec3(new Pointing(1.1515842233393097,0.9823346503008543)));
263 vert.add(new Vec3(new Pointing(1.1513896921866162,0.9825271705205277)));
264 vert.add(new Vec3(new Pointing(1.1511627565046656,0.9827518193104232)));
265 vert.add(new Vec3(new Pointing(1.1508710094941494,0.9830407197788995)));
266 vert.add(new Vec3(new Pointing(1.1506441165054242,0.9832654717657893)));
267 vert.add(new Vec3(new Pointing(1.150482061529942,0.9834260365777083)));
268 vert.add(new Vec3(new Pointing(1.1503524244193444,0.9835545050450514)));
269 vert.add(new Vec3(new Pointing(1.1502258785647448,0.983615364692989)));
270 vert.add(new Vec3(new Pointing(1.150040689827067,0.9836052230787131)));
271 vert.add(new Vec3(new Pointing(1.1497289561324662,0.9836559547866632)));
272 vert.add(new Vec3(new Pointing(1.1496348192975478,0.9836847052609023)));
273 vert.add(new Vec3(new Pointing(1.1494727890458836,0.9838453720714817)));
274 vert.add(new Vec3(new Pointing(1.1494049018076335,0.9839772939956009)));
275 vert.add(new Vec3(new Pointing(1.149324740233309,0.9843798294222985)));
276 vert.add(new Vec3(new Pointing(1.1492739766976383,0.9848178951560865)));
277 vert.add(new Vec3(new Pointing(1.1492880620951265,0.9851916630592842)));
278 vert.add(new Vec3(new Pointing(1.1494023951081926,0.9854012904878543)));
279 vert.add(new Vec3(new Pointing(1.149519781095103,0.9855432489469033)));
280 vert.add(new Vec3(new Pointing(1.1497839272856774,0.9858626006164312)));
281 vert.add(new Vec3(new Pointing(1.1501482692615095,0.986017767907073)));
282 vert.add(new Vec3(new Pointing(1.1506158045877952,0.9859411952965156)));
283 vert.add(new Vec3(new Pointing(1.1510863719564317,0.9857970535978254)));
284 vert.add(new Vec3(new Pointing(1.1514010989298469,0.9856784621213586)));
285 vert.add(new Vec3(new Pointing(1.1517158310959092,0.9855599035665571)));
286 vert.add(new Vec3(new Pointing(1.1520923005998371,0.9854447044733927)));
287 vert.add(new Vec3(new Pointing(1.152556811551436,0.9854358697505938)));
288 vert.add(new Vec3(new Pointing(1.152936329868326,0.9852531893604244)));
289 vert.add(new Vec3(new Pointing(1.1534980080389958,0.9851480997557343)));
290 vert.add(new Vec3(new Pointing(1.1542448858126413,0.9850530625072047)));
291 vert.add(new Vec3(new Pointing(1.1548713566503563,0.9848839302619462)));
292 vert.add(new Vec3(new Pointing(1.155238694559804,0.9849714230186063)));
293 vert.add(new Vec3(new Pointing(1.155511913488695,0.9850876232716619)));
294 vert.add(new Vec3(new Pointing(1.1556879733525678,0.9852999969140172)));
295 vert.add(new Vec3(new Pointing(1.1559784112498703,0.9857213321874994)));
296 vert.add(new Vec3(new Pointing(1.1559865844022958,0.9862288863472906)));
297 vert.add(new Vec3(new Pointing(1.1560385791492556,0.9871444375227638)));
298 vert.add(new Vec3(new Pointing(1.1560116805212006,0.9877515244318255)));
299 vert.add(new Vec3(new Pointing(1.1558379990039347,0.9881818725706057)));
300 vert.add(new Vec3(new Pointing(1.155543873841697,0.9885383490226638)));
301 vert.add(new Vec3(new Pointing(1.1552557042400238,0.9887599602232404)));
302 vert.add(new Vec3(new Pointing(1.1549352096290768,0.9890137597369755)));
303 vert.add(new Vec3(new Pointing(1.1546147391191914,0.9892676311236104)));
304 vert.add(new Vec3(new Pointing(1.1542354927708685,0.9894508532485825)));
305 vert.add(new Vec3(new Pointing(1.1538621301597058,0.9894990936671686)));
306 vert.add(new Vec3(new Pointing(1.1536181187451178,0.9894187147674598)));
307 vert.add(new Vec3(new Pointing(1.1533447121031735,0.9893029412643478)));
308 vert.add(new Vec3(new Pointing(1.1529537305101472,0.9890455986187472)));
309 vert.add(new Vec3(new Pointing(1.1524980830083356,0.9888524937214215)));
310 vert.add(new Vec3(new Pointing(1.1523481741773312,0.9887430639190622)));
311 vert.add(new Vec3(new Pointing(1.1520629738824093,0.988897439436812)));
312 vert.add(new Vec3(new Pointing(1.1518395192779805,0.9890550816485132)));
313 vert.add(new Vec3(new Pointing(1.1515513932259047,0.9892771221299574)));
314 vert.add(new Vec3(new Pointing(1.1513250228779512,0.9895024356245301)));
315 vert.add(new Vec3(new Pointing(1.1510957407699558,0.9897953995250245)));
316 vert.add(new Vec3(new Pointing(1.1508988210950766,0.9900562178915127)));
317 vert.add(new Vec3(new Pointing(1.150763665085474,0.9903202764372446)));
318 vert.add(new Vec3(new Pointing(1.1507843367123325,0.990558526439852)));
319 vert.add(new Vec3(new Pointing(1.1507992237525468,0.9909320025905168)));
320 vert.add(new Vec3(new Pointing(1.1508522671724446,0.9911380213792874)));
321 vert.add(new Vec3(new Pointing(1.1509376417668262,0.9913118073666528)));
322 vert.add(new Vec3(new Pointing(1.1510230276226834,0.9914855800960104)));
323 vert.add(new Vec3(new Pointing(1.1511701646336845,0.9916624962872871)));
324 vert.add(new Vec3(new Pointing(1.1513467444499845,0.9918747650352789)));
325 vert.add(new Vec3(new Pointing(1.151493907126133,0.9920516301034698)));
326 vert.add(new Vec3(new Pointing(1.15167051772407,0.9922638375354705)));
327 vert.add(new Vec3(new Pointing(1.1517825427272692,0.9925404659613722)));
328 vert.add(new Vec3(new Pointing(1.1518945962236837,0.9928170667717601)));
329 vert.add(new Vec3(new Pointing(1.151944936626454,0.9930905238387734)));
330 vert.add(new Vec3(new Pointing(1.1519364038488704,0.9932932756669433)));
331 vert.add(new Vec3(new Pointing(1.1519545044629247,0.9935989574717053)));
332 vert.add(new Vec3(new Pointing(1.1518899290891478,0.9936634411834805)));
333 vert.add(new Vec3(new Pointing(1.1518576419864373,0.9936956844356148)));
334 vert.add(new Vec3(new Pointing(1.1515670755926695,0.9939859156123069)));
335 vert.add(new Vec3(new Pointing(1.1514056634584344,0.9941471877691483)));
336 vert.add(new Vec3(new Pointing(1.151209167317511,0.9944083526588667)));
337 vert.add(new Vec3(new Pointing(1.1510098905412778,0.9947371775119466)));
338 vert.add(new Vec3(new Pointing(1.1509074670044037,0.9949692293531077)));
339 vert.add(new Vec3(new Pointing(1.1507939027845748,0.9954717874109883)));
340 vert.add(new Vec3(new Pointing(1.1507154681212395,0.9958744790360815)));
341 vert.add(new Vec3(new Pointing(1.150728328381526,0.9963155562525036)));
342 vert.add(new Vec3(new Pointing(1.1507145219246022,0.9966536818156724)));
343 vert.add(new Vec3(new Pointing(1.150698010346289,0.9970594382294491)));
344 vert.add(new Vec3(new Pointing(1.1507515235186312,0.9972653214392541)));
345 vert.add(new Vec3(new Pointing(1.15074330622707,0.9974681979653209)));
346 vert.add(new Vec3(new Pointing(1.150794120124925,0.9977416918927585)));
347 vert.add(new Vec3(new Pointing(1.1508449617882088,0.9980151735411477)));
348 vert.add(new Vec3(new Pointing(1.150810006084698,0.9981151193696918)));
349 vert.add(new Vec3(new Pointing(1.1508045689258863,0.9982503689627922)));
350 vert.add(new Vec3(new Pointing(1.1507669084789147,0.9984179465727627)));
351 vert.add(new Vec3(new Pointing(1.1507882982747644,0.9986561219049502)));
352 vert.add(new Vec3(new Pointing(1.1508097091375338,0.9988942928018621)));
353 vert.add(new Vec3(new Pointing(1.1508955843794588,0.9990677867461779)));
354 vert.add(new Vec3(new Pointing(1.1509814707456794,0.9992412674747779)));
355 vert.add(new Vec3(new Pointing(1.1510968986908656,0.999450015299713)));
356 vert.add(new Vec3(new Pointing(1.1511559609826625,0.9995205731460943)));
357 vert.add(new Vec3(new Pointing(1.151370737557223,0.9995646668380104)));
358 vert.add(new Vec3(new Pointing(1.1514620182432866,0.9996028778795772)));
359 vert.add(new Vec3(new Pointing(1.1515855148424001,0.9996087523184793)));
360 vert.add(new Vec3(new Pointing(1.1516794788958802,0.9995793575868965)));
361 vert.add(new Vec3(new Pointing(1.15174122717978,0.9995822953104395)));
362 vert.add(new Vec3(new Pointing(1.1518647237644064,0.9995881703312073)));
363 vert.add(new Vec3(new Pointing(1.151894256435611,0.9996234359315822)));
364 vert.add(new Vec3(new Pointing(1.1519855379350588,0.9996616359063851)));
365 vert.add(new Vec3(new Pointing(1.152015071556617,0.9996968986628608)));
366 checkPoly(vert,13,17,"");
367 }
368 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import healpix.essentials.*;
22 import junit.framework.TestCase;
23 import java.io.*;
24 import java.util.Random;
25 import java.util.Arrays;
26
27 /** Tests for the Moc class
28
29 @copyright 2015 Max-Planck-Society
30 @author Martin Reinecke */
31 public class MocTest extends TestCase
32 {
33 private static Moc randomMoc(int num, long start, int dist)
34 {
35 Random rng = new Random();
36 Moc moc = new Moc();
37 long curval=start+(1L<<58);
38 for (int i=0; i<num; ++i)
39 {
40 long v1=curval+1+rng.nextInt(dist);
41 long v2=v1+1+rng.nextInt(dist);
42 moc.addPixelRange(29,v1,v2);
43 curval=v2;
44 }
45 return moc;
46 }
47
48 public void testSimple() throws Exception
49 {
50 Moc moc=new Moc();
51 moc.addPixelRange(0,4,5);
52 moc.addPixelRange(0,6,7);
53 moc.addPixelRange(2,4,17);
54 moc.addPixelRange(10,3000000,3000001);
55
56 assertEquals("inconsistency",moc,moc.complement().complement());
57 assertEquals("inconsistency",moc,MocStringIO.mocFromString(" 0/4, 6 2/ \t 4 -16 10/3000000 \t\n "));
58 assertEquals("inconsistency",moc,MocStringIO.mocFromString("0/6 2/ 5 2/4 2/6- 16 0/4 10/3000000"));
59 assertEquals("inconsistency",moc,MocStringIO.mocFromString
60 ("{\"0\":[6] , \"2\": [5 ], \"2\":[ 4,6,7,8,9,10,11,12,13,14,15,16], \"0\":[4], \"10\":[3000000]}"));
61 assertEquals("inconsistency",moc,MocStringIO.mocFromString(MocStringIO.mocToStringASCII(moc)));
62 assertEquals("inconsistency",moc,MocStringIO.mocFromString(MocStringIO.mocToStringJSON(moc)));
63 assertEquals("inconsistency",moc,Moc.fromUniq(moc.toUniq()));
64 assertEquals("inconsistency",moc.maxOrder(),10);
65 Moc xtmp = moc.degradedToOrder(8,false);
66 assertTrue("inconsistency",moc.contains(xtmp));
67 assertFalse("inconsistency",xtmp.contains(moc));
68 assertTrue("inconsistency",xtmp.overlaps(moc));
69 xtmp=moc.degradedToOrder(8,true);
70 assertFalse("inconsistency",moc.contains(xtmp));
71 assertTrue("inconsistency",xtmp.contains(moc));
72 assertEquals("inconsistency",moc,Moc.fromCompressed(moc.toCompressed()));
73 }
74
75 public void testPeano() throws Exception
76 {
77 HealpixBase base = new HealpixBase (8192,Scheme.NESTED);
78 RangeSet lrs=base.queryDisc(new Pointing(new Vec3(1,0,0)),Constants.halfpi/9.);
79 Moc moc=new Moc(lrs,13);
80
81 long[] arr=moc.toUniq();
82 for (int i=0; i<arr.length; ++i)
83 {
84 int order=HealpixUtils.uniq2order(arr[i]);
85 long shift=1L<<(2*order+2);
86 arr[i]=HealpixUtils.nest2peano(arr[i]-shift,order)+shift;
87 }
88 Arrays.sort(arr);
89 Moc pmoc=Moc.fromUniq(arr);
90 arr=pmoc.toUniq();
91 for (int i=0; i<arr.length; ++i)
92 {
93 int order=HealpixUtils.uniq2order(arr[i]);
94 long shift=1L<<(2*order+2);
95 arr[i]=HealpixUtils.peano2nest(arr[i]-shift,order)+shift;
96 }
97 Arrays.sort(arr);
98 Moc moc2=Moc.fromUniq(arr);
99 assertEquals(moc,moc2);
100 }
101
102 public void testOps() throws Exception
103 {
104 int niter = 100;
105 Moc full = MocStringIO.mocFromString("0/0-11");
106 Moc empty = MocStringIO.mocFromString("");
107 for (int iter=0; iter<niter; ++iter)
108 {
109 Moc a = randomMoc(1000, 0, 100);
110 assertEquals(a.complement().complement(),a);
111 assertFalse(a.overlaps(a.complement()));
112 assertEquals(a.union(a.complement()),full);
113 assertEquals(a.intersection(a.complement()),empty);
114 }
115 }
116 }
0 /*
1 * This file is part of Healpix Java.
2 *
3 * This code is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this code; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * For more information about HEALPix, see http://healpix.sourceforge.net
18 */
19 package healpix.essentials.test;
20
21 import healpix.essentials.RangeSet;
22 import junit.framework.TestCase;
23 import java.io.*;
24 import java.util.Random;
25
26 /** Tests for the RangeSet class
27
28 @copyright 2014 Max-Planck-Society
29 @author Martin Reinecke */
30 public class RangeSetTest extends TestCase {
31
32 private static RangeSet randomRangeSet(Random rng, int num, long start,
33 int dist)
34 {
35 RangeSet rs = new RangeSet(num);
36 long curval=start;
37 for (int i=0; i<num; ++i)
38 {
39 long v1=curval+1+rng.nextInt(dist);
40 long v2=v1+1+rng.nextInt(dist);
41 rs.append(v1,v2);
42 curval=v2;
43 }
44 return rs;
45 }
46
47 public void testAppend()
48 {
49 RangeSet b = new RangeSet();
50 b.append(1,11);
51 assertEquals(b,new RangeSet(new long[]{1,11}));
52 b.append(10,15);
53 assertEquals(b,new RangeSet(new long[]{1,15}));
54 b.append(1,15);
55 assertEquals(b,new RangeSet(new long[]{1,15}));
56 b.append(7,15);
57 assertEquals(b,new RangeSet(new long[]{1,15}));
58 b.append(30,41);
59 assertEquals(b,new RangeSet(new long[]{1,15,30,41}));
60 try
61 {
62 b.append(29,31);
63 fail("Should have raised an IllegalArgumentException");
64 }
65 catch (IllegalArgumentException expected) {}
66 }
67 public void testContains()
68 {
69 RangeSet b=new RangeSet(new long[]{1,11,30,41});
70 assertTrue(!b.contains(0));
71 assertTrue(b.contains(1));
72 assertTrue(b.contains(5));
73 assertTrue(b.contains(10));
74 assertTrue(!b.contains(11));
75 assertTrue(!b.contains(29));
76 assertTrue(b.contains(30));
77 assertTrue(b.contains(35));
78 assertTrue(b.contains(40));
79 assertTrue(!b.contains(41));
80 }
81 public void testAdd()
82 {
83 RangeSet b = new RangeSet();
84 b.add(5, 11);
85 assertEquals(b,new RangeSet(new long[]{5,11}));
86 b.add(1, 7);
87 assertEquals(b,new RangeSet(new long[]{1,11}));
88 b.add(1, 11);
89 assertEquals(b,new RangeSet(new long[]{1,11}));
90 b.add(30, 41);
91 assertEquals(b,new RangeSet(new long[]{1,11,30,41}));
92 b.add(1, 11);
93 assertEquals(b,new RangeSet(new long[]{1,11,30,41}));
94 b.add(-1,0);
95 assertEquals(b,new RangeSet(new long[]{-1,0,1,11,30,41}));
96 b.add(-2,-1);
97 assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
98 b.add(-2,-1);
99 assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
100 b.add(2, 11);
101 assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
102 b.add(1, 10);
103 assertEquals(b,new RangeSet(new long[]{-2,0,1,11,30,41}));
104 b.add(15, 21);
105 assertEquals(b,new RangeSet(new long[]{-2,0,1,11,15,21,30,41}));
106 }
107 public void testRemove()
108 {
109 RangeSet b = new RangeSet(new long[]{0,11,20,31});
110 b.remove(5,25);
111 assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
112 b.remove(31,32);
113 assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
114 b.remove(35,38);
115 assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
116 b.remove(-90,-80);
117 assertEquals(b,new RangeSet(new long[]{0,5,25,31}));
118 b.remove(27,29);
119 assertEquals(b,new RangeSet(new long[]{0,5,25,27,29,31}));
120 b.remove(25,26);
121 assertEquals(b,new RangeSet(new long[]{0,5,26,27,29,31}));
122 b.remove(4,6);
123 assertEquals(b,new RangeSet(new long[]{0,4,26,27,29,31}));
124 b.remove(-20,40);
125 assertEquals(b,new RangeSet(new long[]{}));
126 b.remove(-20,40);
127 assertEquals(b,new RangeSet(new long[]{}));
128 }
129 public void testIntersect2()
130 {
131 RangeSet b = new RangeSet(new long[]{0,11,20,31});
132 b.intersect(2,29);
133 assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
134 b.intersect(-8,50);
135 assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
136 b.intersect(2,50);
137 assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
138 b.intersect(2,29);
139 assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
140 b.intersect(-18,29);
141 assertEquals(b,new RangeSet(new long[]{2,11,20,29}));
142 b.intersect(3,11);
143 assertEquals(b,new RangeSet(new long[]{3,11}));
144 b = new RangeSet(new long[]{0,11,20,31});
145 b.intersect(3,15);
146 assertEquals(b,new RangeSet(new long[]{3,11}));
147 b = new RangeSet(new long[]{0,11,20,31});
148 b.intersect(17,30);
149 assertEquals(b,new RangeSet(new long[]{20,30}));
150 b = new RangeSet(new long[]{0,11,20,31});
151 b.intersect(11,20);
152 assertEquals(b,new RangeSet(new long[]{}));
153 b = new RangeSet(new long[]{0,11,20,31});
154 b.intersect(-8,-7);
155 assertEquals(b,new RangeSet(new long[]{}));
156 b = new RangeSet(new long[]{0,11,20,31});
157 b.intersect(31,35);
158 assertEquals(b,new RangeSet(new long[]{}));
159 }
160 public void testUnion()
161 {
162 assertEquals(new RangeSet(new long[]{1,11,20,31,40,56}),
163 new RangeSet(new long[]{20,31,40,51}).union
164 (new RangeSet(new long[]{1,11,45,56})));
165 assertEquals(new RangeSet(new long[]{1,11,45,56}),
166 new RangeSet(new long[]{}).union
167 (new RangeSet(new long[]{1,11,45,56})));
168 assertEquals(new RangeSet(new long[]{1,11,45,56}),
169 new RangeSet(new long[]{1,11,45,56}).union
170 (new RangeSet(new long[]{})));
171 }
172
173 public void testIntersect()
174 {
175 assertEquals(new RangeSet(new long[]{22,24,45,51}),
176 new RangeSet(new long[]{20,31,40,51}).intersection
177 (new RangeSet(new long[]{1,11,22,24,45,56})));
178 assertEquals(new RangeSet(new long[]{20,31,40,51,90,101,110,121,200,201}),
179 new RangeSet(new long[]{10,101,110,121,200,221}).intersection
180 (new RangeSet(new long[]{20,31,40,51,90,201})));
181 assertEquals(new RangeSet(new long[]{}),
182 new RangeSet(new long[]{20,31,40,51}).intersection
183 (new RangeSet(new long[]{})));
184 assertEquals(new RangeSet(new long[]{}),
185 new RangeSet(new long[]{}).intersection
186 (new RangeSet(new long[]{20,31,40,51})));
187 }
188 public void testDifference()
189 {
190 assertEquals(new RangeSet(new long[]{20,31,40,45}),
191 new RangeSet(new long[]{20,31,40,51}).difference
192 (new RangeSet(new long[]{1,11,45,56})));
193 assertEquals(new RangeSet(new long[]{}),
194 new RangeSet(new long[]{}).difference
195 (new RangeSet(new long[]{1,11,45,56})));
196 assertEquals(new RangeSet(new long[]{1,11,45,56}),
197 new RangeSet(new long[]{1,11,45,56}).difference
198 (new RangeSet(new long[]{})));
199 }
200
201 public void testContainsRS()
202 {
203 RangeSet b = new RangeSet(new long[]{20,31,40,51});
204
205 assertFalse(b.contains(0,11));
206 assertFalse(b.contains(10,21));
207 assertFalse(b.contains(19,20));
208 assertTrue(b.contains(20,21));
209 assertTrue(b.contains(21,22));
210 assertTrue(b.contains(20,31));
211 assertFalse(b.contains(25,36));
212 assertTrue(b.contains(30,31));
213 assertFalse(b.contains(31,32));
214 assertFalse(b.contains(35,38));
215 assertFalse(b.contains(35,46));
216 assertTrue(b.contains(40,41));
217 assertFalse(b.contains(45,56));
218 assertFalse(b.contains(60,71));
219 }
220 public void testContainsRS2()
221 {
222 RangeSet b = new RangeSet(new long[]{20,31,40,51});
223
224 assertTrue(b.contains(new RangeSet(new long[]{20,31,40,51})));
225 assertTrue(b.contains(new RangeSet(new long[]{20,21})));
226 assertTrue(b.contains(new RangeSet(new long[]{50,51})));
227 assertFalse(b.contains(new RangeSet(new long[]{19,31,40,51})));
228 assertFalse(b.contains(new RangeSet(new long[]{20,31,40,52})));
229 assertFalse(b.contains(new RangeSet(new long[]{20,51})));
230 assertFalse(b.contains(new RangeSet(new long[]{0,1})));
231 assertFalse(b.contains(new RangeSet(new long[]{0,20,31,40,51,100})));
232 }
233 public void testOverlaps()
234 {
235 RangeSet b = new RangeSet(new long[]{20,31,40,51});
236
237 assertFalse(b.overlaps(0,11));
238 assertTrue(b.overlaps(10,21));
239 assertFalse(b.overlaps(19,20));
240 assertTrue(b.overlaps(20,21));
241 assertTrue(b.overlaps(21,22));
242 assertTrue(b.overlaps(20,31));
243 assertTrue(b.overlaps(25,36));
244 assertTrue(b.overlaps(30,37));
245 assertFalse(b.overlaps(31,32));
246 assertFalse(b.overlaps(35,38));
247 assertTrue(b.overlaps(35,46));
248 assertTrue(b.overlaps(40,41));
249 assertTrue(b.overlaps(45,56));
250 assertFalse(b.overlaps(60,71));
251 }
252 public void testOverlaps2()
253 {
254 RangeSet b = new RangeSet(new long[]{20,31,40,51});
255
256 assertTrue(b.overlaps(new RangeSet(new long[]{20,31,40,51})));
257 assertTrue(b.overlaps(new RangeSet(new long[]{20,21})));
258 assertTrue(b.overlaps(new RangeSet(new long[]{50,51})));
259 assertTrue(b.overlaps(new RangeSet(new long[]{19,31,40,51})));
260 assertTrue(b.overlaps(new RangeSet(new long[]{20,31,40,52})));
261 assertTrue(b.overlaps(new RangeSet(new long[]{20,51})));
262 assertFalse(b.overlaps(new RangeSet(new long[]{0,1})));
263 assertFalse(b.overlaps(new RangeSet(new long[]{0,20,31,40,51,100})));
264 }
265
266 public void testIterator()
267 {
268 RangeSet b = new RangeSet(new long[]{20,31,40,51});
269 RangeSet.ValueIterator it =b.valueIterator();
270 for (int i=0; i<b.nranges(); ++i)
271 for (long j=b.ivbegin(i); j<b.ivend(i); ++j)
272 {
273 assertTrue(it.hasNext());
274 assertEquals("value mismatch", j, it.next());
275 }
276 assertFalse(it.hasNext());
277 }
278
279 public void testCompress() throws Exception
280 {
281 RangeSet r = new RangeSet(new long[]{10,20,30,40,50,51});
282 assertEquals(r,RangeSet.fromCompressed(r.toCompressed()));
283 }
284
285 private static void rsOps(RangeSet a, RangeSet b) throws Exception
286 {
287 assertFalse(b.overlaps(a.difference(b)));
288 assertTrue(a.union(b).nval()>=a.nval());
289 assertTrue(a.union(b).nval()>=b.nval());
290 assertTrue(a.intersection(b).nval()<=a.nval());
291 assertTrue(a.intersection(b).nval()<=b.nval());
292 assertTrue(a.union(b).contains(a));
293 assertTrue(a.union(b).contains(b));
294 assertFalse(a.difference(b).overlaps(b));
295 assertFalse(b.difference(a).overlaps(a));
296 assertEquals(a.union(b).nval(),a.nval()+b.nval()-a.intersection(b).nval());
297 assertEquals(a.union(b).difference(a.intersection(b)).nval(),
298 a.union(b).nval()-a.intersection(b).nval());
299 assertEquals(a,RangeSet.fromCompressed(a.toCompressed()));
300 }
301
302 public static void testOps() throws Exception
303 {
304 int niter = 100;
305 Random rng = new Random(42);
306 for (int iter=0; iter<niter; ++iter)
307 {
308 RangeSet a = randomRangeSet(rng, 1000, 0, 100);
309 RangeSet b = randomRangeSet(rng, 1000, 0, 100);
310 RangeSet c = randomRangeSet(rng, 10, 10000, 100);
311 rsOps(a,b);
312 rsOps(a,c);
313 rsOps(c,a);
314 }
315 }
316 }