1/*
2 *  This file is part of Healpix Java.
3 *
4 *  This code is free software; you can redistribute it and/or modify
5 *  it under the terms of the GNU General Public License as published by
6 *  the Free Software Foundation; either version 2 of the License, or
7 *  (at your option) any later version.
8 *
9 *  This code is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 *  GNU General Public License for more details.
13 *
14 *  You should have received a copy of the GNU General Public License
15 *  along with this code; if not, write to the Free Software
16 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 *
18 *  For more information about HEALPix, see http://healpix.sourceforge.net
19 */
20
21package healpix.essentials;
22
23import java.util.Arrays;
24
25/** Class representing a full HEALPix map containing <type> values.
26    This class is conceptually very similar the the Healpix_Map&lt;<type>&gt;
27    class of Healpix_cxx.
28
29    @copyright 2011,2012 Max-Planck-Society
30    @author Martin Reinecke */
31public class HealpixMap<Type> extends HealpixBase
32  {
33  private <type>[] data;
34
35  public static final <type> undef=(<type>)(-1.6375e30);
36
37  public HealpixMap<Type>() throws Exception
38    { this(1,Scheme.NESTED); }
39  public HealpixMap<Type>(long nside_in, Scheme scheme_in) throws Exception
40    {
41    super(nside_in,scheme_in);
42    HealpixUtils.check(nside<=(1<<13),"resolution too high");
43    data=new <type>[(int)getNpix()];
44    }
45  public HealpixMap<Type>(<type>[] data_in, Scheme scheme_in) throws Exception
46    {
47    super(npix2Nside(data_in.length),scheme_in);
48    HealpixUtils.check(nside<=(1<<13),"resolution too high");
49    data=data_in;
50    }
51
52  /** Adjusts the object to nside_in.
53      @param nside_in the new Nside parameter */
54  public void setNside (long nside_in) throws Exception
55    {
56    if (nside_in!=nside)
57      {
58      super.setNside(nside_in);
59      HealpixUtils.check(nside<=(1<<13),"resolution too high");
60      data=new <type>[(int)getNpix()];
61      }
62    }
63
64  /** Adjusts the object to nside_in and scheme_in.
65      @param nside_in the new Nside parameter
66      @param scheme_in the new ordering scheme */
67  public void setNsideAndScheme (long nside_in, Scheme scheme_in)
68    throws Exception
69    {
70    super.setNsideAndScheme(nside_in,scheme_in);
71    HealpixUtils.check(nside<=(1<<13),"resolution too high");
72    data=new <type>[(int)getNpix()];
73    }
74
75  /** Adjusts the object to scheme_in, and sets pixel data to data_in.
76      @param data_in pixel data; must have a valid length (12*nside^2)
77      @param scheme_in the new ordering scheme */
78  public void setDataAndScheme(<type>[] data_in, Scheme scheme_in)
79    throws Exception
80    {
81    super.setNsideAndScheme(npix2Nside(data_in.length),scheme_in);
82    data=data_in;
83    }
84
85  /** Sets all map pixel to a specific value.
86      @param val pixel value to use */
87  public void fill(<type> val)
88    { Arrays.fill(data,val); }
89
90  /** Converts the map from NESTED to RING scheme or vice versa.
91      This operation is done in-place, i.e. it does not require additional
92      memory. */
93  public void swapScheme() throws Exception
94    {
95    HealpixUtils.check((order>=0) && (order<=13),
96      "swapping not supported for this Nside");
97    for (int m=0; m<swap_cycle[order].length; ++m)
98      {
99      int istart = swap_cycle[order][m];
100
101      <type> pixbuf = data[istart];
102      long iold = istart,
103           inew = (scheme==Scheme.RING) ? nest2ring(istart) : ring2nest(istart);
104      while (inew != istart)
105        {
106        data[(int)iold] = data[(int)inew];
107        iold = inew;
108        inew = (scheme==Scheme.RING) ? nest2ring(inew) : ring2nest(inew);
109        }
110      data[(int)iold] = pixbuf;
111      }
112    scheme = (scheme==Scheme.RING) ? Scheme.NESTED : Scheme.RING;
113    }
114
115  /** Returns the value of the pixel with a given index.
116      @param ipix index of the requested pixel
117      @return pixel value */
118  public <type> getPixel(int ipix)
119    { return data[ipix]; }
120  /** Returns the value of the pixel with a given index.
121      @param ipix index of the requested pixel
122      @return pixel value */
123  public <type> getPixel(long ipix)
124    { return data[(int)ipix]; }
125  /** Sets the value of a specific pixel.
126      @param ipix index of the pixel
127      @param val new value for the pixel */
128  public void setPixel(int ipix, <type> val)
129    { data[ipix] = val; }
130  /** Sets the value of a specific pixel.
131      @param ipix index of the pixel
132      @param val new value for the pixel */
133  public void setPixel(long ipix, <type> val)
134    { data[(int)ipix] = val; }
135
136  /** Returns the array containing all map pixels.
137      @return the map array */
138  public <type>[] getData()
139    { return data; }
140
141  /** Imports the map "orig" to this object, adjusting pixel ordering.
142      @param orig map to import */
143  public void importNograde (HealpixMap<Type> orig) throws Exception
144    {
145    HealpixUtils.check (nside==orig.nside,
146      "importNograde: maps have different nside");
147    if (orig.scheme == scheme)
148      System.arraycopy(orig.data,0,data,0,(int)npix);
149    else
150      for (int m=0; m<npix; ++m)
151        data[scheme==Scheme.NESTED ? (int)ring2nest(m) : (int)nest2ring(m)]
152          = orig.data[m];
153    }
154  /** Imports the map "orig" to this object, adjusting pixel ordering
155      and increasing resolution.
156      @param orig map to import */
157  public void importUpgrade (HealpixMap<Type> orig) throws Exception
158    {
159    HealpixUtils.check(nside>orig.nside,"importUpgrade: this is no upgrade");
160    int fact = (int)(nside/orig.nside);
161    HealpixUtils.check(nside==orig.nside*fact,
162      "the larger Nside must be a multiple of the smaller one");
163
164    for (int m=0; m<orig.npix; ++m)
165      {
166      Xyf xyf = orig.pix2xyf(m);
167      int x=xyf.ix, y=xyf.iy, f=xyf.face;
168      for (int j=fact*y; j<fact*(y+1); ++j)
169        for (int i=fact*x; i<fact*(x+1); ++i)
170          {
171          long mypix = xyf2pix(i,j,f);
172          data[(int)mypix] = orig.data[m];
173          }
174      }
175    }
176  /** Imports the map "orig" to this object, adjusting pixel ordering
177      and reducing resolution.
178      @param orig map to import
179      @param pessimistic if true, set a pixel to undefined if at least one the
180        original subpixels was undefined; otherwise only set it to undefined if
181        all original subpixels were undefined. */
182  public void importDegrade (HealpixMap<Type> orig, boolean pessimistic)
183    throws Exception
184    {
185    HealpixUtils.check(nside<orig.nside,"importDegrade: this is no degrade");
186    int fact = (int)(orig.nside/nside);
187    HealpixUtils.check(orig.nside==nside*fact,
188      "the larger Nside must be a multiple of the smaller one");
189
190    int minhits = pessimistic ? fact*fact : 1;
191    for (int m=0; m<npix; ++m)
192      {
193      Xyf xyf = pix2xyf(m);
194      int x=xyf.ix, y=xyf.iy, f=xyf.face;
195      int hits = 0;
196      double sum = 0;
197      for (int j=fact*y; j<fact*(y+1); ++j)
198        for (int i=fact*x; i<fact*(x+1); ++i)
199          {
200          int opix = (int)orig.xyf2pix(i,j,f);
201          if (!HealpixUtils.approx(orig.data[opix],undef,1e-5))
202            {
203            ++hits;
204            sum += orig.data[opix];
205            }
206          }
207      data[m] = (hits<minhits) ? undef : (<type>) (sum/hits);
208      }
209    }
210  /** Imports the map "orig" to this object, adjusting pixel ordering
211      and resolution if necessary.
212      @param orig map to import
213      @param pessimistic only used when resolution must be reduced: if true,
214        set a pixel to undefined if at least one the original subpixels
215        was undefined; otherwise only set it to undefined if all original
216        subpixels were undefined. */
217  public void importGeneral (HealpixMap<Type> orig, boolean pessimistic)
218    throws Exception
219    {
220    if (orig.nside==nside)
221      importNograde(orig);
222    else if (orig.nside<nside) // upgrading
223      importUpgrade(orig);
224    else
225      importDegrade(orig,pessimistic);
226    }
227  }
228