All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.iosp.sigmet.SigmetVolumeScan Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */


package ucar.nc2.iosp.sigmet;

//~--- non-JDK imports --------------------------------------------------------

import ucar.nc2.Variable;
import ucar.unidata.io.RandomAccessFile;

import java.util.*;

/**
 * @author yuanho
 * @since Apr 7, 2010
 */
public class SigmetVolumeScan {
  String[] data_name = {
          " ", "TotalPower", "Reflectivity", "Velocity", "Width", "DifferentialReflectivity"
  };
  private List> differentialReflectivityGroups;
  private List> reflectivityGroups;
  private List> totalPowerGroups;
  private List> velocityGroups;
  private List> widthGroups;
  private List> timeGroups;
  private int[] num_gates;
  public int[] base_time;
  public short[] year;
  public short[] month;
  public short[] day;
  public Ray firstRay = null;
  public Ray lastRay = null;
  public ucar.unidata.io.RandomAccessFile raf;
  public boolean hasReflectivity = false;
  public boolean hasVelocity = false;
  public boolean hasWidth = false;
  public boolean hasTotalPower = false;
  public boolean hasDifferentialReflectivity = false;
  public boolean hasTime = false;

  /**
   * Read all the values from SIGMET-IRIS file which are necessary to fill in the ncfile.
   *
   * @param raf     ucar.unidata.io.RandomAccessFile corresponds to SIGMET datafile.
   * @param ncfile  an empty NetcdfFile object which will be filled.
   * @param varList ArrayList of Variables of ncfile
   */
  SigmetVolumeScan(ucar.unidata.io.RandomAccessFile raf, ucar.nc2.NetcdfFile ncfile, ArrayList varList)
          throws java.io.IOException {
    final int REC_SIZE = 6144;
    int len = 12288;    // ---- Read from the 3d record----------- 6144*2=12288
    short nrec = 0,
            nsweep = 1,
            nray = 0,
            byteoff = 0;
    int nwords = 0,
            end_words = 0,
            data_read = 0,
            num_zero = 0,
            rays_count = 0,
            nb = 0,
            pos = 0,
            pos_ray_hdr = 0,
            t = 0;
    short a0 = 0,
            a00 = 0,
            dty = 1;
    short beg_az = 0,
            beg_elev = 0,
            end_az = 0,
            end_elev = 0,
            num_bins = 0,
            time_start_sw = 0;
    float az = 0.0f,
            elev = 0.0f,
            d = 0.0f,
            step = 0.0f;
    //     byte      data          = 0;
    boolean beg_rec = true,
            end_rec = true,
            read_ray_hdr = true,
            begin = true;
    int cur_len = len,
            beg = 1,
            kk = 0,
            col = 0,
            nu = 0,
            bt0 = 0,
            bt1 = 0;
    int start_sweep = 1,
            end_sweep = 1,
            start_ray = 1,
            end_ray = 1;

    // Input
    this.raf = raf;
    raf.order(RandomAccessFile.LITTLE_ENDIAN);

    int fileLength = (int) raf.length();
    java.util.Map recHdr = SigmetIOServiceProvider.readRecordsHdr(raf);
    int nparams = recHdr.get("nparams").intValue();    // System.out.println("DO: nparams="+nparams);
    short number_sweeps = recHdr.get("number_sweeps").shortValue();

    // System.out.println("DO: number_sweeps="+number_sweeps);
    short num_rays = recHdr.get("num_rays").shortValue();

    // System.out.println("DO: num_rays="+num_rays);
    int range_1st = recHdr.get("range_first").intValue();
    float range_first = range_1st * 0.01f;
    int stepp = recHdr.get("range_last").intValue();

    // System.out.println("DO: stepp="+stepp);
    float range_last = stepp * 0.01f;
    short bins = recHdr.get("bins").shortValue();

    // System.out.println("DO: bins="+bins);
    // int[]   base_time    = new int[nparams * number_sweeps];

    short[] num_sweep = new short[nparams];
    short[] num_rays_swp = new short[nparams];
    short[] indx_1ray = new short[nparams];
    short[] num_rays_act = new short[nparams];
    short[] angl_swp = new short[nparams];
    short[] bin_len = new short[nparams];
    short[] data_type = new short[nparams];
    // float[] dd           = new float[bins];
    num_gates = new int[number_sweeps];
    end_sweep = (int) number_sweeps;
    end_ray = (int) num_rays;
    base_time = new int[nparams * number_sweeps];
    year = new short[nparams * number_sweeps];
    month = new short[nparams * number_sweeps];
    day = new short[nparams * number_sweeps];
    // Array of Ray objects is 2D. Number of columns=number of rays
    // Number of raws = number of types of data if number_sweeps=1,
    // or number of raws = number_sweeps
    List totalPower = new ArrayList();
    List velocity = new ArrayList();
    List reflectivity = new ArrayList();
    List width = new ArrayList();
    List diffReflectivity = new ArrayList();
    List time = new ArrayList();
    int irays = (int) num_rays;
    Ray ray = null;
    int two = 0;
    // init array
    float[] val = new float[bins];

    while (len < fileLength) {
      int rayoffset = 0;
      int rayoffset1 = 0;
      int datalen = 0;

      cur_len = len;

      if (nsweep == number_sweeps & rays_count == beg) {
        return;
      }

      if (beg_rec) {

        // ---   12bytes -----------
        raf.seek(cur_len);
        nrec = raf.readShort();    // cur_len
        nsweep = raf.readShort();    // cur_len+2
        byteoff = raf.readShort();
        len = len + 2;            // cur_len+4
        nray = raf.readShort();
        len = len + 2;            // cur_len+6

        // ---- end of  -------------
        cur_len = cur_len + 12;
        beg_rec = false;
      }

      if ((nsweep <= number_sweeps) & (rays_count % beg == 0)) {

        // --Read  Number of them=nparams*number_sweeps -----
        // ---Len of =76 bytes -----------------
        beg = 0;

        for (int i = 0; i < nparams; i++) {
          int idh_len = cur_len + 12 + i * 76;

          raf.seek(idh_len);

          // Read seconds since midnight
          base_time[nu] = raf.readInt();         // idh_len
          raf.skipBytes(2);
          year[nu] = raf.readShort();           // idh_len+6
          month[nu] = raf.readShort();           // idh_len+8
          day[nu] = raf.readShort();           // idh_len+10
          nu++;
          num_sweep[i] = raf.readShort();     // idh_len+12
          num_rays_swp[i] = raf.readShort();     // idh_len+14
          indx_1ray[i] = raf.readShort();     // idh_len+16
          raf.skipBytes(2);
          num_rays_act[i] = raf.readShort();
          beg += num_rays_act[i];    // idh_len+20
          angl_swp[i] = raf.readShort();     // idh_len+22
          bin_len[i] = raf.readShort();     // idh_len+24
          data_type[i] = raf.readShort();     // idh_len+26
        }

        cur_len = cur_len + nparams * 76;
      }

      len = cur_len;

      if (end_rec) {

        // --- Read compression code=2 bytes from cur_len
        raf.seek(cur_len);
        a0 = raf.readShort();
        cur_len = cur_len + 2;

        // --- Check if the code=1 ("1" means an end of a ray)
        if (a0 == (short) 1) {
          if (cur_len % REC_SIZE == 0) {
            beg_rec = true;
            end_rec = true;
            rays_count++;
            read_ray_hdr = true;
            pos = 0;
            data_read = 0;
            nb = 0;
            len = cur_len;
          } else {
            end_rec = true;
            len = cur_len;
            rays_count++;
          }

          continue;
        }

        nwords = a0 & 0x7fff;
        end_words = nwords - 6;
        data_read = end_words * 2;
        end_rec = false;

        if (cur_len % REC_SIZE == 0) {
          len = cur_len;
          read_ray_hdr = true;
          beg_rec = true;

          continue;
        }
      }

      len = cur_len;

      // ---Define output data files for each data_type (= nparams)/sweep ---------
      dty = data_type[0];

      if (nparams > 1) {
        kk = rays_count % nparams;
        col = rays_count / nparams;
        dty = data_type[kk];
      } else if (number_sweeps > 1) {
        kk = nsweep - 1;
        col = rays_count % irays;
      }

      String var_name = data_name[dty];

      // --- read ray_header (size=12 bytes=6 words)---------------------------------------
      if (read_ray_hdr) {
        if (pos_ray_hdr < 2) {
          raf.seek(cur_len);
          beg_az = raf.readShort();
          cur_len = cur_len + 2;
          len = cur_len;

          if (cur_len % REC_SIZE == 0) {
            pos_ray_hdr = 2;
            beg_rec = true;
            read_ray_hdr = true;

            continue;
          }
        }
        if (pos_ray_hdr < 4) {
          raf.seek(cur_len);
          beg_elev = raf.readShort();
          cur_len = cur_len + 2;
          len = cur_len;

          if (cur_len % REC_SIZE == 0) {
            pos_ray_hdr = 4;
            beg_rec = true;
            read_ray_hdr = true;
            continue;
          }
        }
        if (pos_ray_hdr < 6) {
          raf.seek(cur_len);
          end_az = raf.readShort();
          cur_len = cur_len + 2;
          len = cur_len;

          if (cur_len % REC_SIZE == 0) {
            pos_ray_hdr = 6;
            beg_rec = true;
            read_ray_hdr = true;
            continue;
          }
        }
        if (pos_ray_hdr < 8) {
          raf.seek(cur_len);
          end_elev = raf.readShort();
          cur_len = cur_len + 2;
          len = cur_len;

          if (cur_len % REC_SIZE == 0) {
            pos_ray_hdr = 8;
            beg_rec = true;
            read_ray_hdr = true;

            continue;
          }
        }

        if (pos_ray_hdr < 10) {
          raf.seek(cur_len);
          num_bins = raf.readShort();
          cur_len = cur_len + 2;
          len = cur_len;

          if (num_bins % 2 != 0) {
            num_bins = (short) (num_bins + 1);
          }
          num_gates[nsweep - 1] = (int) num_bins;
          if (cur_len % REC_SIZE == 0) {
            pos_ray_hdr = 10;
            beg_rec = true;
            read_ray_hdr = true;

            continue;
          }
        }

        if (pos_ray_hdr < 12) {
          raf.seek(cur_len);
          time_start_sw = raf.readShort();
          cur_len = cur_len + 2;
          len = cur_len;
        }
      }

      // ---------- end of ray header ----------------------------------------------
      az = SigmetIOServiceProvider.calcAz(beg_az, end_az);
      elev = SigmetIOServiceProvider.calcElev(end_elev);
      step = SigmetIOServiceProvider.calcStep(range_first, range_last, num_bins);

      if (cur_len % REC_SIZE == 0) {
        len = cur_len;
        beg_rec = true;
        read_ray_hdr = false;

        continue;
      }

      if (pos > 0) {
        data_read = data_read - pos;
        pos = 0;
      }
      //  if(az > 358.5 && az < 358.8 && var_name.contains("Reflectivity")) {
      //      System.out.println(" here ");
      //  }
      if (data_read > 0) {
        raf.seek(cur_len);
        rayoffset = cur_len;
        datalen = data_read;

        for (int i = 0; i < data_read; i++) {
          //  data   = raf.readByte();
          //  dd[nb] = SigmetIOServiceProvider.calcData(recHdr, dty, data);
          cur_len++;
          nb++;

          if (cur_len % REC_SIZE == 0) {
            pos = i + 1;
            beg_rec = true;
            read_ray_hdr = false;
            len = cur_len;
            raf.seek(cur_len);
            break;
          }
        }
        raf.seek(cur_len);
        if (pos > 0) {
          continue;
        }
      }

      if (cur_len % REC_SIZE == 0) {
        pos = 0;
        beg_rec = true;
        read_ray_hdr = false;
        data_read = 0;
        len = cur_len;

        continue;
      }

      raf.seek(cur_len);
      rayoffset1 = cur_len;

      while (nb < (int) num_bins) {
        a00 = raf.readShort();
        cur_len = cur_len + 2;

        // --- Check if the code=1 ("1" means an end of a ray)
        if (a00 == (short) 1) {
          // for (int uk = 0; uk < (int) num_bins; uk++) {
          //  dd[uk] = -999.99f;
          //  }
          ray = new Ray(-999.99f, -999.99f, -999.99f, -999.99f, num_bins, (short) (-99), -999, 0, -999,
                  nsweep, var_name, dty);
          rays_count++;
          beg_rec = false;
          end_rec = true;

          break;
        }

        if (a00 < 0) {    // -- This is data
          nwords = a00 & 0x7fff;
          data_read = nwords * 2;

          if (cur_len % REC_SIZE == 0) {
            pos = 0;
            beg_rec = true;
            end_rec = false;
            len = cur_len;
            read_ray_hdr = false;

            break;
          }

          raf.seek(cur_len);

          for (int ii = 0; ii < data_read; ii++) {
            //   data    = raf.readByte();
            //    dd[nb]  = SigmetIOServiceProvider.calcData(recHdr, dty, data);
            cur_len = cur_len + 1;
            nb = nb + 1;

            if (cur_len % REC_SIZE == 0) {
              pos = ii + 1;
              beg_rec = true;
              end_rec = false;
              len = cur_len;
              read_ray_hdr = false;
              raf.seek(cur_len);
              break;
            }
          }
          raf.seek(cur_len);
          if (pos > 0) {
            break;
          }
        } else if (a00 > 0 & a00 != 1) {
          num_zero = a00 * 2;

          // for (int k = 0; k < num_zero; k++) {
          //   dd[nb + k] = SigmetIOServiceProvider.calcData(recHdr, dty, (byte) 0);
          // }

          nb = nb + num_zero;

          if (cur_len % REC_SIZE == 0) {
            beg_rec = true;
            end_rec = false;
            read_ray_hdr = false;
            pos = 0;
            data_read = 0;
            len = cur_len;

            break;
          }
        }
      }                     // ------ end of while for num_bins---------------------------------

      if (cur_len % REC_SIZE == 0) {
        len = cur_len;

        continue;
      }

      raf.seek(cur_len);

      if (nb == (int) num_bins) {
        a00 = raf.readShort();
        cur_len = cur_len + 2;
        end_rec = true;
        ray = new Ray(range_first, step, az, elev, num_bins, time_start_sw, rayoffset, datalen, rayoffset1,
                nsweep, var_name, dty);
        rays_count++;
        two++;
        if ((nsweep == number_sweeps) & (rays_count % beg == 0)) {
          if (var_name.trim().equalsIgnoreCase("TotalPower")) {
            totalPower.add(ray);
          } else if (var_name.trim().equalsIgnoreCase("Reflectivity")) {
            reflectivity.add(ray);
          } else if (var_name.trim().equalsIgnoreCase("Velocity")) {
            velocity.add(ray);
          } else if (var_name.trim().equalsIgnoreCase("Width")) {
            width.add(ray);
          } else if (var_name.trim().equalsIgnoreCase("DifferentialReflectivity")) {
            diffReflectivity.add(ray);
          } else {
            System.out.println(" Error: Unknown Radial Variable found!!");
          }
          break;
        }

        if (cur_len % REC_SIZE == 0) {
          beg_rec = true;
          end_rec = true;
          read_ray_hdr = true;
          pos = 0;
          data_read = 0;
          nb = 0;
          len = cur_len;
          if (var_name.trim().equalsIgnoreCase("TotalPower")) {
            totalPower.add(ray);
          } else if (var_name.trim().equalsIgnoreCase("Reflectivity")) {
            reflectivity.add(ray);
          } else if (var_name.trim().equalsIgnoreCase("Velocity")) {
            velocity.add(ray);
          } else if (var_name.trim().equalsIgnoreCase("Width")) {
            width.add(ray);
          } else if (var_name.trim().equalsIgnoreCase("DifferentialReflectivity")) {
            diffReflectivity.add(ray);
          } else {
            System.out.println(" Error: Unknown Radial Variable found!!");
          }
          continue;
        }
      }

      // "TotalPower", "Reflectivity", "Velocity", "Width", "DifferentialReflectivity"
      if (firstRay == null) firstRay = ray;

      if (var_name.trim().equalsIgnoreCase("TotalPower")) {
        totalPower.add(ray);
      } else if (var_name.trim().equalsIgnoreCase("Reflectivity")) {
        reflectivity.add(ray);
      } else if (var_name.trim().equalsIgnoreCase("Velocity")) {
        velocity.add(ray);
      } else if (var_name.trim().equalsIgnoreCase("Width")) {
        width.add(ray);
      } else if (var_name.trim().equalsIgnoreCase("DifferentialReflectivity")) {
        diffReflectivity.add(ray);
      } else {
        System.out.println(" Error: Unknown Radial Variable found!!");
      }

      pos = 0;
      data_read = 0;
      nb = 0;
      read_ray_hdr = true;
      pos_ray_hdr = 0;

      if ((nsweep <= number_sweeps) & (rays_count % beg == 0)) {
        beg_rec = true;
        end_rec = true;
        rays_count = 0;
        nb = 0;
        cur_len = REC_SIZE * (nrec + 1);
        len = cur_len;
        read_ray_hdr = true;
      }

      len = cur_len;
    }    // ------------end of outer while  ---------------
    lastRay = ray;

    if (reflectivity.size() > 0) {
      reflectivityGroups = sortScans("reflectivity", reflectivity, 1000);
      hasReflectivity = true;
    }
    if (velocity.size() > 0) {
      velocityGroups = sortScans("velocity", velocity, 1000);
      hasVelocity = true;
    }
    if (totalPower.size() > 0) {
      totalPowerGroups = sortScans("totalPower", totalPower, 1000);
      hasTotalPower = true;
    }
    if (width.size() > 0) {
      widthGroups = sortScans("width", width, 1000);
      hasWidth = true;
    }
    if (diffReflectivity.size() > 0) {
      differentialReflectivityGroups = sortScans("diffReflectivity", diffReflectivity, 1000);
      hasDifferentialReflectivity = true;
    }

    if (time.size() > 0) {
      timeGroups = sortScans("diffReflectivity", diffReflectivity, 1000);
      hasTime = true;
    }

    // --------- fill all of values in the ncfile ------
  }    // ----------- end of doData -----------------------

