/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/

package visad.data.fits;

import java.rmi.RemoteException;

import nom.tam.fits.BasicHDU;
import nom.tam.fits.BinaryTableHDU;
import nom.tam.fits.Column;
import nom.tam.fits.Fits;
import nom.tam.fits.FitsException;
import nom.tam.fits.ImageHDU;
import nom.tam.fits.PrimaryHDU;

import nom.tam.util.ArrayFuncs;

import visad.FieldImpl;
import visad.FlatField;
import visad.Function;
import visad.FunctionType;
import visad.GriddedSet;
import visad.MathType;
import visad.RealTupleType;
import visad.Scalar;
import visad.ScalarType;
import visad.Set;
import visad.VisADException;
import visad.UnimplementedException;

public class TourWriter
	extends Tourist
{
  private Fits fits;

  public TourWriter(boolean replace, Fits fits)
  {
    super(replace);
    this.fits = fits;
  }

  private String[] getNames(RealTupleType rtt)
	throws VisADException
  {
    int dim = rtt.getDimension();
    if (dim == 0) {
      return null;
    }

    String[] list = new String[dim];
    for (int i = 0; i < dim; i++) {
      MathType type = rtt.getComponent(i);
      if (!(type instanceof ScalarType)) {
	throw new VisADException("Expected a ScalarType name, got " +
				 type.getClass().getName());
      }

      list[i] = ((ScalarType )type).getName();
    }

    return list;
  }

  private String[] getNames(ScalarType st)
	throws VisADException
  {
    String[] list = new String[1];
    list[0] = st.getName();
    return list;
  }

  private String[] getNames(MathType mt)
	throws VisADException
  {
    if (mt instanceof RealTupleType) {
      return getNames((RealTupleType )mt);
    }
    if (mt instanceof ScalarType) {
      return getNames((ScalarType )mt);
    }
    throw new VisADException("Couldn't get list of names from " +
			     mt.getClass().getName());
  }

  private void saveBinaryTable(FlatField fld, int domainDim, int rangeDim)
	throws VisADException
  {
    System.err.println("TourWriter.saveBinaryTable(" + domainDim + ", " + rangeDim + "):");

    FunctionType funcType = (FunctionType )fld.getType();

    String[] rangeNames = getNames(funcType.getRange());

    BinaryTableHDU hdu;
    try {
      hdu = new BinaryTableHDU();
    } catch (FitsException e) {
      throw new VisADException("Couldn't create BinaryTableHDU: " +
			       e.getMessage());
    }

    double[][] values = fld.getValues();
    System.err.println("\tvalues: " + values.length + "x" + values[0].length);

    double[][] column = new double[1][];
    int[] lengths = new int[2];

    Object[][] table = new Object[values.length][];

    lengths[0] = 1;
    for (int i = 0; i < table.length; i++) {
      column[0] = values[i];
      lengths[1] = column[0].length;

      ConvertDoubleArray cvtArray = new ConvertDoubleArray(lengths, column);
      Object o = cvtArray.getConverter().getRowMajor(column);
      if (o == null) {
	throw new VisADException("Couldn't extract array from column #" + i);
      }

      try {
	Column col = new Column();
	col.setData((Object[] )o);

	String num = "" + i;

	StringBuffer buf = new StringBuffer(8);

	if (rangeNames != null) {
	  buf.setLength(0);
	  buf.append("TTYPE");
	  buf.append(num);
	  buf.append("        ");
	  buf.setLength(8);
	  buf.append("= '");
	  buf.append(rangeNames[i]);
	  buf.append("'");
	  col.addKey(buf.toString());
	}

	hdu.addColumn(col);
      } catch (FitsException e) {
	System.err.println("Couldn't add binary table column #" + i + ": " +
			   e.getMessage());
      }
    }

    try {
      fits.addHDU(hdu);
    } catch (FitsException e) {
      throw new VisADException("Couldn't add FITS binary table HDU : " +
			       e.getMessage());
    }
  }

  private void saveImage(FlatField fld, int domainDim, int rangeDim)
	throws VisADException
  {
    Set set = fld.getDomainSet();

    if (!(set instanceof GriddedSet)) {
      throw new VisADException("Cannot build FITS Image" +
			       " from non-Gridded domain");
    }

    int size;
    try {
      size = fits.size();
    } catch (FitsException e) {
      System.err.println("TourWriter.saveImage: Yikes!  Fits.size() threw");
      e.printStackTrace(System.err);
      throw new VisADException("Couldn't get size of FITS file");
    }

    final int[] lengths = ((GriddedSet )set).getLengths();
    if (lengths.length != 2) {
      throw new VisADException("Don't know how to decipher " + lengths.length +
                               "-dimension FlatField!");
    }

    double[][] values = fld.getValues();
    if (values[0].length != lengths[0]*lengths[1]) {
      throw new VisADException("Mismatch between FlatField length array" +
                               " and value array length");
    } else if (values.length != 1 && values.length != 3) {
      throw new VisADException("Don't know how to decipher " + values.length +
                               "-dimension FlatField values!");
    }

    // create 8-bit color value array
    final int len = values[0].length;
    byte[] colorVals = new byte[len];

    // fill in 8-bit color values
    int colRow, valIndex;
    valIndex = 0;
    for (int i = lengths[1] - 1; i >= 0; i--) {
      colRow = i * lengths[0];
      for (int j = 0; j < lengths[0]; j++) {
        int v;
        if (values.length == 3) {
          // map to RGB
          v = (int )((0.299 * values[0][valIndex]) +
                     (0.587 * values[1][valIndex]) +
                     (0.114 * values[2][valIndex]));
        } else {
          v = (int )values[0][valIndex];
        }
        colorVals[colRow+j] = (byte )v;

        valIndex++;
      }
    }

    byte[][] image = (byte[][] )ArrayFuncs.curl(colorVals, lengths);

    try {
      BasicHDU hdu;
      if (size == 0) {
	hdu = new PrimaryHDU((Object )image);
      } else {
	hdu = new ImageHDU((Object )image);
      }

      fits.addHDU(hdu);
    } catch (FitsException e) {
      throw new VisADException("Couldn't build " +
			       (size == 0 ? "primary" : "image") +
			       " FITS HDU : " + e.getMessage());
    }
  }

  private void save(FlatField fld)
	throws RemoteException, VisADException
  {
    MathType type = fld.getType();
    if (!(type instanceof FunctionType)) {
      throw new VisADException("Confused Data object" +
			       " (FlatField with non-FunctionType)");
    }

    int domainDim = fld.getDomainSet().getDimension();
    if (domainDim > 2) {
      throw new VisADException("Can't write FITS file with" +
			       " domain dimension of " + domainDim);
    }

    int rangeDim = fld.getRangeDimension();
    if (rangeDim != 1 && rangeDim != 3) {
      throw new VisADException("Can't write FITS file with" +
			       " range dimension of " + rangeDim);
    }

    if (domainDim != 2) {
      saveBinaryTable(fld, domainDim, rangeDim);
    } else {
      saveImage(fld, domainDim, rangeDim);
    }
  }

  private void save(FieldImpl fld)
	throws RemoteException, VisADException
  {
    if (fld instanceof FlatField) {
      save((FlatField )fld);
      return;
    }

    throw new UnimplementedException("Can only save FlatField data");
  }

  public boolean visit(Function func, int depth)
	throws RemoteException, VisADException
  {

    if (!(func instanceof FieldImpl)) {
      throw new UnimplementedException("Can only save FieldImpl data");
    }

    save((FieldImpl )func);
    return true;
  }

  public boolean visit(Scalar scalar, int depth)
	throws VisADException
  {
    return false;
  }

  public boolean visit(Set set, int depth)
	throws VisADException
  {
    throw new UnimplementedException("Cannot write Set data to FITS files yet");
  }
}

 

Ads help maintain this website.