001    /* @(#)FitsRGroup.java     $Revision: 1.1 $    $Date: 2002/05/06 12:41:34 $
002     *
003     * Copyright (C) 2000 European Southern Observatory 
004     * License:  GNU General Public License version 2 or later
005     */
006    package org.eso.fits;
007    
008    import java.lang.*;
009    import java.io.*;
010    
011    /** FitsRGroup class represents a FITS data matrix in the Random Group
012     *  format.
013     *
014     *  @version $Revision: 1.1 $ $Date: 2002/05/06 12:41:34 $
015     *  @author  P.Grosbol, DMD/ESO, <pgrosbol@eso.org>
016     */
017    public class FitsRGroup extends FitsData {
018    
019        private int noValues;
020        private int dataFormat = Fits.FLOAT;
021        private int bytesPerData = 4;
022        private boolean scaling = false;
023        private double zero = 0.0;
024        private double scale = 1.0;
025        private FitsWCS wcs;
026    
027        /** Constructor for FitsRGroup class given a FITS prime matrix or
028         *  an image extension header with associated data unit as a file.
029         *
030         *  @param header  FitsHeader object with the image header
031         *  @param file    RandomAccess file positioned at the start of the
032         *                 associated data unit
033         *  @param sflag   Flag for storing data matrix internally
034         *  @exception FitsException */
035        public FitsRGroup(FitsHeader header, DataInput file, boolean sflag)
036                throws FitsException {
037            super(header, file, sflag);
038    
039            if (type != Fits.RGROUP) {
040                throw  new FitsException("Wrong header type",
041                                         FitsException.HEADER);
042            }
043    
044            int nax = naxis.length;
045    
046            FitsKeyword kw = header.getKeyword("BITPIX");
047            if ((kw == null) || (kw.getType() != FitsKeyword.INTEGER)) {
048                throw  new FitsException("Invalid or missing BITPIX",
049                                         FitsException.HEADER);
050            }
051     
052            dataFormat = kw.getInt();
053            bytesPerData = Math.abs(dataFormat)/8;
054            noValues = (int) (size / bytesPerData);
055        
056            wcs = new FitsWCS(header);
057    
058            kw = header.getKeyword("BSCALE");     // check if scale is given
059            if (kw!=null) {
060                scale = kw.getReal();
061                if (scale != 1.0) {
062                    scaling = true;
063                }
064            }
065    
066            kw = header.getKeyword("BZERO");      // check if zero point is given
067            if (kw!=null) {
068                zero = kw.getReal();
069                if (zero != 0.0) {
070                    scaling = true;
071                }
072            }
073        }
074    
075        /** Create and return a minimum FITS header for data Matrix.
076         */
077        public FitsHeader getHeader() {
078            FitsHeader hdr = new FitsHeader();
079    
080            hdr.addKeyword(new FitsKeyword("SIMPLE", true,
081                                           "Standard FITS format; NOST 100-2.0"));
082            hdr.addKeyword(new FitsKeyword("BITPIX", bitpix,
083                                           "No. of bits per pixel"));
084            hdr.addKeyword(new FitsKeyword("NAXIS", naxis.length+1,
085                                           "No. of axes in image"));
086            hdr.addKeyword(new FitsKeyword("NAXIS1",0,"Random Groups convension"));
087            for (int n=2; n<=naxis.length+1; n++) {
088                hdr.addKeyword(new FitsKeyword("NAXIS"+n, naxis[n-2],
089                                               "No. of pixels"));
090            }
091            hdr.addKeyword(new FitsKeyword("PCOUNT", noParm, "Parameter count"));
092            hdr.addKeyword(new FitsKeyword("GCOUNT", noGroup, "Group count"));
093            hdr.addKeyword(new FitsKeyword("GROUPS", true,
094                                           "Random Groups format"));
095    
096    
097            return hdr;
098        }
099    
100        /** Gets set of data points from the matrix as a short values.
101         *  Only FITS file with BITPIX 8, 16 and 32 are read.
102         *
103         *  @param  offset   pixel offset within hte data matrix
104         *  @param  size     no. of pixel values to be read
105         *  @param  data     array which will hold the return values.
106         *                   If null an array of size is created.
107         *  @return          data[] array updated with pixel values
108         *  @exception FitsException */
109        public short[] getShortValues(int offset, int size, short data[])
110                throws FitsException {
111    
112            if ((offset<0) || (size<1)) return data;
113            if (noValues < offset+size) size = (int) (noValues - offset);
114            if ((data == null) || (data.length<size)) data = new short[size];
115    
116            int n = 0;
117            DataInputStream dis = getStream(offset, size);
118            try {
119                switch (dataFormat) {
120                case Fits.BYTE:
121                    while (n<size) data[n++] = (short) dis.readUnsignedByte();
122                    break;
123                case Fits.SHORT:
124                    while (n<size) data[n++] = dis.readShort();
125                    break;
126                case Fits.INT:
127                    while (n<size) data[n++] = (short) dis.readInt();
128                    break;
129                case Fits.FLOAT:
130                case Fits.DOUBLE:
131                default: return data;
132                } 
133            } catch (IOException e) {
134                throw new FitsException("Cannot convert data", FitsException.DATA);
135            }
136    
137            if (scaling) {
138              for (int i=0; i<n; i++) data[i] = (short) (scale*data[i]+zero);
139            }
140    
141            return data;
142        }
143    
144        /** Gets set of data points from the matrix as a int values.
145         *  Only FITS file with BITPIX 8, 16 and 32 are read.
146         *
147         *  @param  offset   pixel offset within hte data matrix
148         *  @param  size     no. of pixel values to be read
149         *  @param  data     array which will hold the return values.
150         *                   If null an array of size is created.
151         *  @return          data[] array updated with pixel values
152         *  @exception FitsException */
153        public int[] getFloatValues(int offset, int size, int data[])
154                throws FitsException {
155    
156            if ((offset<0) || (size<1)) return data;
157            if (noValues < offset+size) size = (int) (noValues - offset);
158            if ((data == null) || (data.length<size)) data = new int[size];
159    
160            int n = 0;
161            DataInputStream dis = getStream(offset, size);
162            try {
163                switch (dataFormat) {
164                case Fits.BYTE:
165                    while (n<size) data[n++] = (int) dis.readUnsignedByte();
166                    break;
167                case Fits.SHORT:
168                    while (n<size) data[n++] = (int) dis.readShort();
169                    break;
170                case Fits.INT:
171                    while (n<size) data[n++] = dis.readInt();
172                    break;
173                case Fits.FLOAT:
174                case Fits.DOUBLE:
175                default: return data;
176                } 
177            } catch (IOException e) {
178                throw new FitsException("Cannot convert data", FitsException.DATA);
179            }
180    
181            if (scaling) {
182              for (int i=0; i<n; i++) data[i] = (int) (scale*data[i]+zero);
183            }
184    
185            return data;
186        }
187    
188        /** Read set of data values from the matrix as a float array.  The
189         *  values are returned as a float array.
190         *
191         *  @param  offset   pixel offset within hte data matrix
192         *  @param  size     no. of pixel values to be read
193         *  @param  data     array which will hold the return values.
194         *                   If null an array of size is created.
195         *  @return          data[] array updated with pixel values
196         *  @exception FitsException */
197        public float[] getFloatValues(int offset, int size, float data[])
198                throws FitsException {
199    
200            if ((offset<0) || (size<1)) return data;
201            if (noValues < offset+size) size = (int) (noValues - offset);
202            if ((data == null) || (data.length<size)) data = new float[size];
203    
204            int n = 0;
205            DataInputStream dis = getStream(offset, size);
206            try {
207                switch (dataFormat) {
208                case Fits.BYTE:
209                    while (n<size) data[n++] = (float) dis.readUnsignedByte();
210                    break;
211                case Fits.SHORT:
212                    while (n<size) data[n++] = (float) dis.readShort();
213                    break;
214                case Fits.INT:
215                    while (n<size) data[n++] = (float) dis.readInt();
216                    break;
217                case Fits.FLOAT:
218                    while (n<size) data[n++] = dis.readFloat();
219                    break;
220                case Fits.DOUBLE:
221                    while (n<size) data[n++] = (float) dis.readDouble();
222                    break;
223                default: return data;
224                } 
225            } catch (IOException e) {
226                throw new FitsException("Cannot convert data", FitsException.DATA);
227            }
228    
229            if (scaling) {
230              for (int i=0; i<n; i++) data[i] = (float) (scale*data[i]+zero);
231            }
232    
233            return data;
234        }
235    
236        private DataInputStream getStream(int offset, int size)
237                throws FitsException {
238            DataInputStream di;
239            try {
240                dataFile.seek(dataOffset+offset*bytesPerData);
241                if (noValues < offset + size) {
242                    size = (int) (noValues - offset);
243                }
244                byte[] dbuf = new byte[size*bytesPerData];
245                dataFile.read(dbuf);
246                di = new DataInputStream(new ByteArrayInputStream(dbuf));
247            } catch (IOException e) {
248                throw new FitsException("Cannot read data", FitsException.DATA);
249            }
250            return di;
251        }
252    
253    
254        /** Gets the total number of data values in the data matrix.  */
255        public int getNoValues(){
256            return noValues;
257        }
258        
259        /** Gets reference pixel for the axes (see CRPIXn). */
260        public double[] getCrpix(){
261            return wcs.crpix;
262        }
263    
264        /** Gets coordinate value for the reference pixel of the axes
265         *  (see CRVALn). */
266        public double[] getCrval(){
267            return wcs.crval;
268        }
269    
270        /** Gets step size for the axes (see CDELTn). */
271        public double[] getCdelt(){
272            return wcs.cdelt;
273        }
274    
275        /** Gets the WCS object for the image.  */
276        public FitsWCS getWCS(){
277            return wcs;
278        }
279    
280        /** Compute World Coordinates from pixel coordinates.
281         *
282         *  @param  pix  Array with pixel coordinates
283         */
284        public double[] toWCS(double[] pix) {
285            return wcs.toWCS(pix);
286        }
287    
288        /** Compute pixel coordinates from a set of World Coordinates.
289         *
290         *  @param  wc  Array with World Coordinates
291         */
292        public double[] toPixel(double[] wc) {
293            return wcs.toPixel(wc);
294        }
295    }
296    
297