  private int max_radials = 0;
  private int min_radials = Integer.MAX_VALUE;
  private boolean debugRadials = false;


  private List> sortScans(String name, List scans, int siz) {

    // now group by elevation_num
    Map> groupHash = new HashMap>(siz);

    for (Ray ray : scans) {
      List group = groupHash.get((short) ray.nsweep);

      if (null == group) {
        group = new ArrayList();
        groupHash.put((short) ray.nsweep, group);
      }

      group.add(ray);
    }

    for (Short aShort : groupHash.keySet()) {
      List group = groupHash.get(aShort);
      Ray[] rr = new Ray[group.size()];
      group.toArray(rr);
      checkSort(rr);
    }

    // sort the groups by elevation_num
    List> groups = new ArrayList>(groupHash.values());
    Collections.sort(groups, new GroupComparator());

    // use the maximum radials
    for (List group : groups) {
      max_radials = Math.max(max_radials, group.size());
      min_radials = Math.min(min_radials, group.size());
    }

    if (debugRadials) {
      System.out.println(name + " min_radials= " + min_radials + " max_radials= " + max_radials);

      for (List group : groups) {
        Ray lastr = group.get(0);

        for (int j = 1; j < group.size(); j++) {
          Ray r = group.get(j);
          if (r.getTime() < lastr.getTime()) {
            System.out.println(" out of order " + j);
          }
          lastr = r;
        }
      }
    }


    return groups;
  }

