/*
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.amanda;

import java.rmi.RemoteException;

import visad.Data;
import visad.FieldImpl;
import visad.FlatField;
import visad.FunctionType;
import visad.Gridded1DSet;
import visad.Gridded3DSet;
import visad.RealTupleType;
import visad.RealType;
import visad.SetType;
import visad.VisADException;

import visad.util.Util;

public abstract class BaseTrack
  implements Comparable
{
  public static final RealType indexType =
    RealType.getRealType("Track_Index");

  private static final RealType energyType =
    RealType.getRealType("Track_Energy");

  public static FunctionType functionType;
  public static FunctionType timeSequenceType;
  public static FieldImpl missing;

  private static FunctionType indexTupleType;

  static {
    try {
      functionType =
        new FunctionType(AmandaFile.xyzType,
                         new RealTupleType(RealType.Time, energyType));

      timeSequenceType = new FunctionType(RealType.Time,
                                          new SetType(AmandaFile.xyzType));

      Gridded1DSet set = new Gridded1DSet(RealType.Time, new float[1][1], 1);
      missing = new FieldImpl(timeSequenceType, set);
    } catch (VisADException ve) {
      ve.printStackTrace();
      functionType = null;
      indexTupleType = null;
      timeSequenceType = null;
      missing = null;
    }
  }

  private static final float LENGTH_SCALE = 1000.0f;

  private static final int X_SAMPLE = 0;
  private static final int Y_SAMPLE = 1;
  private static final int Z_SAMPLE = 2;

  private float xstart;
  private float ystart;
  private float zstart;
  private float zenith;
  private float azimuth;
  private float length;
  private float energy;
  private float time;
  private float maxLength;

  private float[] timeSteps;
  private float[][] samples;

  BaseTrack(float xstart, float ystart, float zstart, float zenith,
            float azimuth, float length, float energy, float time)
  {
    this.xstart = xstart;
    this.ystart = ystart;
    this.zstart = zstart;
    this.zenith = zenith;
    this.azimuth = azimuth;
    this.length = length;
    this.energy = energy;
    this.time = time;

    timeSteps = null;
    samples = null;
  }

  private static final int compareFloat(float f0, float f1)
  {
    if (Util.isApproximatelyEqual(f0, f1)) {
      return 0;
    }

    return (f0 < f1 ? -1 : 1);
  }

  public int compareTo(Object obj)
  {
    if (obj instanceof BaseTrack) {
      return compareTo((BaseTrack )obj);
    }

    return getClass().getName().compareTo(obj.getClass().getName());
  }

  public int compareTo(BaseTrack t)
  {
    int cmp = compareFloat(time, t.time);
    if (cmp == 0) {
      cmp = compareFloat(xstart, t.xstart);
      if (cmp == 0) {
        cmp = compareFloat(ystart, t.ystart);
        if (cmp == 0) {
          cmp = compareFloat(zstart, t.zstart);
          if (cmp == 0) {
            cmp = compareFloat(zenith, t.zenith);
            if (cmp == 0) {
              cmp = compareFloat(azimuth, t.azimuth);
              if (cmp == 0) {
                // negate this since we want to prefer higher-energy tracks
                cmp = -compareFloat(energy, t.energy);
                if (cmp == 0) {
                  // negate this since we want to prefer longer tracks
                  cmp = -compareFloat(length, t.length);
                }
              }
            }
          }
        }
      }
    }

    return cmp;
  }

  final void computeSamples(float[] timeSteps)
  {
    final double degrees2radians = Data.DEGREES_TO_RADIANS;

    final double sinZenith = Math.sin(zenith * degrees2radians);
    final double cosZenith = Math.cos(zenith * degrees2radians);

    final double sinAzimuth = Math.sin(azimuth * degrees2radians);
    final double cosAzimuth = Math.cos(azimuth * degrees2radians);

    // speed of light (.3 m/nanosecond)
    final double SPEED_OF_LIGHT = 0.3 /* * 1000.0 */;

    final float timeOrigin, xOrigin, yOrigin, zOrigin;
    if (timeSteps.length == 0) {
      timeOrigin = time;
      xOrigin = xstart;
      yOrigin = ystart;
      zOrigin = zstart;
      samples = null;
    } else {
      timeOrigin = timeSteps[0];

      final double length = (timeOrigin - time) * SPEED_OF_LIGHT;

      xOrigin = xstart + (float )(length * sinZenith * cosAzimuth);
      yOrigin = ystart + (float )(length * sinZenith * sinAzimuth);
      zOrigin = zstart + (float )(length * cosZenith);

      samples = new float[timeSteps.length + 1][3];

      samples[0][X_SAMPLE] = xOrigin;
      samples[0][Y_SAMPLE] = yOrigin;
      samples[0][Z_SAMPLE] = zOrigin;
    }

    for (int i = 0; i < timeSteps.length; i++) {

      final double length = (timeSteps[i] - timeOrigin) * SPEED_OF_LIGHT;

      float xDelta = (float )(length * sinZenith * cosAzimuth);
      float yDelta = (float )(length * sinZenith * sinAzimuth);
      float zDelta = (float )(length * cosZenith);

      samples[i][X_SAMPLE] = xOrigin + xDelta;
      samples[i][Y_SAMPLE] = yOrigin + yDelta;
      samples[i][Z_SAMPLE] = zOrigin + zDelta;
    }

    this.timeSteps = timeSteps;
  }

  public boolean equals(Object obj) { return compareTo(obj) == 0; }

  public final float getEnergy() { return energy; }
  public final float getLength() { return length; }

  private final float getMaxSample(int sample, float dfltValue)
  {
    if (samples == null) {
      System.err.println("BaseTrack.getMaxSample() called before " +
                         "BaseTrack.computeSamples()");
      Thread.dumpStack();
      return dfltValue;
    }

    float max = samples[0][sample];
    for (int i = 1; i < samples.length; i++) {
      if (samples[i][sample] > max) max = samples[i][sample];
    }

    return max;
  }

  private final float getMinSample(int sample, float dfltValue)
  {
    if (samples == null) {
      System.err.println("BaseTrack.getMinSample() called before " +
                         "BaseTrack.computeSamples()");
      Thread.dumpStack();
      return dfltValue;
    }

    float min = samples[0][sample];
    for (int i = 1; i < samples.length; i++) {
      if (samples[i][sample] < min) min = samples[i][sample];
    }

    return min;
  }

  public final float getXMax() { return getMaxSample(X_SAMPLE, xstart); }
  public final float getXMin() { return getMinSample(X_SAMPLE, xstart); }
  public final float getYMax() { return getMaxSample(Y_SAMPLE, xstart); }
  public final float getYMin() { return getMinSample(Y_SAMPLE, ystart); }
  public final float getZMax() { return getMaxSample(Z_SAMPLE, xstart); }
  public final float getZMin() { return getMinSample(Z_SAMPLE, zstart); }

  abstract FlatField makeData()
    throws VisADException;

  final FlatField makeData(float maxLength)
    throws VisADException
  {
    float fldLength = length;
    if (fldLength > maxLength) {
      fldLength = maxLength;
    } else if (fldLength != fldLength) {
      fldLength = -1.0f;
    }

    float fldEnergy = energy;
    if (fldEnergy != fldEnergy) {
      fldEnergy = 1.0f;
    }

    float zs = (float) Math.sin(zenith * Data.DEGREES_TO_RADIANS);
    float zc = (float) Math.cos(zenith * Data.DEGREES_TO_RADIANS);
    float as = (float) Math.sin(azimuth * Data.DEGREES_TO_RADIANS);
    float ac = (float) Math.cos(azimuth * Data.DEGREES_TO_RADIANS);
    float zinc = fldLength * zc;
    float xinc = fldLength * zs * ac;
    float yinc = fldLength * zs * as;

    float[][] locs = {{xstart - LENGTH_SCALE * xinc,
                       xstart + LENGTH_SCALE * xinc},
                      {ystart - LENGTH_SCALE * yinc,
                       ystart + LENGTH_SCALE * yinc},
                      {zstart - LENGTH_SCALE * zinc,
                       zstart + LENGTH_SCALE * zinc}};

    // construct Field for fit
    Gridded3DSet set = new Gridded3DSet(AmandaFile.xyzType, locs, 2);
    FlatField field = new FlatField(functionType, set);
    float[][] values = {{time, time}, {fldEnergy, fldEnergy}};

    try {
      field.setSamples(values, false);
    } catch (RemoteException re) {
      re.printStackTrace();
      return null;
    }

    return field;
  }

  final FieldImpl makeTimeSequence(float[] timeSteps)
  {
    if (timeSteps == null || timeSteps.length == 0) {
      return null;
    }

    final double degrees2radians = Data.DEGREES_TO_RADIANS;

    // zenith value is the direction from which
    // the muon came, not the direction in which it's going,
    // so it's 180 degrees off
    final double z2 = ((double )zenith + 180.0) % 360.0;

    final double a2 = (double )azimuth;

    final double sinZenith = Math.sin(z2 * degrees2radians);
    final double cosZenith = Math.cos(z2 * degrees2radians);

    final double sinAzimuth = Math.sin(a2 * degrees2radians);
    final double cosAzimuth = Math.cos(a2 * degrees2radians);

    // speed of light (.3 m/nanosecond)
    final double SPEED_OF_LIGHT = 0.3;

    Gridded3DSet[] sets = new Gridded3DSet[timeSteps.length];
    Gridded3DSet missingSet = null;

    final float timeOrigin = timeSteps[0];
    final float timeFinal = timeSteps[timeSteps.length - 1];

    final double baseTime = (timeOrigin - time);
    final double baseLength = baseTime * SPEED_OF_LIGHT;

    final float xOrigin, yOrigin, zOrigin;
    xOrigin = xstart + (float )(baseLength * sinZenith * cosAzimuth);
    yOrigin = ystart + (float )(baseLength * sinZenith * sinAzimuth);
    zOrigin = zstart + (float )(baseLength * cosZenith);

    final double preTime = baseTime - ((timeFinal - timeOrigin) / 2.0);
    final double preLength = preTime * SPEED_OF_LIGHT;

    final float xPreOrigin, yPreOrigin, zPreOrigin;
    xPreOrigin = xstart + (float )(preLength * sinZenith * cosAzimuth);
    yPreOrigin = ystart + (float )(preLength * sinZenith * sinAzimuth);
    zPreOrigin = zstart + (float )(preLength * cosZenith);

    for (int i = 0; i < timeSteps.length; i++) {

      final double length = (timeSteps[i] - timeOrigin) * SPEED_OF_LIGHT;

      final float xEndpoint, yEndpoint, zEndpoint;
      xEndpoint = xOrigin + (float )(length * sinZenith * cosAzimuth);
      yEndpoint = yOrigin + (float )(length * sinZenith * sinAzimuth);
      zEndpoint = zOrigin + (float )(length * cosZenith);

      float[][] locs = {
        { xPreOrigin, xEndpoint },
        { yPreOrigin, yEndpoint },
        { zPreOrigin, zEndpoint },
      };

      Gridded3DSet subSet;
      try {
        subSet = new Gridded3DSet(AmandaFile.xyzType, locs, 2);
      } catch (VisADException ve) {
        ve.printStackTrace();

        if (missingSet == null) {
          try {
            missingSet =
              new Gridded3DSet(AmandaFile.xyzType, new float[3][1], 1);
          } catch (VisADException ve2) {
            ve2.printStackTrace();
          }
        }
        subSet = missingSet;
      }

      sets[i] = subSet;
    }

    Gridded1DSet set;
    try {
      set = new Gridded1DSet(RealType.Time,
                             new float[][] { timeSteps },
                             timeSteps.length);
    } catch (VisADException ve) {
      ve.printStackTrace();
      set = null;
    }

    FieldImpl fld;
    try {
      fld = new FieldImpl(timeSequenceType, set);
      fld.setSamples(sets, false);
    } catch (VisADException ve) {
      ve.printStackTrace();
      fld = missing;
    } catch (RemoteException re) {
      re.printStackTrace();
      fld = missing;
    }

    return fld;
  }

  public String toString()
  {
    String fullName = getClass().getName();
    int pt = fullName.lastIndexOf('.');
    final int ds = fullName.lastIndexOf('$');
    if (ds > pt) {
      pt = ds;
    }
    String className = fullName.substring(pt == -1 ? 0 : pt + 1);

    return className + "[" + xstart + "," + ystart + "," + zstart +
      " LA#" + zenith + " LO#" + azimuth + " LE#" + length + " NRG#" +
      energy + " TIM#" + time + "]";
  }
}

 

Ads help maintain this website.