cdm/src/main/java/ucar/nc2/iosp/nids/Nidsheader.java
void read(ucar.unidata.io.RandomAccessFile raf, ucar.nc2.NetcdfFile ncfile ) throws IOException {

        int      hedsiz;                  /* NEXRAD header size            */
        int      rc;                      /* function return status        */
        int      hoff = 0;
        int      type;
        int      zlibed;
        boolean  isZ = false;
        int      encrypt;
        long     actualSize ;
        int      readLen ;
        readWMO( raf );
        this.ncfile = ncfile;
        actualSize = raf.length();
        int pos = 0;
        raf.seek(pos);

        // Read in the whole contents of the NEXRAD Level III product since
        // some product require to go through the whole file to build the  struct of file.

        readLen = (int)actualSize;

        byte[] b = new byte[readLen];
        rc = raf.read(b);
        if ( rc != readLen )
        {
            log.warn(" error reading nids product header "+raf.getLocation());
        }

        if( !noHeader ) {
        //Get product message header into a string for processing
            String pib = new String(b, 0, 100, CDM.utf8Charset);
            type = 0;
            pos = pib.indexOf ( "\r\r\n" );
            while ( pos != -1 ) {
                hoff =  pos + 3;
                type++;
                pos = pib.indexOf ( "\r\r\n" , pos+1);
            }
            raf.seek(hoff);

            // Test the next two bytes to see if the image portion looks like
            // it is zlib-compressed.
            byte[] b2 = new byte[2];
            // byte[] b4 = new byte[4];
            System.arraycopy(b, hoff, b2, 0, 2);

            zlibed = isZlibHed( b2 );
            if ( zlibed == 0){
                encrypt = IsEncrypt( b2 );
                if(encrypt == 1){
                    log.error( "error reading encryted product "+raf.getLocation());
                    throw new IOException("unable to handle the product with encrypt code " + encrypt);
                }
            }
           // process product description for station ID
            byte[] b3 = new byte[3];

            switch ( type ) {
              case 0:
                log.warn( "ReadNexrInfo:: Unable to seek to ID "+raf.getLocation());
                break;
              case 1:
              case 2:
              case 3:
              case 4:
                System.arraycopy(b, hoff - 6, b3, 0, 3);
                stationId  = new String(b3, CDM.utf8Charset);
                try {
                  NexradStationDB.init(); // make sure database is initialized
                  NexradStationDB.Station station = NexradStationDB.get("K"+stationId);
                  if (station != null) {
                    stationName = station.name;
                  }
                } catch (IOException ioe) {
                  log.error("NexradStationDB.init "+raf.getLocation(), ioe);
                }
                break;

              default:
                break;
            }

        if ( zlibed == 1 ) {
              isZ = true;
              uncompdata = GetZlibedNexr( b, readLen,  hoff );
              //uncompdata = Nidsiosp.readCompData(hoff, 160) ;
              if ( uncompdata == null ) {
                log.warn( "ReadNexrInfo: error uncompressing image " +raf.getLocation());
                uncompdata = new byte[b.length - hoff];
                System.arraycopy(b, hoff, uncompdata, 0, b.length - hoff);
              }
        }
        else {
             uncompdata = new byte[b.length-hoff];
             System.arraycopy(b, hoff, uncompdata, 0, b.length- hoff);
        }
    } else {
        uncompdata = new byte[b.length];
        System.arraycopy(b, 0, uncompdata, 0, b.length);
        // stationId  = "YYY";
    }
    byte[] b2 = new byte[2];
    ByteBuffer bos = ByteBuffer.wrap(uncompdata);
    rc = read_msghead( bos, 0 );
    hedsiz = 18;
    Pinfo pinfo = read_proddesc( bos, hedsiz );

    hedsiz += 102;



    // Set product-dependent information
    int prod_type = code_typelookup(pinfo.pcode);
    setProductInfo(prod_type, pinfo );

    //int windb = 0;
    int pcode1Number = 0;
    int pcode2Number = 0;
    int pcode8Number = 0;
    int pcode4Number = 0;
    int pcode5Number = 0;
    int pcode10Number = 0;
    int pcode6Number = 0;
    int pcode25Number = 0;
    int pcode12Number = 0;
    int pcode13Number = 0;
    int pcode14Number = 0;
    int pcode15Number = 0;
    int pcode16Number = 0;
    int pcode19Number = 0;
    int pcode20Number = 0;
    int pkcode1Doff[] = null;
    int pkcode2Doff[] = null;
    int pkcode8Doff[] = null;
    int pkcode1Size[] = null;
    int pkcode2Size[] = null;
    int pkcode8Size[] = null;
    int pkcode4Doff[] = null;
    int pkcode5Doff[] = null;
    int pkcode10Doff[] = null;
    int pkcode10Dlen[] = null;
    int pkcode6Doff[] = null;
    int pkcode6Dlen[] = null;
    int pkcode25Doff[] = null;
    int pkcode12Doff[] = null;
    int pkcode13Doff[] = null;
    int pkcode14Doff[] = null;
    int pkcode12Dlen[] = null;
    int pkcode13Dlen[] = null;
    int pkcode14Dlen[] = null;
    int pkcode15Dlen[] = null;
    int pkcode15Doff[] = null;
    int pkcode16Dlen[] = null;
    int pkcode16Doff[] = null;
    int pkcode19Dlen[] = null;
    int pkcode19Doff[] = null;
    int pkcode20Dlen[] = null;
    int pkcode20Doff[] = null;
    // Get product symbology header (needed to get image shape)
    ifloop: if ( pinfo.offsetToSymbologyBlock != 0 ) {

      // Symbology header
      if(pinfo.p8 == 1) {
          // TDWR data and the symbology is compressed
          int size = shortsToInt(pinfo.p9,  pinfo.p10, false);
          uncompdata = uncompressed(bos, hedsiz, size);
          bos = ByteBuffer.wrap(uncompdata);
      }

      Sinfo sinfo = read_dividlen( bos, hedsiz );
      if( rc == 0 || pinfo.divider != -1 )
      {
          log.warn( "error in product symbology header "+raf.getLocation());
      }

      if(sinfo.id != 1)
      {
          if(pinfo.pcode == 82) {
              read_SATab( bos, hedsiz );
          }
          break ifloop;

      }
      hedsiz += 10;

      // Symbology layer
      int klayer = pinfo.offsetToSymbologyBlock*2 + 10;
      for(int i=0; i<sinfo.nlayers ; i++ ){
          hedsiz = klayer;
          bos.position(hedsiz);
          short Divlen_divider = bos.getShort();
          hedsiz += 2;
          int Divlen_length = bos.getInt();
          hedsiz += 4;

          if ( Divlen_divider != -1 ) {
            log.warn( "error reading length divider "+raf.getLocation());
          }

          int icount = 0;
          int plen;

          while (icount < Divlen_length ) {
              int boff = klayer + icount + 6;
              bos.position(boff);
              bos.get(b2);
              int pkcode = getUInt(b2, 2);
              hedsiz += 2;
              boff += 2;
              switch(pkcode)
              {
                 case 18:  //  DPA
                 case 17: //   (pkcode == 0x11)   Digital Precipitation Array
                      hedsiz += 8;
                      plen = pcode_DPA( bos, boff, hoff, hedsiz, isZ, i, pkcode);
                      break;
                 case 10:    //     (pkcode == 0xA)
                      if(pkcode10Doff == null)  {
                          pkcode10Doff = new int[250];
                          pkcode10Dlen = new int[250];
                      }
                      plen =  bos.getShort();   // for unlinked Vector Packet the length of data block
                      pkcode10Doff[pcode10Number] = boff + 2;
                      pkcode10Dlen[pcode10Number] = ( plen - 2 ) / 8;
                      pcode10Number++;
                      //pcode_10n7( bos, boff, hoff, isZ, pkcode );
                      break;
                 case 1:
                      if(pkcode1Doff == null) {
                          pkcode1Doff = new int[250];
                          pkcode1Size = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode1Doff[pcode1Number] = boff + 2;
                      pkcode1Size[pcode1Number] = plen - 4;
                      pcode1Number++;
                      break;
                 case 2:
                      if(pkcode2Doff == null) {
                          pkcode2Doff = new int[250];
                          pkcode2Size = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode2Doff[pcode2Number] = boff + 2;
                      pkcode2Size[pcode2Number] = plen - 4;
                      pcode2Number++;
                      break;
                 case 8:       //text string
                      if(pkcode8Doff == null) {
                          pkcode8Doff = new int[550];
                          pkcode8Size = new int[550];
                      }
                      plen = bos.getShort();
                      pkcode8Doff[pcode8Number] = boff + 2;
                      pkcode8Size[pcode8Number] = plen - 6;
                      pcode8Number++;
                      break;
                 case 3:
                 case 11:
                 case 25:
                      if(pkcode25Doff == null) {
                          pkcode25Doff = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode25Doff[pcode25Number] = boff + 2;
                      pcode25Number++;
                      break;
                 case 12:
                      if(pkcode12Doff == null) {
                          pkcode12Doff = new int[250];
                          pkcode12Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode12Doff[pcode12Number] = boff + 2;
                      pkcode12Dlen[pcode12Number] = plen/4;
                      pcode12Number++;
                      break;
                 case 13:
                      if(pkcode13Doff == null) {
                          pkcode13Doff = new int[250];
                          pkcode13Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode13Doff[pcode13Number] = boff + 2;
                      pkcode13Dlen[pcode13Number] = plen/4;
                      pcode13Number++;
                      break;
                 case 14:
                      if(pkcode14Doff == null) {
                          pkcode14Doff = new int[250];
                          pkcode14Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode14Doff[pcode14Number] = boff + 2;
                      pkcode14Dlen[pcode14Number] = plen/4;
                      pcode14Number++;
                      break;
                 case 15:
                      if(pkcode15Doff == null) {
                          pkcode15Doff = new int[250];
                          pkcode15Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode15Doff[pcode15Number] = boff + 2;
                      pkcode15Dlen[pcode15Number] = plen/6;
                      pcode15Number++;
                      break;
                 case 166:
                      if(pkcode16Doff == null) {
                          pkcode16Doff = new int[250];
                          pkcode16Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode16Doff[pcode16Number] = boff + 2;
                      pkcode16Dlen[pcode16Number] = plen/4;
                      pcode16Number++;
                      break;
                  case 19:
                      if(pkcode19Doff == null) {
                          pkcode19Doff = new int[250];
                          pkcode19Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode19Doff[pcode19Number] = boff + 2;
                      pkcode19Dlen[pcode19Number] = plen/10;
                      pcode19Number++;
                      break;
                  case 20:
                      if(pkcode20Doff == null) {
                          pkcode20Doff = new int[250];
                          pkcode20Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode20Doff[pcode20Number] = boff + 2;
                      pkcode20Dlen[pcode20Number] = plen/8;
                      pcode20Number++;
                      break;
                 case 4:    // wind barb
                      if(pkcode4Doff == null) {
                          pkcode4Doff = new int[1000];
                      }
                      plen = bos.getShort();
                      pkcode4Doff[pcode4Number] = boff + 2;
                      pcode4Number++;
                      break;
                 case 5:  //   Vector Arrow Data
                      if(pkcode5Doff == null) {
                          pkcode5Doff = new int[1000];
                      }
                      plen = bos.getShort();
                      pkcode5Doff[pcode5Number] = boff + 2;
                      pcode5Number++;
                      break;
                 case 43:
                      plen = bos.getShort();
                      break;
                 case 23:
                 case 24:
                      plen = bos.getShort();
                      int poff = 2;
                      while (poff < plen){
                          int pcode = bos.getShort();
                          int len = bos.getShort();
                          switch (pcode)
                          {
                             case 2:
                                 if(pkcode2Doff == null) {
                                     pkcode2Doff = new int[250];
                                     pkcode2Size = new int[250];
                                 }
                                 pkcode2Doff[pcode2Number] = boff + poff + 4;
                                 pkcode2Size[pcode2Number] = len - 4;
                                 pcode2Number++;
                                 break;
                             case 6:
                                 if(pkcode6Doff == null) {
                                     pkcode6Doff = new int[250];
                                     pkcode6Dlen = new int[250];
                                 }
                                 pkcode6Doff[pcode6Number] = boff + poff + 4;
                                 pkcode6Dlen[pcode6Number] = (len - 6)/4;
                                 pcode6Number++;
                                 break;
                             case 25:
                                 if(pkcode25Doff == null) {
                                     pkcode25Doff = new int[250];
                                 }
                                 pkcode25Doff[pcode25Number] = boff + poff + 4;
                                 pcode25Number++;
                                 break;
                             default:
                                log.error( "error reading pcode= " + pcode+" "+raf.getLocation());
                                throw new IOException("error reading pcode, " +
                                        "unable to handle the packet with code "
                                        + pcode);
                          }
                          poff = poff + len + 4;
                          // Need to advance the file's position
                          bos.position(bos.position() + len);
                      }
                      break;
                  case 0x0802:
                      log.warn("Encountered unhandled packet code 0x0802 (contour color) -- reading past.");
                      Divlen_divider = bos.getShort(); // Color marker
                      if (Divlen_divider != 0x0002) {
                          log.warn("Missing color marker!");
                      }
                      plen = 2;
                      break;
                  case 0x0E03:
                      log.warn("Encountered unhandled packet code 0x0E03 (linked contours) -- reading past.");
                      Divlen_divider = bos.getShort(); // Start marker
                      if (Divlen_divider != 0x8000) {
                          log.warn("Missing start marker!");
                      }
                      // Read past start x, y for now
                      bos.getShort();
                      bos.getShort();
                      plen = 6 + bos.getShort();
                      break;

                 default:
                      if ( pkcode == 0xAF1F  || pkcode == 16) {              /* radial image                  */
                          hedsiz += pcode_radial( bos, hoff, hedsiz, isZ, uncompdata, pinfo.threshold) ;
                          //myInfo = new Vinfo (cname, numX, numX0, numY, numY0, hoff, hedsiz, isR, isZ);
                          plen = Divlen_length;
                          break;
                      }
                      else if ( pkcode == 28) {              /* radial image                  */
                          hedsiz += pcode_generic( bos, hoff, hedsiz, isZ, uncompdata, pinfo.threshold) ;
                          //myInfo = new Vinfo (cname, numX, numX0, numY, numY0, hoff, hedsiz, isR, isZ);
                          plen = Divlen_length;
                          break;
                      }
                      else if (pkcode == 0xBA0F ||pkcode == 0xBA07 )
                      {      /* raster image                  */
                          hedsiz += pcode_raster( bos, (short)pkcode, hoff, hedsiz, isZ, uncompdata);
                          //myInfo = new Vinfo (cname, numX, numX0, numY, numY0, hoff, hedsiz, isR, isZ);
                          plen = Divlen_length;
                          break;
                      }
                      else
                      {
                          log.error( "error reading pkcode equals " + pkcode+" "+raf.getLocation());
                          throw new IOException("error reading pkcode, unable to handle the product with code " + pkcode);
                      }

                  // size and beginning data position in file

              } //end of switch
              icount = icount + plen + 4;
          }

          klayer = klayer + Divlen_length + 6;
     }

      //int curDoff = hedsiz;

      if(pkcode8Doff != null){
          pcode_128( pkcode8Doff, pkcode8Size, 8, hoff, pcode8Number, "textStruct_code8", "",isZ);
      }
      if (pkcode1Doff != null){
          pcode_128( pkcode1Doff, pkcode1Size, 1, hoff, pcode1Number, "textStruct_code1", "", isZ);
      }
      if (pkcode2Doff != null){
          pcode_128( pkcode2Doff, pkcode2Size, 2, hoff, pcode2Number, "textStruct_code2", "", isZ);
      }
      if (pkcode10Doff != null){
          pcode_10n9( pkcode10Doff, pkcode10Dlen, hoff, pcode10Number, isZ);
      }
      if (pkcode4Doff != null){
          pcode_4( pkcode4Doff, hoff, pcode4Number, isZ);
      }
      if (pkcode5Doff != null){
          pcode_5( pkcode5Doff, hoff, pcode5Number, isZ);
      }
      if (pkcode6Doff != null){
          pcode_6n7( pkcode6Doff, pkcode6Dlen, hoff, pcode6Number, isZ, "linkedVector", 6);
      }
      if (pkcode25Doff != null){
          pcode_25( pkcode25Doff, hoff, pcode25Number, isZ);
      }
      if (pkcode12Doff != null){
          pcode_12n13n14( pkcode12Doff, pkcode12Dlen, hoff, pcode12Number, isZ, "TVS", 12);
      }
      if (pkcode13Doff != null){
          pcode_12n13n14( pkcode13Doff, pkcode13Dlen, hoff, pcode13Number, isZ, "hailPositive", 13);
      }
      if (pkcode14Doff != null){
          pcode_12n13n14( pkcode14Doff, pkcode14Dlen, hoff, pcode14Number, isZ, "hailProbable", 14);
      }
      if (pkcode19Doff != null){
          pcode_12n13n14( pkcode19Doff, pkcode19Dlen, hoff, pcode19Number, isZ, "hailIndex", 19);
      }
      if (pkcode20Doff != null){
          pcode_12n13n14( pkcode20Doff, pkcode20Dlen, hoff, pcode20Number, isZ, "mesocyclone", 20);
      }
    } else {
      log.debug ( "GetNexrDirs:: no product symbology block found (no image data) " +raf.getLocation());

    }

    if ( pinfo.offsetToTabularBlock != 0 ) {
         int tlayer = pinfo.offsetToTabularBlock*2;
         bos.position(tlayer);
         if( bos.hasRemaining()) {

             short tab_divider = bos.getShort();
             if ( tab_divider != -1) {
                 log.error ( "Block divider not found "+raf.getLocation());
                 throw new IOException("error reading graphic alphanumeric block" );
             }
             short tab_bid = bos.getShort();
             int tblen = bos.getInt();

             bos.position(tlayer+116);
             int inc = bos.getInt();
             bos.position(tlayer+128); // skip the second header and prod description

             tab_divider = bos.getShort();
             if ( tab_divider != -1) {
                 log.error ( "tab divider not found "+raf.getLocation());
                 throw new IOException("error reading graphic alphanumeric block" );
             }
             int npage = bos.getShort();

             int ppos =  bos.position();

             ArrayList dims =  new ArrayList();
             Dimension tbDim = new Dimension("pageNumber", npage);
             ncfile.addDimension( null, tbDim);
             dims.add( tbDim);
             Variable ppage = new Variable(ncfile, null, null, "TabMessagePage");
             ppage.setDimensions(dims);
             ppage.setDataType(DataType.STRING);
             ppage.addAttribute( new Attribute(CDM.LONG_NAME, "Graphic Product Message"));
             ncfile.addVariable(null, ppage);
             ppage.setSPobject( new Vinfo (npage, 0, tblen, 0, hoff, ppos, isR, isZ, null, null, tab_bid, 0));
         }

     }

     if ( pinfo.offsetToGraphicBlock != 0 ) {
         int gpkcode1Doff[] = null;
         int gpkcode2Doff[] = null;
         int gpkcode10Doff[] = null;
         int gpkcode10Dlen[] = null;
         int gpkcode8Doff[] = null;
         int gpkcode1Size[] = null;
         int gpkcode2Size[] = null;
         int gpkcode8Size[] = null;
         int gpcode1Number = 0;
         int gpcode10Number = 0;
         int gpcode8Number = 0;
         int gpcode2Number = 0;
         int tlayer = pinfo.offsetToGraphicBlock*2;
         bos.position(tlayer);
         short graphic_divider = bos.getShort();
         short graphic_bid = bos.getShort();
         if(graphic_divider!=-1 || graphic_bid != 2) {
               log.error( "error reading graphic alphanumeric block "+raf.getLocation());
               throw new IOException("error reading graphic alphanumeric block" );
         }
         int blen = bos.getInt();
         int clen = 0;
         int npage = bos.getShort();
         int lpage ;
         int ipage = 0;
         int plen ;

         while ( (clen < blen) && (ipage < npage) ) {
          //  bos.position(ppos);
            int ppos = bos.position();
            ipage =  bos.getShort();
            lpage =  bos.getShort();
            int icnt = 0;
            ppos = ppos + 4;
            while (icnt < lpage)
            {
                bos.position(ppos+icnt);
                int pkcode = bos.getShort();
                if(pkcode == 8 ) {
                   if(gpkcode8Doff == null) {
                          gpkcode8Doff = new int[550];
                          gpkcode8Size = new int[550];
                   }
                   plen = bos.getShort();
                   gpkcode8Doff[gpcode8Number] = ppos + 4 + icnt;
                   gpkcode8Size[gpcode8Number] = plen - 6;
                   icnt += plen + 4;
                   gpcode8Number++;
                }
                else if ( pkcode == 1 ) {
                   if(gpkcode1Doff == null) {
                          gpkcode1Doff = new int[550];
                          gpkcode1Size = new int[550];
                   }
                   plen = bos.getShort();
                   gpkcode1Doff[gpcode1Number] = ppos + 4 + icnt;
                   gpkcode1Size[gpcode1Number] = plen - 4;
                   icnt += plen + 4;
                   gpcode1Number++;
                }
                else if ( pkcode == 10 ) {
                   if(gpkcode10Doff == null)  {
                          gpkcode10Doff = new int[250];
                          gpkcode10Dlen = new int[250];
                   }
                   plen =  bos.getShort();   // for unlinked Vector Packet the length of data block

                   gpkcode10Doff[gpcode10Number] = ppos + 4+ icnt;
                   gpkcode10Dlen[gpcode10Number] = ( plen - 2 ) / 8;
                   icnt += plen + 4;
                   gpcode10Number++;
                }  else {
                   plen = bos.getShort();
                   icnt += plen + 4;
                }

              //  else {
              //      out.println( "error reading pkcode equals " + pkcode);
              //      throw new IOException("error reading pkcode in graphic alpha num block " + pkcode);
              //  }

            }
            ppos = ppos + lpage + 4;
            clen = clen + lpage + 4;
         }

         if(gpkcode8Doff != null){
             pcode_128( gpkcode8Doff, gpkcode8Size, 8, hoff, gpcode8Number, "textStruct_code8g", "g", isZ);
         }
         if(gpkcode2Doff != null){
             pcode_128( gpkcode2Doff, gpkcode2Size, 2, hoff, gpcode8Number, "textStruct_code2g", "g", isZ);
         }
         if(gpkcode1Doff != null){
             pcode_128( gpkcode1Doff, gpkcode1Size, 1, hoff, gpcode1Number, "textStruct_code1g", "g", isZ);
         }
         if (gpkcode10Doff != null){
             pcode_10n9( gpkcode10Doff, gpkcode10Dlen, hoff, gpcode10Number, isZ);
         }
         /*
         int ppos = bos.position();
         ArrayList dims =  new ArrayList();
         Dimension tbDim = new Dimension("pageNumber", npage, true);
         ncfile.addDimension( null, tbDim);
         dims.add( tbDim);
         Variable ppage = new Variable(ncfile, null, null, "GraphicMessagePage");
         ppage.setDimensions(dims);
         ppage.setDataType(DataType.STRING);
         ppage.addAttribute( new Attribute(CDM.LONG_NAME, "Graphic Product Message"));
         ncfile.addVariable(null, ppage);
         ppage.setSPobject( new Vinfo (npage, 0, tblen, 0, hoff, ppos, isR, isZ, null, null, graphic_bid));
           */
     }
    // finish
    ncfile.finish();
    }
void read(ucar.unidata.io.RandomAccessFile raf, ucar.nc2.NetcdfFile ncfile ) throws IOException {

        int      hedsiz;                  /* NEXRAD header size            */
        int      rc;                      /* function return status        */
        int      hoff = 0;
        int      type;
        int      zlibed;
        boolean  isZ = false;
        int      encrypt;
        long     actualSize ;
        int      readLen ;
        readWMO( raf );
        this.ncfile = ncfile;
        actualSize = raf.length();
        int pos = 0;
        raf.seek(pos);

        // Read in the whole contents of the NEXRAD Level III product since
        // some product require to go through the whole file to build the  struct of file.

        readLen = (int)actualSize;

        byte[] b = new byte[readLen];
        rc = raf.read(b);
        if ( rc != readLen )
        {
            log.warn(" error reading nids product header "+raf.getLocation());
        }

        if( !noHeader ) {
        //Get product message header into a string for processing
            String pib = new String(b, 0, 100, CDM.utf8Charset);
            type = 0;
            pos = pib.indexOf ( "\r\r\n" );
            while ( pos != -1 ) {
                hoff =  pos + 3;
                type++;
                pos = pib.indexOf ( "\r\r\n" , pos+1);
            }
            raf.seek(hoff);

            // Test the next two bytes to see if the image portion looks like
            // it is zlib-compressed.
            byte[] b2 = new byte[2];
            // byte[] b4 = new byte[4];
            System.arraycopy(b, hoff, b2, 0, 2);

            zlibed = isZlibHed( b2 );
            if ( zlibed == 0){
                encrypt = IsEncrypt( b2 );
                if(encrypt == 1){
                    log.error( "error reading encryted product "+raf.getLocation());
                    throw new IOException("unable to handle the product with encrypt code " + encrypt);
                }
            }
           // process product description for station ID
            byte[] b3 = new byte[3];

            switch ( type ) {
              case 0:
                log.warn( "ReadNexrInfo:: Unable to seek to ID "+raf.getLocation());
                break;
              case 1:
              case 2:
              case 3:
              case 4:
                System.arraycopy(b, hoff - 6, b3, 0, 3);
                stationId  = new String(b3, CDM.utf8Charset);
                try {
                  NexradStationDB.init(); // make sure database is initialized
                  NexradStationDB.Station station = NexradStationDB.get("K"+stationId);
                  if (station != null) {
                    stationName = station.name;
                  }
                } catch (IOException ioe) {
                  log.error("NexradStationDB.init "+raf.getLocation(), ioe);
                }
                break;

              default:
                break;
            }

        if ( zlibed == 1 ) {
              isZ = true;
              uncompdata = GetZlibedNexr( b, readLen,  hoff );
              //uncompdata = Nidsiosp.readCompData(hoff, 160) ;
              if ( uncompdata == null ) {
                log.warn( "ReadNexrInfo: error uncompressing image " +raf.getLocation());
                uncompdata = new byte[b.length - hoff];
                System.arraycopy(b, hoff, uncompdata, 0, b.length - hoff);
              }
        }
        else {
             uncompdata = new byte[b.length-hoff];
             System.arraycopy(b, hoff, uncompdata, 0, b.length- hoff);
        }
    } else {
        uncompdata = new byte[b.length];
        System.arraycopy(b, 0, uncompdata, 0, b.length);
        // stationId  = "YYY";
    }
    byte[] b2 = new byte[2];
    ByteBuffer bos = ByteBuffer.wrap(uncompdata);
    rc = read_msghead( bos, 0 );
    hedsiz = 18;
    Pinfo pinfo = read_proddesc( bos, hedsiz );

    hedsiz += 102;



    // Set product-dependent information
    int prod_type = code_typelookup(pinfo.pcode);
    setProductInfo(prod_type, pinfo );

    //int windb = 0;
    int pcode1Number = 0;
    int pcode2Number = 0;
    int pcode8Number = 0;
    int pcode4Number = 0;
    int pcode5Number = 0;
    int pcode10Number = 0;
    int pcode6Number = 0;
    int pcode25Number = 0;
    int pcode12Number = 0;
    int pcode13Number = 0;
    int pcode14Number = 0;
    int pcode15Number = 0;
    int pcode16Number = 0;
    int pcode19Number = 0;
    int pcode20Number = 0;
    int pkcode1Doff[] = null;
    int pkcode2Doff[] = null;
    int pkcode8Doff[] = null;
    int pkcode1Size[] = null;
    int pkcode2Size[] = null;
    int pkcode8Size[] = null;
    int pkcode4Doff[] = null;
    int pkcode5Doff[] = null;
    int pkcode10Doff[] = null;
    int pkcode10Dlen[] = null;
    int pkcode6Doff[] = null;
    int pkcode6Dlen[] = null;
    int pkcode25Doff[] = null;
    int pkcode12Doff[] = null;
    int pkcode13Doff[] = null;
    int pkcode14Doff[] = null;
    int pkcode12Dlen[] = null;
    int pkcode13Dlen[] = null;
    int pkcode14Dlen[] = null;
    int pkcode15Dlen[] = null;
    int pkcode15Doff[] = null;
    int pkcode16Dlen[] = null;
    int pkcode16Doff[] = null;
    int pkcode19Dlen[] = null;
    int pkcode19Doff[] = null;
    int pkcode20Dlen[] = null;
    int pkcode20Doff[] = null;
    // Get product symbology header (needed to get image shape)
    ifloop: if ( pinfo.offsetToSymbologyBlock != 0 ) {

      // Symbology header
      if(pinfo.p8 == 1) {
          // TDWR data and the symbology is compressed
          int size = shortsToInt(pinfo.p9,  pinfo.p10, false);
          uncompdata = uncompressed(bos, hedsiz, size);
          bos = ByteBuffer.wrap(uncompdata);
      }

      Sinfo sinfo = read_dividlen( bos, hedsiz );
      if( rc == 0 || pinfo.divider != -1 )
      {
          log.warn( "error in product symbology header "+raf.getLocation());
      }

      if(sinfo.id != 1)
      {
          if(pinfo.pcode == 82) {
              read_SATab( bos, hedsiz );
          }
          break ifloop;

      }
      hedsiz += 10;

      // Symbology layer
      int klayer = pinfo.offsetToSymbologyBlock*2 + 10;
      for(int i=0; i<sinfo.nlayers ; i++ ){
          hedsiz = klayer;
          bos.position(hedsiz);
          short Divlen_divider = bos.getShort();
          hedsiz += 2;
          int Divlen_length = bos.getInt();
          hedsiz += 4;

          if ( Divlen_divider != -1 ) {
            log.warn( "error reading length divider "+raf.getLocation());
          }

          int icount = 0;
          int plen;

          while (icount < Divlen_length ) {
              int boff = klayer + icount + 6;
              bos.position(boff);
              bos.get(b2);
              int pkcode = getUInt(b2, 2);
              hedsiz += 2;
              boff += 2;
              switch(pkcode)
              {
                 case 18:  //  DPA
                 case 17: //   (pkcode == 0x11)   Digital Precipitation Array
                      hedsiz += 8;
                      plen = pcode_DPA( bos, boff, hoff, hedsiz, isZ, i, pkcode);
                      break;
                 case 10:    //     (pkcode == 0xA)
                      if(pkcode10Doff == null)  {
                          pkcode10Doff = new int[250];
                          pkcode10Dlen = new int[250];
                      }
                      plen =  bos.getShort();   // for unlinked Vector Packet the length of data block
                      pkcode10Doff[pcode10Number] = boff + 2;
                      pkcode10Dlen[pcode10Number] = ( plen - 2 ) / 8;
                      pcode10Number++;
                      //pcode_10n7( bos, boff, hoff, isZ, pkcode );
                      break;
                 case 1:
                      if(pkcode1Doff == null) {
                          pkcode1Doff = new int[250];
                          pkcode1Size = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode1Doff[pcode1Number] = boff + 2;
                      pkcode1Size[pcode1Number] = plen - 4;
                      pcode1Number++;
                      break;
                 case 2:
                      if(pkcode2Doff == null) {
                          pkcode2Doff = new int[250];
                          pkcode2Size = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode2Doff[pcode2Number] = boff + 2;
                      pkcode2Size[pcode2Number] = plen - 4;
                      pcode2Number++;
                      break;
                 case 8:       //text string
                      if(pkcode8Doff == null) {
                          pkcode8Doff = new int[550];
                          pkcode8Size = new int[550];
                      }
                      plen = bos.getShort();
                      pkcode8Doff[pcode8Number] = boff + 2;
                      pkcode8Size[pcode8Number] = plen - 6;
                      pcode8Number++;
                      break;
                 case 3:
                 case 11:
                 case 25:
                      if(pkcode25Doff == null) {
                          pkcode25Doff = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode25Doff[pcode25Number] = boff + 2;
                      pcode25Number++;
                      break;
                 case 12:
                      if(pkcode12Doff == null) {
                          pkcode12Doff = new int[250];
                          pkcode12Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode12Doff[pcode12Number] = boff + 2;
                      pkcode12Dlen[pcode12Number] = plen/4;
                      pcode12Number++;
                      break;
                 case 13:
                      if(pkcode13Doff == null) {
                          pkcode13Doff = new int[250];
                          pkcode13Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode13Doff[pcode13Number] = boff + 2;
                      pkcode13Dlen[pcode13Number] = plen/4;
                      pcode13Number++;
                      break;
                 case 14:
                      if(pkcode14Doff == null) {
                          pkcode14Doff = new int[250];
                          pkcode14Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode14Doff[pcode14Number] = boff + 2;
                      pkcode14Dlen[pcode14Number] = plen/4;
                      pcode14Number++;
                      break;
                 case 15:
                      if(pkcode15Doff == null) {
                          pkcode15Doff = new int[250];
                          pkcode15Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode15Doff[pcode15Number] = boff + 2;
                      pkcode15Dlen[pcode15Number] = plen/6;
                      pcode15Number++;
                      break;
                 case 166:
                      if(pkcode16Doff == null) {
                          pkcode16Doff = new int[250];
                          pkcode16Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode16Doff[pcode16Number] = boff + 2;
                      pkcode16Dlen[pcode16Number] = plen/4;
                      pcode16Number++;
                      break;
                  case 19:
                      if(pkcode19Doff == null) {
                          pkcode19Doff = new int[250];
                          pkcode19Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode19Doff[pcode19Number] = boff + 2;
                      pkcode19Dlen[pcode19Number] = plen/10;
                      pcode19Number++;
                      break;
                  case 20:
                      if(pkcode20Doff == null) {
                          pkcode20Doff = new int[250];
                          pkcode20Dlen = new int[250];
                      }
                      plen = bos.getShort();
                      pkcode20Doff[pcode20Number] = boff + 2;
                      pkcode20Dlen[pcode20Number] = plen/8;
                      pcode20Number++;
                      break;
                 case 4:    // wind barb
                      if(pkcode4Doff == null) {
                          pkcode4Doff = new int[1000];
                      }
                      plen = bos.getShort();
                      pkcode4Doff[pcode4Number] = boff + 2;
                      pcode4Number++;
                      break;
                 case 5:  //   Vector Arrow Data
                      if(pkcode5Doff == null) {
                          pkcode5Doff = new int[1000];
                      }
                      plen = bos.getShort();
                      pkcode5Doff[pcode5Number] = boff + 2;
                      pcode5Number++;
                      break;
                 case 43:
                      plen = bos.getShort();
                      break;
                 case 23:
                 case 24:
                      plen = bos.getShort();
                      int poff = 2;
                      while (poff < plen){
                          int pcode = bos.getShort();
                          int len = bos.getShort();
                          switch (pcode)
                          {
                             case 2:
                                 if(pkcode2Doff == null) {
                                     pkcode2Doff = new int[250];
                                     pkcode2Size = new int[250];
                                 }
                                 pkcode2Doff[pcode2Number] = boff + poff + 4;
                                 pkcode2Size[pcode2Number] = len - 4;
                                 pcode2Number++;
                                 break;
                             case 6:
                                 if(pkcode6Doff == null) {
                                     pkcode6Doff = new int[250];
                                     pkcode6Dlen = new int[250];
                                 }
                                 pkcode6Doff[pcode6Number] = boff + poff + 4;
                                 pkcode6Dlen[pcode6Number] = (len - 6)/4;
                                 pcode6Number++;
                                 break;
                             case 25:
                                 if(pkcode25Doff == null) {
                                     pkcode25Doff = new int[250];
                                 }
                                 pkcode25Doff[pcode25Number] = boff + poff + 4;
                                 pcode25Number++;
                                 break;
                             default:
                                log.error( "error reading pcode= " + pcode+" "+raf.getLocation());
                                throw new IOException("error reading pcode, " +
                                        "unable to handle the packet with code "
                                        + pcode);
                          }
                          poff = poff + len + 4;
                          // Need to advance the file's position
                          bos.position(bos.position() + len);
                      }
                      break;
                  case 0x0802:
                      log.warn("Encountered unhandled packet code 0x0802 (contour color) -- reading past.");
                      Divlen_divider = bos.getShort(); // Color marker
                      if (Divlen_divider != 0x0002) {
                          log.warn("Missing color marker!");
                      }
                      plen = 2;
                      break;
                  case 0x0E03:
                      log.warn("Encountered unhandled packet code 0x0E03 (linked contours) -- reading past.");
                      Divlen_divider = bos.getShort(); // Start marker
                      if (Divlen_divider != 0x8000) {
                          log.warn("Missing start marker!");
                      }
                      // Read past start x, y for now
                      bos.getShort();
                      bos.getShort();
                      plen = 6 + bos.getShort();
                      break;

                 default:
                      if ( pkcode == 0xAF1F  || pkcode == 16) {              /* radial image                  */
                          hedsiz += pcode_radial( bos, hoff, hedsiz, isZ, uncompdata, pinfo.threshold) ;
                          //myInfo = new Vinfo (cname, numX, numX0, numY, numY0, hoff, hedsiz, isR, isZ);
                          plen = Divlen_length;
                          break;
                      }
                      else if ( pkcode == 28) {              /* radial image                  */
                          hedsiz += pcode_generic( bos, hoff, hedsiz, isZ, uncompdata, pinfo.threshold) ;
                          //myInfo = new Vinfo (cname, numX, numX0, numY, numY0, hoff, hedsiz, isR, isZ);
                          plen = Divlen_length;
                          break;
                      }
                      else if (pkcode == 0xBA0F ||pkcode == 0xBA07 )
                      {      /* raster image                  */
                          hedsiz += pcode_raster( bos, (short)pkcode, hoff, hedsiz, isZ, uncompdata);
                          //myInfo = new Vinfo (cname, numX, numX0, numY, numY0, hoff, hedsiz, isR, isZ);
                          plen = Divlen_length;
                          break;
                      }
                      else
                      {
                          log.error( "error reading pkcode equals " + pkcode+" "+raf.getLocation());
                          throw new IOException("error reading pkcode, unable to handle the product with code " + pkcode);
                      }

                  // size and beginning data position in file

              } //end of switch
              icount = icount + plen + 4;
          }

          klayer = klayer + Divlen_length + 6;
     }

      //int curDoff = hedsiz;

      if(pkcode8Doff != null){
          pcode_128( pkcode8Doff, pkcode8Size, 8, hoff, pcode8Number, "textStruct_code8", "",isZ);
      }
      if (pkcode1Doff != null){
          pcode_128( pkcode1Doff, pkcode1Size, 1, hoff, pcode1Number, "textStruct_code1", "", isZ);
      }
      if (pkcode2Doff != null){
          pcode_128( pkcode2Doff, pkcode2Size, 2, hoff, pcode2Number, "textStruct_code2", "", isZ);
      }
      if (pkcode10Doff != null){
          pcode_10n9( pkcode10Doff, pkcode10Dlen, hoff, pcode10Number, isZ);
      }
      if (pkcode4Doff != null){
          pcode_4( pkcode4Doff, hoff, pcode4Number, isZ);
      }
      if (pkcode5Doff != null){
          pcode_5( pkcode5Doff, hoff, pcode5Number, isZ);
      }
      if (pkcode6Doff != null){
          pcode_6n7( pkcode6Doff, pkcode6Dlen, hoff, pcode6Number, isZ, "linkedVector", 6);
      }
      if (pkcode25Doff != null){
          pcode_25( pkcode25Doff, hoff, pcode25Number, isZ);
      }
      if (pkcode12Doff != null){
          pcode_12n13n14( pkcode12Doff, pkcode12Dlen, hoff, pcode12Number, isZ, "TVS", 12);
      }
      if (pkcode13Doff != null){
          pcode_12n13n14( pkcode13Doff, pkcode13Dlen, hoff, pcode13Number, isZ, "hailPositive", 13);
      }
      if (pkcode14Doff != null){
          pcode_12n13n14( pkcode14Doff, pkcode14Dlen, hoff, pcode14Number, isZ, "hailProbable", 14);
      }
      if (pkcode19Doff != null){
          pcode_12n13n14( pkcode19Doff, pkcode19Dlen, hoff, pcode19Number, isZ, "hailIndex", 19);
      }
      if (pkcode20Doff != null){
          pcode_12n13n14( pkcode20Doff, pkcode20Dlen, hoff, pcode20Number, isZ, "mesocyclone", 20);
      }
    } else {
      log.debug ( "GetNexrDirs:: no product symbology block found (no image data) " +raf.getLocation());

    }

    if ( pinfo.offsetToTabularBlock != 0 ) {
         int tlayer = pinfo.offsetToTabularBlock*2;
         bos.position(tlayer);
         if( bos.hasRemaining()) {

             short tab_divider = bos.getShort();
             if ( tab_divider != -1) {
                 log.error ( "Block divider not found "+raf.getLocation());
                 throw new IOException("error reading graphic alphanumeric block" );
             }
             short tab_bid = bos.getShort();
             int tblen = bos.getInt();

             bos.position(tlayer+116);
             int inc = bos.getInt();
             bos.position(tlayer+128); // skip the second header and prod description

             tab_divider = bos.getShort();
             if ( tab_divider != -1) {
                 log.error ( "tab divider not found "+raf.getLocation());
                 throw new IOException("error reading graphic alphanumeric block" );
             }
             int npage = bos.getShort();

             int ppos =  bos.position();

             ArrayList dims =  new ArrayList();
             Dimension tbDim = new Dimension("pageNumber", npage);
             ncfile.addDimension( null, tbDim);
             dims.add( tbDim);
             Variable ppage = new Variable(ncfile, null, null, "TabMessagePage");
             ppage.setDimensions(dims);
             ppage.setDataType(DataType.STRING);
             ppage.addAttribute( new Attribute(CDM.LONG_NAME, "Graphic Product Message"));
             ncfile.addVariable(null, ppage);
             ppage.setSPobject( new Vinfo (npage, 0, tblen, 0, hoff, ppos, isR, isZ, null, null, tab_bid, 0));
         }

     }

     if ( pinfo.offsetToGraphicBlock != 0 ) {
         int gpkcode1Doff[] = null;
         int gpkcode2Doff[] = null;
         int gpkcode10Doff[] = null;
         int gpkcode10Dlen[] = null;
         int gpkcode8Doff[] = null;
         int gpkcode1Size[] = null;
         int gpkcode2Size[] = null;
         int gpkcode8Size[] = null;
         int gpcode1Number = 0;
         int gpcode10Number = 0;
         int gpcode8Number = 0;
         int gpcode2Number = 0;
         int tlayer = pinfo.offsetToGraphicBlock*2;
         bos.position(tlayer);
         short graphic_divider = bos.getShort();
         short graphic_bid = bos.getShort();
         if(graphic_divider!=-1 || graphic_bid != 2) {
               log.error( "error reading graphic alphanumeric block "+raf.getLocation());
               throw new IOException("error reading graphic alphanumeric block" );
         }
         int blen = bos.getInt();
         int clen = 0;
         int npage = bos.getShort();
         int lpage ;
         int ipage = 0;
         int plen ;

         while ( (clen < blen) && (ipage < npage) ) {
          //  bos.position(ppos);
            int ppos = bos.position();
            ipage =  bos.getShort();
            lpage =  bos.getShort();
            int icnt = 0;
            ppos = ppos + 4;
            while (icnt < lpage)
            {
                bos.position(ppos+icnt);
                int pkcode = bos.getShort();
                if(pkcode == 8 ) {
                   if(gpkcode8Doff == null) {
                          gpkcode8Doff = new int[550];
                          gpkcode8Size = new int[550];
                   }
                   plen = bos.getShort();
                   gpkcode8Doff[gpcode8Number] = ppos + 4 + icnt;
                   gpkcode8Size[gpcode8Number] = plen - 6;
                   icnt += plen + 4;
                   gpcode8Number++;
                }
                else if ( pkcode == 1 ) {
                   if(gpkcode1Doff == null) {
                          gpkcode1Doff = new int[550];
                          gpkcode1Size = new int[550];
                   }
                   plen = bos.getShort();
                   gpkcode1Doff[gpcode1Number] = ppos + 4 + icnt;
                   gpkcode1Size[gpcode1Number] = plen - 4;
                   icnt += plen + 4;
                   gpcode1Number++;
                }
                else if ( pkcode == 10 ) {
                   if(gpkcode10Doff == null)  {
                          gpkcode10Doff = new int[250];
                          gpkcode10Dlen = new int[250];
                   }
                   plen =  bos.getShort();   // for unlinked Vector Packet the length of data block

                   gpkcode10Doff[gpcode10Number] = ppos + 4+ icnt;
                   gpkcode10Dlen[gpcode10Number] = ( plen - 2 ) / 8;
                   icnt += plen + 4;
                   gpcode10Number++;
                }  else {
                   plen = bos.getShort();
                   icnt += plen + 4;
                }

              //  else {
              //      out.println( "error reading pkcode equals " + pkcode);
              //      throw new IOException("error reading pkcode in graphic alpha num block " + pkcode);
              //  }

            }
            ppos = ppos + lpage + 4;
            clen = clen + lpage + 4;
         }

         if(gpkcode8Doff != null){
             pcode_128( gpkcode8Doff, gpkcode8Size, 8, hoff, gpcode8Number, "textStruct_code8g", "g", isZ);
         }
         if(gpkcode2Doff != null){
             pcode_128( gpkcode2Doff, gpkcode2Size, 2, hoff, gpcode8Number, "textStruct_code2g", "g", isZ);
         }
         if(gpkcode1Doff != null){
             pcode_128( gpkcode1Doff, gpkcode1Size, 1, hoff, gpcode1Number, "textStruct_code1g", "g", isZ);
         }
         if (gpkcode10Doff != null){
             pcode_10n9( gpkcode10Doff, gpkcode10Dlen, hoff, gpcode10Number, isZ);
         }
         /*
         int ppos = bos.position();
         ArrayList dims =  new ArrayList();
         Dimension tbDim = new Dimension("pageNumber", npage, true);
         ncfile.addDimension( null, tbDim);
         dims.add( tbDim);
         Variable ppage = new Variable(ncfile, null, null, "GraphicMessagePage");
         ppage.setDimensions(dims);
         ppage.setDataType(DataType.STRING);
         ppage.addAttribute( new Attribute(CDM.LONG_NAME, "Graphic Product Message"));
         ncfile.addVariable(null, ppage);
         ppage.setSPobject( new Vinfo (npage, 0, tblen, 0, hoff, ppos, isR, isZ, null, null, graphic_bid));
           */
     }
    // finish
    ncfile.finish();
    }
void read ( ucar . unidata . io . RandomAccessFile raf , ucar . nc2 . NetcdfFile ncfile ) throws IOException { int hedsiz ; /* NEXRAD header size            */ int rc ; /* function return status        */ int hoff = 0 ; int type ; int zlibed ; boolean isZ = false ; int encrypt ; long actualSize ; int readLen ; readWMO ( raf ) ; this . ncfile = ncfile ; actualSize = raf . length ( ) ; int pos = 0 ; raf . seek ( pos ) ; // Read in the whole contents of the NEXRAD Level III product since
 // some product require to go through the whole file to build the  struct of file.
 readLen = ( int ) actualSize ; byte [ ] b = new byte [ readLen ] ; rc = raf . read ( b ) ; if ( rc != readLen ) { log . warn ( " error reading nids product header " + raf . getLocation ( ) ) ; } if ( ! noHeader ) { //Get product message header into a string for processing
 String pib = new String ( b , 0 , 100 , CDM . utf8Charset ) ; type = 0 ; pos = pib . indexOf ( "\r\r\n" ) ; while ( pos != - 1 ) { hoff = pos + 3 ; type ++ ; pos = pib . indexOf ( "\r\r\n" , pos + 1 ) ; } raf . seek ( hoff ) ; // Test the next two bytes to see if the image portion looks like
 // it is zlib-compressed.
 byte [ ] b2 = new byte [ 2 ] ; // byte[] b4 = new byte[4];
 System . arraycopy ( b , hoff , b2 , 0 , 2 ) ; zlibed = isZlibHed ( b2 ) ; if ( zlibed == 0 ) { encrypt = IsEncrypt ( b2 ) ; if ( encrypt == 1 ) { log . error ( "error reading encryted product " + raf . getLocation ( ) ) ; throw new IOException ( "unable to handle the product with encrypt code " + encrypt ) ; } } // process product description for station ID
 byte [ ] b3 = new byte [ 3 ] ; switch ( type ) { case 0 : log . warn ( "ReadNexrInfo:: Unable to seek to ID " + raf . getLocation ( ) ) ; break ; case 1 : case 2 : case 3 : case 4 : System . arraycopy ( b , hoff - 6 , b3 , 0 , 3 ) ; stationId = new String ( b3 , CDM . utf8Charset ) ; try { NexradStationDB . init ( ) ; // make sure database is initialized
 NexradStationDB . Station station = NexradStationDB . get ( "K" + stationId ) ; if ( station != null ) { stationName = station . name ; } } catch ( IOException ioe ) { log . error ( "NexradStationDB.init " + raf . getLocation ( ) , ioe ) ; } break ; default : break ; } if ( zlibed == 1 ) { isZ = true ; uncompdata = GetZlibedNexr ( b , readLen , hoff ) ; //uncompdata = Nidsiosp.readCompData(hoff, 160) ;
 if ( uncompdata == null ) { log . warn ( "ReadNexrInfo: error uncompressing image " + raf . getLocation ( ) ) ; uncompdata = new byte [ b . length - hoff ] ; System . arraycopy ( b , hoff , uncompdata , 0 , b . length - hoff ) ; } } else { uncompdata = new byte [ b . length - hoff ] ; System . arraycopy ( b , hoff , uncompdata , 0 , b . length - hoff ) ; } } else { uncompdata = new byte [ b . length ] ; System . arraycopy ( b , 0 , uncompdata , 0 , b . length ) ; // stationId  = "YYY";
 } byte [ ] b2 = new byte [ 2 ] ; ByteBuffer bos = ByteBuffer . wrap ( uncompdata ) ; rc = read_msghead ( bos , 0 ) ; hedsiz = 18 ; Pinfo pinfo = read_proddesc ( bos , hedsiz ) ; hedsiz += 102 ; // Set product-dependent information
 int prod_type = code_typelookup ( pinfo . pcode ) ; setProductInfo ( prod_type , pinfo ) ; //int windb = 0;
 int pcode1Number = 0 ; int pcode2Number = 0 ; int pcode8Number = 0 ; int pcode4Number = 0 ; int pcode5Number = 0 ; int pcode10Number = 0 ; int pcode6Number = 0 ; int pcode25Number = 0 ; int pcode12Number = 0 ; int pcode13Number = 0 ; int pcode14Number = 0 ; int pcode15Number = 0 ; int pcode16Number = 0 ; int pcode19Number = 0 ; int pcode20Number = 0 ; int pkcode1Doff [ ] = null ; int pkcode2Doff [ ] = null ; int pkcode8Doff [ ] = null ; int pkcode1Size [ ] = null ; int pkcode2Size [ ] = null ; int pkcode8Size [ ] = null ; int pkcode4Doff [ ] = null ; int pkcode5Doff [ ] = null ; int pkcode10Doff [ ] = null ; int pkcode10Dlen [ ] = null ; int pkcode6Doff [ ] = null ; int pkcode6Dlen [ ] = null ; int pkcode25Doff [ ] = null ; int pkcode12Doff [ ] = null ; int pkcode13Doff [ ] = null ; int pkcode14Doff [ ] = null ; int pkcode12Dlen [ ] = null ; int pkcode13Dlen [ ] = null ; int pkcode14Dlen [ ] = null ; int pkcode15Dlen [ ] = null ; int pkcode15Doff [ ] = null ; int pkcode16Dlen [ ] = null ; int pkcode16Doff [ ] = null ; int pkcode19Dlen [ ] = null ; int pkcode19Doff [ ] = null ; int pkcode20Dlen [ ] = null ; int pkcode20Doff [ ] = null ; // Get product symbology header (needed to get image shape)
 ifloop : if ( pinfo . offsetToSymbologyBlock != 0 ) { // Symbology header
 if ( pinfo . p8 == 1 ) { // TDWR data and the symbology is compressed
 int size = shortsToInt ( pinfo . p9 , pinfo . p10 , false ) ; uncompdata = uncompressed ( bos , hedsiz , size ) ; bos = ByteBuffer . wrap ( uncompdata ) ; } Sinfo sinfo = read_dividlen ( bos , hedsiz ) ; if ( rc == 0 || pinfo . divider != - 1 ) { log . warn ( "error in product symbology header " + raf . getLocation ( ) ) ; } if ( sinfo . id != 1 ) { if ( pinfo . pcode == 82 ) { read_SATab ( bos , hedsiz ) ; } break ifloop ; } hedsiz += 10 ; // Symbology layer
 int klayer = pinfo . offsetToSymbologyBlock * 2 + 10 ; for ( int i = 0 ; i < sinfo . nlayers ; i ++ ) { hedsiz = klayer ; bos . position ( hedsiz ) ; short Divlen_divider = bos . getShort ( ) ; hedsiz += 2 ; int Divlen_length = bos . getInt ( ) ; hedsiz += 4 ; if ( Divlen_divider != - 1 ) { log . warn ( "error reading length divider " + raf . getLocation ( ) ) ; } int icount = 0 ; int plen ; while ( icount < Divlen_length ) { int boff = klayer + icount + 6 ; bos . position ( boff ) ; bos . get ( b2 ) ; int pkcode = getUInt ( b2 , 2 ) ; hedsiz += 2 ; boff += 2 ; switch ( pkcode ) { case 18 : //  DPA
 case 17 : //   (pkcode == 0x11)   Digital Precipitation Array
 hedsiz += 8 ; plen = pcode_DPA ( bos , boff , hoff , hedsiz , isZ , i , pkcode ) ; break ; case 10 : //     (pkcode == 0xA)
 if ( pkcode10Doff == null ) { pkcode10Doff = new int [ 250 ] ; pkcode10Dlen = new int [ 250 ] ; } plen = bos . getShort ( ) ; // for unlinked Vector Packet the length of data block
 pkcode10Doff [ pcode10Number ] = boff + 2 ; pkcode10Dlen [ pcode10Number ] = ( plen - 2 ) / 8 ; pcode10Number ++ ; //pcode_10n7( bos, boff, hoff, isZ, pkcode );
 break ; case 1 : if ( pkcode1Doff == null ) { pkcode1Doff = new int [ 250 ] ; pkcode1Size = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode1Doff [ pcode1Number ] = boff + 2 ; pkcode1Size [ pcode1Number ] = plen - 4 ; pcode1Number ++ ; break ; case 2 : if ( pkcode2Doff == null ) { pkcode2Doff = new int [ 250 ] ; pkcode2Size = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode2Doff [ pcode2Number ] = boff + 2 ; pkcode2Size [ pcode2Number ] = plen - 4 ; pcode2Number ++ ; break ; case 8 : //text string
 if ( pkcode8Doff == null ) { pkcode8Doff = new int [ 550 ] ; pkcode8Size = new int [ 550 ] ; } plen = bos . getShort ( ) ; pkcode8Doff [ pcode8Number ] = boff + 2 ; pkcode8Size [ pcode8Number ] = plen - 6 ; pcode8Number ++ ; break ; case 3 : case 11 : case 25 : if ( pkcode25Doff == null ) { pkcode25Doff = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode25Doff [ pcode25Number ] = boff + 2 ; pcode25Number ++ ; break ; case 12 : if ( pkcode12Doff == null ) { pkcode12Doff = new int [ 250 ] ; pkcode12Dlen = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode12Doff [ pcode12Number ] = boff + 2 ; pkcode12Dlen [ pcode12Number ] = plen / 4 ; pcode12Number ++ ; break ; case 13 : if ( pkcode13Doff == null ) { pkcode13Doff = new int [ 250 ] ; pkcode13Dlen = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode13Doff [ pcode13Number ] = boff + 2 ; pkcode13Dlen [ pcode13Number ] = plen / 4 ; pcode13Number ++ ; break ; case 14 : if ( pkcode14Doff == null ) { pkcode14Doff = new int [ 250 ] ; pkcode14Dlen = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode14Doff [ pcode14Number ] = boff + 2 ; pkcode14Dlen [ pcode14Number ] = plen / 4 ; pcode14Number ++ ; break ; case 15 : if ( pkcode15Doff == null ) { pkcode15Doff = new int [ 250 ] ; pkcode15Dlen = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode15Doff [ pcode15Number ] = boff + 2 ; pkcode15Dlen [ pcode15Number ] = plen / 6 ; pcode15Number ++ ; break ; case 166 : if ( pkcode16Doff == null ) { pkcode16Doff = new int [ 250 ] ; pkcode16Dlen = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode16Doff [ pcode16Number ] = boff + 2 ; pkcode16Dlen [ pcode16Number ] = plen / 4 ; pcode16Number ++ ; break ; case 19 : if ( pkcode19Doff == null ) { pkcode19Doff = new int [ 250 ] ; pkcode19Dlen = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode19Doff [ pcode19Number ] = boff + 2 ; pkcode19Dlen [ pcode19Number ] = plen / 10 ; pcode19Number ++ ; break ; case 20 : if ( pkcode20Doff == null ) { pkcode20Doff = new int [ 250 ] ; pkcode20Dlen = new int [ 250 ] ; } plen = bos . getShort ( ) ; pkcode20Doff [ pcode20Number ] = boff + 2 ; pkcode20Dlen [ pcode20Number ] = plen / 8 ; pcode20Number ++ ; break ; case 4 : // wind barb
 if ( pkcode4Doff == null ) { pkcode4Doff = new int [ 1000 ] ; } plen = bos . getShort ( ) ; pkcode4Doff [ pcode4Number ] = boff + 2 ; pcode4Number ++ ; break ; case 5 : //   Vector Arrow Data
 if ( pkcode5Doff == null ) { pkcode5Doff = new int [ 1000 ] ; } plen = bos . getShort ( ) ; pkcode5Doff [ pcode5Number ] = boff + 2 ; pcode5Number ++ ; break ; case 43 : plen = bos . getShort ( ) ; break ; case 23 : case 24 : plen = bos . getShort ( ) ; int poff = 2 ; while ( poff < plen ) { int pcode = bos . getShort ( ) ; int len = bos . getShort ( ) ; switch ( pcode ) { case 2 : if ( pkcode2Doff == null ) { pkcode2Doff = new int [ 250 ] ; pkcode2Size = new int [ 250 ] ; } pkcode2Doff [ pcode2Number ] = boff + poff + 4 ; pkcode2Size [ pcode2Number ] = len - 4 ; pcode2Number ++ ; break ; case 6 : if ( pkcode6Doff == null ) { pkcode6Doff = new int [ 250 ] ; pkcode6Dlen = new int [ 250 ] ; } pkcode6Doff [ pcode6Number ] = boff + poff + 4 ; pkcode6Dlen [ pcode6Number ] = ( len - 6 ) / 4 ; pcode6Number ++ ; break ; case 25 : if ( pkcode25Doff == null ) { pkcode25Doff = new int [ 250 ] ; } pkcode25Doff [ pcode25Number ] = boff + poff + 4 ; pcode25Number ++ ; break ; default : log . error ( "error reading pcode= " + pcode + " " + raf . getLocation ( ) ) ; throw new IOException ( "error reading pcode, " + "unable to handle the packet with code " + pcode ) ; } poff = poff + len + 4 ; // Need to advance the file's position
 bos . position ( bos . position ( ) + len ) ; } break ; case 0x0802 : log . warn ( "Encountered unhandled packet code 0x0802 (contour color) -- reading past." ) ; Divlen_divider = bos . getShort ( ) ; // Color marker
 if ( Divlen_divider != 0x0002 ) { log . warn ( "Missing color marker!" ) ; } plen = 2 ; break ; case 0x0E03 : log . warn ( "Encountered unhandled packet code 0x0E03 (linked contours) -- reading past." ) ; Divlen_divider = bos . getShort ( ) ; // Start marker
 if ( Divlen_divider != 0x8000 ) { log . warn ( "Missing start marker!" ) ; } // Read past start x, y for now
 bos . getShort ( ) ; bos . getShort ( ) ; plen = 6 + bos . getShort ( ) ; break ; default : if ( pkcode == 0xAF1F || pkcode == 16 ) { /* radial image                  */ hedsiz += pcode_radial ( bos , hoff , hedsiz , isZ , uncompdata , pinfo . threshold ) ; //myInfo = new Vinfo (cname, numX, numX0, numY, numY0, hoff, hedsiz, isR, isZ);
 plen = Divlen_length ; break ; } else if ( pkcode == 28 ) { /* radial image                  */ hedsiz += pcode_generic ( bos , hoff , hedsiz , isZ , uncompdata , pinfo . threshold ) ; //myInfo = new Vinfo (cname, numX, numX0, numY, numY0, hoff, hedsiz, isR, isZ);
 plen = Divlen_length ; break ; } else if ( pkcode == 0xBA0F || pkcode == 0xBA07 ) { /* raster image                  */ hedsiz += pcode_raster ( bos , ( short ) pkcode , hoff , hedsiz , isZ , uncompdata ) ; //myInfo = new Vinfo (cname, numX, numX0, numY, numY0, hoff, hedsiz, isR, isZ);
 plen = Divlen_length ; break ; } else { log . error ( "error reading pkcode equals " + pkcode + " " + raf . getLocation ( ) ) ; throw new IOException ( "error reading pkcode, unable to handle the product with code " + pkcode ) ; } // size and beginning data position in file
 } //end of switch
 icount = icount + plen + 4 ; } klayer = klayer + Divlen_length + 6 ; } //int curDoff = hedsiz;
 if ( pkcode8Doff != null ) { pcode_128 ( pkcode8Doff , pkcode8Size , 8 , hoff , pcode8Number , "textStruct_code8" , "" , isZ ) ; } if ( pkcode1Doff != null ) { pcode_128 ( pkcode1Doff , pkcode1Size , 1 , hoff , pcode1Number , "textStruct_code1" , "" , isZ ) ; } if ( pkcode2Doff != null ) { pcode_128 ( pkcode2Doff , pkcode2Size , 2 , hoff , pcode2Number , "textStruct_code2" , "" , isZ ) ; } if ( pkcode10Doff != null ) { pcode_10n9 ( pkcode10Doff , pkcode10Dlen , hoff , pcode10Number , isZ ) ; } if ( pkcode4Doff != null ) { pcode_4 ( pkcode4Doff , hoff , pcode4Number , isZ ) ; } if ( pkcode5Doff != null ) { pcode_5 ( pkcode5Doff , hoff , pcode5Number , isZ ) ; } if ( pkcode6Doff != null ) { pcode_6n7 ( pkcode6Doff , pkcode6Dlen , hoff , pcode6Number , isZ , "linkedVector" , 6 ) ; } if ( pkcode25Doff != null ) { pcode_25 ( pkcode25Doff , hoff , pcode25Number , isZ ) ; } if ( pkcode12Doff != null ) { pcode_12n13n14 ( pkcode12Doff , pkcode12Dlen , hoff , pcode12Number , isZ , "TVS" , 12 ) ; } if ( pkcode13Doff != null ) { pcode_12n13n14 ( pkcode13Doff , pkcode13Dlen , hoff , pcode13Number , isZ , "hailPositive" , 13 ) ; } if ( pkcode14Doff != null ) { pcode_12n13n14 ( pkcode14Doff , pkcode14Dlen , hoff , pcode14Number , isZ , "hailProbable" , 14 ) ; } if ( pkcode19Doff != null ) { pcode_12n13n14 ( pkcode19Doff , pkcode19Dlen , hoff , pcode19Number , isZ , "hailIndex" , 19 ) ; } if ( pkcode20Doff != null ) { pcode_12n13n14 ( pkcode20Doff , pkcode20Dlen , hoff , pcode20Number , isZ , "mesocyclone" , 20 ) ; } } else { log . debug ( "GetNexrDirs:: no product symbology block found (no image data) " + raf . getLocation ( ) ) ; } if ( pinfo . offsetToTabularBlock != 0 ) { int tlayer = pinfo . offsetToTabularBlock * 2 ; bos . position ( tlayer ) ; if ( bos . hasRemaining ( ) ) { short tab_divider = bos . getShort ( ) ; if ( tab_divider != - 1 ) { log . error ( "Block divider not found " + raf . getLocation ( ) ) ; throw new IOException ( "error reading graphic alphanumeric block" ) ; } short tab_bid = bos . getShort ( ) ; int tblen = bos . getInt ( ) ; bos . position ( tlayer + 116 ) ; int inc = bos . getInt ( ) ; bos . position ( tlayer + 128 ) ; // skip the second header and prod description
 tab_divider = bos . getShort ( ) ; if ( tab_divider != - 1 ) { log . error ( "tab divider not found " + raf . getLocation ( ) ) ; throw new IOException ( "error reading graphic alphanumeric block" ) ; } int npage = bos . getShort ( ) ; int ppos = bos . position ( ) ; ArrayList dims = new ArrayList ( ) ; Dimension tbDim = new Dimension ( "pageNumber" , npage ) ; ncfile . addDimension ( null , tbDim ) ; dims . add ( tbDim ) ; Variable ppage = new Variable ( ncfile , null , null , "TabMessagePage" ) ; ppage . setDimensions ( dims ) ; ppage . setDataType ( DataType . STRING ) ; ppage . addAttribute ( new Attribute ( CDM . LONG_NAME , "Graphic Product Message" ) ) ; ncfile . addVariable ( null , ppage ) ; ppage . setSPobject ( new Vinfo ( npage , 0 , tblen , 0 , hoff , ppos , isR , isZ , null , null , tab_bid , 0 ) ) ; } } if ( pinfo . offsetToGraphicBlock != 0 ) { int gpkcode1Doff [ ] = null ; int gpkcode2Doff [ ] = null ; int gpkcode10Doff [ ] = null ; int gpkcode10Dlen [ ] = null ; int gpkcode8Doff [ ] = null ; int gpkcode1Size [ ] = null ; int gpkcode2Size [ ] = null ; int gpkcode8Size [ ] = null ; int gpcode1Number = 0 ; int gpcode10Number = 0 ; int gpcode8Number = 0 ; int gpcode2Number = 0 ; int tlayer = pinfo . offsetToGraphicBlock * 2 ; bos . position ( tlayer ) ; short graphic_divider = bos . getShort ( ) ; short graphic_bid = bos . getShort ( ) ; if ( graphic_divider != - 1 || graphic_bid != 2 ) { log . error ( "error reading graphic alphanumeric block " + raf . getLocation ( ) ) ; throw new IOException ( "error reading graphic alphanumeric block" ) ; } int blen = bos . getInt ( ) ; int clen = 0 ; int npage = bos . getShort ( ) ; int lpage ; int ipage = 0 ; int plen ; while ( ( clen < blen ) && ( ipage < npage ) ) { //  bos.position(ppos);
 int ppos = bos . position ( ) ; ipage = bos . getShort ( ) ; lpage = bos . getShort ( ) ; int icnt = 0 ; ppos = ppos + 4 ; while ( icnt < lpage ) { bos . position ( ppos + icnt ) ; int pkcode = bos . getShort ( ) ; if ( pkcode == 8 ) { if ( gpkcode8Doff == null ) { gpkcode8Doff = new int [ 550 ] ; gpkcode8Size = new int [ 550 ] ; } plen = bos . getShort ( ) ; gpkcode8Doff [ gpcode8Number ] = ppos + 4 + icnt ; gpkcode8Size [ gpcode8Number ] = plen - 6 ; icnt += plen + 4 ; gpcode8Number ++ ; } else if ( pkcode == 1 ) { if ( gpkcode1Doff == null ) { gpkcode1Doff = new int [ 550 ] ; gpkcode1Size = new int [ 550 ] ; } plen = bos . getShort ( ) ; gpkcode1Doff [ gpcode1Number ] = ppos + 4 + icnt ; gpkcode1Size [ gpcode1Number ] = plen - 4 ; icnt += plen + 4 ; gpcode1Number ++ ; } else if ( pkcode == 10 ) { if ( gpkcode10Doff == null ) { gpkcode10Doff = new int [ 250 ] ; gpkcode10Dlen = new int [ 250 ] ; } plen = bos . getShort ( ) ; // for unlinked Vector Packet the length of data block
 gpkcode10Doff [ gpcode10Number ] = ppos + 4 + icnt ; gpkcode10Dlen [ gpcode10Number ] = ( plen - 2 ) / 8 ; icnt += plen + 4 ; gpcode10Number ++ ; } else { plen = bos . getShort ( ) ; icnt += plen + 4 ; } //  else {
 //      out.println( "error reading pkcode equals " + pkcode);
 //      throw new IOException("error reading pkcode in graphic alpha num block " + pkcode);
 //  }
 } ppos = ppos + lpage + 4 ; clen = clen + lpage + 4 ; } if ( gpkcode8Doff != null ) { pcode_128 ( gpkcode8Doff , gpkcode8Size , 8 , hoff , gpcode8Number , "textStruct_code8g" , "g" , isZ ) ; } if ( gpkcode2Doff != null ) { pcode_128 ( gpkcode2Doff , gpkcode2Size , 2 , hoff , gpcode8Number , "textStruct_code2g" , "g" , isZ ) ; } if ( gpkcode1Doff != null ) { pcode_128 ( gpkcode1Doff , gpkcode1Size , 1 , hoff , gpcode1Number , "textStruct_code1g" , "g" , isZ ) ; } if ( gpkcode10Doff != null ) { pcode_10n9 ( gpkcode10Doff , gpkcode10Dlen , hoff , gpcode10Number , isZ ) ; } /*
         int ppos = bos.position();
         ArrayList dims =  new ArrayList();
         Dimension tbDim = new Dimension("pageNumber", npage, true);
         ncfile.addDimension( null, tbDim);
         dims.add( tbDim);
         Variable ppage = new Variable(ncfile, null, null, "GraphicMessagePage");
         ppage.setDimensions(dims);
         ppage.setDataType(DataType.STRING);
         ppage.addAttribute( new Attribute(CDM.LONG_NAME, "Graphic Product Message"));
         ncfile.addVariable(null, ppage);
         ppage.setSPobject( new Vinfo (npage, 0, tblen, 0, hoff, ppos, isR, isZ, null, null, graphic_bid));
           */ } // finish
 ncfile . finish ( ) ; }
read and parse the header of the nids/tdwr file
@param raf       input file
@param ncfile    output file
@throws IOException
read and parse the header of the nids / tdwr file