  private class GroupComparator implements Comparator> {
    public int compare(List group1, List group2) {
      Ray record1 = group1.get(0);
      Ray record2 = group2.get(0);

      // if (record1.elevation_num != record2.elevation_num)
      return record1.nsweep - record2.nsweep;

      // return record1.cut - record2.cut;
    }
  }

  public List> getTotalPowerGroups() {
    return totalPowerGroups;
  }

  public List> getVelocityGroups() {
    return velocityGroups;
  }

  public List> getWidthGroups() {
    return widthGroups;
  }

  public List> getReflectivityGroups() {
    return reflectivityGroups;
  }

  public List> getDifferentialReflectivityGroups() {
    return differentialReflectivityGroups;
  }

  public int[] getNumberGates() {
    return num_gates;
  }

  public int[] getStartSweep() {
    return base_time;
  }

  /**
   * Sort Ray objects in the same sweep according to the ascended azimuth (from 0 to 360)
   * and time.
   *
   * @param r the array of Ray objects in a sweep. Its length=number_rays
   */
  void checkSort(Ray[] r) {
    int j = 0, n = 0, n1 = 0, n2 = 0;
    short time1 = 0, time2 = 0;
    int[] k1 = new int[300];
    int[] k2 = new int[300];
    //      define the groups of rays with the same "time". For ex.:
    //      group1 - ray[0]={time=1,az=344}, ray[1]={time=1,az=345}, ... ray[11]={time=1,az=359}
    //      group2 - ray[12]={time=1,az=0}, ray[13]={time=1,az=1}, ... ray[15]={time=1,az=5}
    //      k1- array of begin indx (0,12), k2- array of end indx (11,15)
    for (int i = 0; i < r.length - 1; i++) {
      time1 = r[i].getTime();
      time2 = r[i + 1].getTime();
      if (time1 != time2) {
        k2[j] = i;
        j = j + 1;
        k1[j] = i + 1;
      }
    }
    if (k2[j] < r.length - 1) {
      k1[j] = k2[j - 1] + 1;
      k2[j] = r.length - 1;
      n = j + 1;
    }

    //      if different groups have the same value of "time" (may be 2 and more groups) -
    //      it1= indx of "k1" of 1st group, it2= indx of "k2" of last group
    int it1 = 0, it2 = 0;
    for (int ii = 0; ii < j + 1; ii++) {
      n1 = k1[ii];
      for (int i = 0; i < j + 1; i++) {
        if (i != ii) {
          n2 = k1[i];
          if (r[n1].getTime() == r[n2].getTime()) {
            it1 = ii;
            it2 = i;
          }
        }
      }
    }

    n1 = k1[it1];
    n2 = k1[it2];
    int s1 = k2[it1] - k1[it1] + 1;
    int s2 = k2[it2] - k1[it2] + 1;
    float[] t0 = new float[s1];
    float[] t00 = new float[s2];
    for (int i = 0; i < s1; i++) {
      t0[i] = r[n1 + i].getAz();
    }
    for (int i = 0; i < s2; i++) {
      t00[i] = r[n2 + i].getAz();
    }
    float mx0 = t0[0];
    for (int i = 0; i < s1; i++) {
      if (mx0 < t0[i]) mx0 = t0[i];
    }
    float mx00 = t00[0];
    for (int i = 0; i < s2; i++) {
      if (mx00 < t00[i]) mx00 = t00[i];
    }
    if ((mx0 > 330.0f & mx00 < 50.0f)) {
      for (int i = 0; i < s1; i++) {
        float q = r[n1 + i].getAz();
        r[n1 + i].setAz(q - 360.0f);
      }
    }
    Arrays.sort(r, new RayComparator());
    for (int i = 0; i < r.length; i++) {
      float a = r[i].getAz();
      if (a < 0 & a > -361.0f) {
        float qa = r[i].getAz();
        r[i].setAz(qa + 360.0f);
      }
    }

  }

  class RayComparator implements Comparator {
    public int compare(Ray ray1, Ray ray2) {
      if (ray1.getTime() < ray2.getTime()) {
        return -1;
      } else if (ray1.getTime() == ray2.getTime()) {
        if (ray1.getAz() < ray2.getAz()) {
          return -1;
        }
        if (ray1.getAz() > ray2.getAz()) {
          return 1;
        }
        if (ray1.getAz() == ray2.getAz()) {
          return 0;
        }
      } else if (ray1.getTime() > ray2.getTime()) {
        return 1;
      }
      return 0;
    }
  } // class RayComparator end ----------------------------------


}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy