Import Upstream version 3.30
Leo Singer
7 years ago
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<<type>> | |
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<double> | |
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<float> | |
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 | } |