Begin versioning.
[fits.git] / src / nom / tam / fits / RandomGroupsHDU.java
1 package nom.tam.fits;
2
3 import nom.tam.util.ArrayFuncs;
4
5 /*
6  * Copyright: Thomas McGlynn 1997-1998.
7  * This code may be used for any purpose, non-commercial
8  * or commercial so long as this copyright notice is retained
9  * in the source code or included in or referred to in any
10  * derived software.
11  * Many thanks to David Glowacki (U. Wisconsin) for substantial
12  * improvements, enhancements and bug fixes.
13  */
14 /** Random groups HDUs.  Note that the internal storage of random
15  * groups is a Object[ngroup][2] array.  The first element of
16  * each group is the parameter data from that group.  The second element
17  * is the data.  The parameters should be a one dimensional array
18  * of the primitive types byte, short, int, long, float or double.
19  * The second element is a n-dimensional array of the same type.
20  * When analyzing group data structure only the first group is examined,
21  * but for a valid FITS file all groups must have the same structure.
22  */
23 public class RandomGroupsHDU extends BasicHDU {
24
25     Object dataArray;
26
27     /** Create an HDU from the given header and data */
28     public RandomGroupsHDU(Header h, Data d) {
29         myHeader = h;
30         myData = d;
31     }
32
33     /** Indicate that a RandomGroupsHDU can come at
34      *  the beginning of a FITS file.
35      */
36     protected boolean canBePrimary() {
37         return true;
38     }
39
40     /** Move a RandomGroupsHDU to or from the beginning
41      *  of a FITS file.  Note that the FITS standard only
42      *  supports Random Groups data at the beginning
43      *  of the file, but we allow it within Image extensions.
44      */
45     protected void setPrimaryHDU(boolean status) {
46         try {
47             super.setPrimaryHDU(status);
48         } catch (FitsException e) {
49             System.err.println("Unreachable catch in RandomGroupsHDU");
50         }
51         if (status) {
52             myHeader.setSimple(true);
53         } else {
54             myHeader.setXtension("IMAGE");
55         }
56     }
57
58     /** Make a header point to the given object.
59      * @param odata The random groups data the header should describe.
60      */
61     static Header manufactureHeader(Data d) throws FitsException {
62
63         if (d == null) {
64             throw new FitsException("Attempt to create null Random Groups data");
65         }
66         Header h = new Header();
67         d.fillHeader(h);
68         return h;
69
70     }
71
72     /** Is this a random groups header?
73      * @param myHeader The header to be tested.
74      */
75     public static boolean isHeader(Header hdr) {
76
77         if (hdr.getBooleanValue("SIMPLE")) {
78             return hdr.getBooleanValue("GROUPS");
79         }
80
81         String s = hdr.getStringValue("XTENSION");
82         if (s.trim().equals("IMAGE")) {
83             return hdr.getBooleanValue("GROUPS");
84         }
85
86         return false;
87     }
88
89     /** Check that this HDU has a valid header.
90      * @return <CODE>true</CODE> if this HDU has a valid header.
91      */
92     public boolean isHeader() {
93         return isHeader(myHeader);
94     }
95
96     /** Check if this data is compatible with Random Groups structure.
97      *  Must be an Object[ngr][2] structure with both elements of each
98      *  group having the same base type and the first element being
99      *  a simple primitive array.  We do not check anything but
100      *  the first row.
101      */
102     public static boolean isData(Object oo) {
103         if (oo instanceof Object[][]) {
104
105             Object[][] o = (Object[][]) oo;
106
107             if (o.length > 0) {
108                 if (o[0].length == 2) {
109                     if (ArrayFuncs.getBaseClass(o[0][0])
110                             == ArrayFuncs.getBaseClass(o[0][1])) {
111                         String cn = o[0][0].getClass().getName();
112                         if (cn.length() == 2 && cn.charAt(1) != 'Z'
113                                 || cn.charAt(1) != 'C') {
114                             return true;
115                         }
116                     }
117                 }
118             }
119         }
120         return false;
121     }
122
123     /** Create a FITS Data object corresponding to
124      * this HDU header.
125      */
126     public Data manufactureData() throws FitsException {
127         return manufactureData(myHeader);
128     }
129
130     /** Create FITS data object corresponding to a given header.
131      */
132     public static Data manufactureData(Header hdr) throws FitsException {
133
134         int gcount = hdr.getIntValue("GCOUNT", -1);
135         int pcount = hdr.getIntValue("PCOUNT", -1);
136
137         if (!hdr.getBooleanValue("GROUPS")
138                 || hdr.getIntValue("NAXIS1", -1) != 0
139                 || gcount < 0 || pcount < 0
140                 || hdr.getIntValue("NAXIS") < 2) {
141             throw new FitsException("Invalid Random Groups Parameters");
142         }
143
144         // Allocate the object.
145         Object[][] dataArray;
146
147         if (gcount > 0) {
148             dataArray = new Object[gcount][2];
149         } else {
150             dataArray = new Object[0][];
151         }
152
153         Object[] sampleRow = generateSampleRow(hdr);
154         for (int i = 0; i < gcount; i += 1) {
155             ((Object[][]) dataArray)[i][0] =
156                     ((Object[]) nom.tam.util.ArrayFuncs.deepClone(sampleRow))[0];
157             ((Object[][]) dataArray)[i][1] =
158                     ((Object[]) nom.tam.util.ArrayFuncs.deepClone(sampleRow))[1];
159         }
160         return new RandomGroupsData(dataArray);
161
162     }
163
164     static Object[] generateSampleRow(Header h)
165             throws FitsException {
166
167         int ndim = h.getIntValue("NAXIS", 0) - 1;
168         int[] dims = new int[ndim];
169
170         int bitpix = h.getIntValue("BITPIX", 0);
171
172
173         Class baseClass;
174
175         switch (bitpix) {
176             case 8:
177                 baseClass = Byte.TYPE;
178                 break;
179             case 16:
180                 baseClass = Short.TYPE;
181                 break;
182             case 32:
183                 baseClass = Integer.TYPE;
184                 break;
185             case 64:
186                 baseClass = Long.TYPE;
187                 break;
188             case -32:
189                 baseClass = Float.TYPE;
190                 break;
191             case -64:
192                 baseClass = Double.TYPE;
193                 break;
194             default:
195                 throw new FitsException("Invalid BITPIX:" + bitpix);
196         }
197
198         // Note that we have to invert the order of the axes
199         // for the FITS file to get the order in the array we
200         // are generating.  Also recall that NAXIS1=0, so that
201         // we have an 'extra' dimension.
202
203         for (int i = 0; i < ndim; i += 1) {
204             long cdim = h.getIntValue("NAXIS" + (i + 2), 0);
205             if (cdim < 0) {
206                 throw new FitsException("Invalid array dimension:" + cdim);
207             }
208             dims[ndim - i - 1] = (int) cdim;
209         }
210
211         Object[] sample = new Object[2];
212         sample[0] = ArrayFuncs.newInstance(baseClass, h.getIntValue("PCOUNT"));
213         sample[1] = ArrayFuncs.newInstance(baseClass, dims);
214
215         return sample;
216     }
217
218     public static Data encapsulate(Object o) throws FitsException {
219         if (o instanceof Object[][]) {
220             return new RandomGroupsData((Object[][]) o);
221         } else {
222             throw new FitsException("Attempt to encapsulate invalid data in Random Group");
223         }
224     }
225
226     /** Display structural information about the current HDU.
227      */
228     public void info() {
229
230         System.out.println("Random Groups HDU");
231         if (myHeader != null) {
232             System.out.println("   HeaderInformation:");
233             System.out.println("     Ngroups:" + myHeader.getIntValue("GCOUNT"));
234             System.out.println("     Npar:   " + myHeader.getIntValue("PCOUNT"));
235             System.out.println("     BITPIX: " + myHeader.getIntValue("BITPIX"));
236             System.out.println("     NAXIS:  " + myHeader.getIntValue("NAXIS"));
237             for (int i = 0; i < myHeader.getIntValue("NAXIS"); i += 1) {
238                 System.out.println("      NAXIS" + (i + 1) + "= "
239                         + myHeader.getIntValue("NAXIS" + (i + 1)));
240             }
241         } else {
242             System.out.println("    No Header Information");
243         }
244
245
246         Object[][] data = null;
247         if (myData != null) {
248             try {
249                 data = (Object[][]) myData.getData();
250             } catch (FitsException e) {
251                 data = null;
252             }
253         }
254
255         if (data == null || data.length < 1 || data[0].length != 2) {
256             System.out.println("    Invalid/unreadable data");
257         } else {
258             System.out.println("    Number of groups:" + data.length);
259             System.out.println("    Parameters: " + nom.tam.util.ArrayFuncs.arrayDescription(data[0][0]));
260             System.out.println("    Data:" + nom.tam.util.ArrayFuncs.arrayDescription(data[0][1]));
261         }
262     }
263 }