visad/src/main/java/ucar/nc2/iosp/grid/GridIndexToNC.java
private void makeDenseCoordSys(NetcdfFile ncfile, GridTableLookup lookup, CancelTask cancelTask) throws IOException {
    List<GridTimeCoord> timeCoords = new ArrayList<>();
    List<GridVertCoord> vertCoords = new ArrayList<>();
    List<GridEnsembleCoord> ensembleCoords = new ArrayList<>();

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));

    // loop over HorizCoordSys
    Collection<GridHorizCoordSys> hcset = hcsHash.values();
    for (GridHorizCoordSys hcs : hcset) {
      if ((cancelTask != null) && cancelTask.isCancel()) break;

      // loop over GridVariables in the HorizCoordSys
      // create the time and vertical coordinates
      List<GridVariable> gribvars = new ArrayList<>(hcs.varHash.values());
      for (GridVariable gv : gribvars) {
        if ((cancelTask != null) && cancelTask.isCancel()) break;

        List<GridRecord> recordList = gv.getRecords();
        GridRecord record = recordList.get(0);
        String vname = gv.makeLevelName(record, lookup);

        // look to see if vertical already exists
        GridVertCoord useVertCoord = null;
        for (GridVertCoord gvcs : vertCoords) {
          if (vname.equals(gvcs.getLevelName())) {
            if (gvcs.matchLevels(recordList)) {  // must have the same levels
              useVertCoord = gvcs;
            }
          }
        }
        if (useVertCoord == null) {  // nope, got to create it
          useVertCoord = makeGridVertCoord(recordList, vname, lookup, hcs);
          vertCoords.add(useVertCoord);
        }
        gv.setVertCoord(useVertCoord);
        // look to see if time coord already exists
        GridTimeCoord useTimeCoord = null;
        for (GridTimeCoord gtc : timeCoords) {
          if (gtc.matchTimes(recordList)) {  // must have the same time coords
            useTimeCoord = gtc;
            break;
          }
        }
        if (useTimeCoord == null) {  // nope, got to create it
          useTimeCoord = makeGridTimeCoord(recordList, ncfile.getLocation());
          timeCoords.add(useTimeCoord);
        }
        gv.setTimeCoord(useTimeCoord);

        if (gv.isEnsemble()) {
          GridEnsembleCoord useEnsembleCoord = addEnsembles(ensembleCoords, recordList);
          if (useEnsembleCoord != null)
            gv.setEnsembleCoord(useEnsembleCoord);
        }
      }

      // assign time coordinate names, add dimensions to file
      // reverse sort by length - give time dimensions unique names
      Collections.sort(timeCoords);
      int count = 0;
      for (GridTimeCoord tcs : timeCoords) {
        tcs.setSequence(count++);
        tcs.addDimensionsToNetcdfFile(ncfile, hcs.getGroup());
      }

      // add Ensemble dimensions, give Ensemble dimensions unique names
      int seqno = 0;
      for (GridEnsembleCoord gec : ensembleCoords) {
        gec.setSequence(seqno++);
        gec.addDimensionsToNetcdfFile(ncfile, hcs.getGroup());
      }

      // add x, y dimensions
      hcs.addDimensionsToNetcdfFile(ncfile);

      // add vertical dimensions, give them unique names
      Collections.sort(vertCoords);
      int vcIndex = 0;
      String listName = null;
      int start = 0;
      for (vcIndex = 0; vcIndex < vertCoords.size(); vcIndex++) {
        GridVertCoord gvcs = vertCoords.get(vcIndex);
        String vname = gvcs.getLevelName();
        if (listName == null) {
          listName = vname;  // initial
        }

        if (!vname.equals(listName)) {
          makeVerticalDimensions(vertCoords.subList(start, vcIndex), ncfile, hcs.getGroup());
          listName = vname;
          start = vcIndex;
        }
      }
      makeVerticalDimensions(vertCoords.subList(start, vcIndex), ncfile, hcs.getGroup());

      // create a variable for each entry, but check for other products with same simple name to disambiguate
      List<List<GridVariable>> products = new ArrayList<>(hcs.productHash.values());
      for (List<GridVariable> plist : products) {
        if ((cancelTask != null) && cancelTask.isCancel()) break;

        if (plist.size() == 1) {
          GridVariable pv = plist.get(0);
          String name = pv.getFirstRecord().cdmVariableName(lookup, false, false); // plain ole name
          Variable v = pv.makeVariable(ncfile, hcs.getGroup(), name, raf );
          ncfile.addVariable(hcs.getGroup(), v);

        } else {

          // collect them grouped by vertical coord
          Map<GridVertCoord,VertCollection> vcMap = new HashMap<>();
          for (GridVariable gv : plist) {
            VertCollection vc = vcMap.get(gv.getVertCoord());
            if (vc == null) {
              vc = new VertCollection(gv);
              vcMap.put(gv.getVertCoord(), vc);
            }
            vc.list.add(gv);
          }

          // sort by larger # vert levels
          List<VertCollection> vclist = new ArrayList<>(vcMap.values());
          Collections.sort(vclist);

          boolean firstVertCoord = true;
          for (VertCollection vc : vclist) {
            boolean hasMultipleLevels = vc.vc.getNLevels() > 1;
            boolean noLevelOk = firstVertCoord; //  && hasMultipleLevels;  LOOK turned off for now 9/15/10
            List<GridVariable> list = vc.list;
            if (list.size() == 1) {
              GridVariable gv = list.get(0);
              String name = gv.getFirstRecord().cdmVariableName(lookup, !noLevelOk, false);
              ncfile.addVariable(hcs.getGroup(), gv.makeVariable(ncfile, hcs.getGroup(), name, raf));

            } else {
              for (GridVariable gv : list) { // more than one - disambiguate by stat name
                String name = gv.getFirstRecord().cdmVariableName(lookup, !noLevelOk, true);
                ncfile.addVariable(hcs.getGroup(), gv.makeVariable(ncfile, hcs.getGroup(), name, raf));
              }
            }
            firstVertCoord = false;
          }

        } // multiple vertical levels

      } // create variable

      // add coordinate variables at the end
      for (GridTimeCoord tcs : timeCoords) {
        tcs.addToNetcdfFile(ncfile, hcs.getGroup());
      }

      for (GridEnsembleCoord ens : ensembleCoords) {
        ens.addToNetcdfFile(ncfile, hcs.getGroup());
      }

      hcs.addToNetcdfFile(ncfile);

      for (GridVertCoord gvcs : vertCoords) {
        gvcs.addToNetcdfFile(ncfile, hcs.getGroup());
      }

    } // loop over hcs
    // TODO: check this,  in ToolsUI it caused problems
    //for (GridVertCoord gvcs : vertCoords) {
    //  gvcs.empty();
    //}

  }
private void makeDenseCoordSys(NetcdfFile ncfile, GridTableLookup lookup, CancelTask cancelTask) throws IOException {
    List<GridTimeCoord> timeCoords = new ArrayList<>();
    List<GridVertCoord> vertCoords = new ArrayList<>();
    List<GridEnsembleCoord> ensembleCoords = new ArrayList<>();

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));

    // loop over HorizCoordSys
    Collection<GridHorizCoordSys> hcset = hcsHash.values();
    for (GridHorizCoordSys hcs : hcset) {
      if ((cancelTask != null) && cancelTask.isCancel()) break;

      // loop over GridVariables in the HorizCoordSys
      // create the time and vertical coordinates
      List<GridVariable> gribvars = new ArrayList<>(hcs.varHash.values());
      for (GridVariable gv : gribvars) {
        if ((cancelTask != null) && cancelTask.isCancel()) break;

        List<GridRecord> recordList = gv.getRecords();
        GridRecord record = recordList.get(0);
        String vname = gv.makeLevelName(record, lookup);

        // look to see if vertical already exists
        GridVertCoord useVertCoord = null;
        for (GridVertCoord gvcs : vertCoords) {
          if (vname.equals(gvcs.getLevelName())) {
            if (gvcs.matchLevels(recordList)) {  // must have the same levels
              useVertCoord = gvcs;
            }
          }
        }
        if (useVertCoord == null) {  // nope, got to create it
          useVertCoord = makeGridVertCoord(recordList, vname, lookup, hcs);
          vertCoords.add(useVertCoord);
        }
        gv.setVertCoord(useVertCoord);
        // look to see if time coord already exists
        GridTimeCoord useTimeCoord = null;
        for (GridTimeCoord gtc : timeCoords) {
          if (gtc.matchTimes(recordList)) {  // must have the same time coords
            useTimeCoord = gtc;
            break;
          }
        }
        if (useTimeCoord == null) {  // nope, got to create it
          useTimeCoord = makeGridTimeCoord(recordList, ncfile.getLocation());
          timeCoords.add(useTimeCoord);
        }
        gv.setTimeCoord(useTimeCoord);

        if (gv.isEnsemble()) {
          GridEnsembleCoord useEnsembleCoord = addEnsembles(ensembleCoords, recordList);
          if (useEnsembleCoord != null)
            gv.setEnsembleCoord(useEnsembleCoord);
        }
      }

      // assign time coordinate names, add dimensions to file
      // reverse sort by length - give time dimensions unique names
      Collections.sort(timeCoords);
      int count = 0;
      for (GridTimeCoord tcs : timeCoords) {
        tcs.setSequence(count++);
        tcs.addDimensionsToNetcdfFile(ncfile, hcs.getGroup());
      }

      // add Ensemble dimensions, give Ensemble dimensions unique names
      int seqno = 0;
      for (GridEnsembleCoord gec : ensembleCoords) {
        gec.setSequence(seqno++);
        gec.addDimensionsToNetcdfFile(ncfile, hcs.getGroup());
      }

      // add x, y dimensions
      hcs.addDimensionsToNetcdfFile(ncfile);

      // add vertical dimensions, give them unique names
      Collections.sort(vertCoords);
      int vcIndex = 0;
      String listName = null;
      int start = 0;
      for (vcIndex = 0; vcIndex < vertCoords.size(); vcIndex++) {
        GridVertCoord gvcs = vertCoords.get(vcIndex);
        String vname = gvcs.getLevelName();
        if (listName == null) {
          listName = vname;  // initial
        }

        if (!vname.equals(listName)) {
          makeVerticalDimensions(vertCoords.subList(start, vcIndex), ncfile, hcs.getGroup());
          listName = vname;
          start = vcIndex;
        }
      }
      makeVerticalDimensions(vertCoords.subList(start, vcIndex), ncfile, hcs.getGroup());

      // create a variable for each entry, but check for other products with same simple name to disambiguate
      List<List<GridVariable>> products = new ArrayList<>(hcs.productHash.values());
      for (List<GridVariable> plist : products) {
        if ((cancelTask != null) && cancelTask.isCancel()) break;

        if (plist.size() == 1) {
          GridVariable pv = plist.get(0);
          String name = pv.getFirstRecord().cdmVariableName(lookup, false, false); // plain ole name
          Variable v = pv.makeVariable(ncfile, hcs.getGroup(), name, raf );
          ncfile.addVariable(hcs.getGroup(), v);

        } else {

          // collect them grouped by vertical coord
          Map<GridVertCoord,VertCollection> vcMap = new HashMap<>();
          for (GridVariable gv : plist) {
            VertCollection vc = vcMap.get(gv.getVertCoord());
            if (vc == null) {
              vc = new VertCollection(gv);
              vcMap.put(gv.getVertCoord(), vc);
            }
            vc.list.add(gv);
          }

          // sort by larger # vert levels
          List<VertCollection> vclist = new ArrayList<>(vcMap.values());
          Collections.sort(vclist);

          boolean firstVertCoord = true;
          for (VertCollection vc : vclist) {
            boolean hasMultipleLevels = vc.vc.getNLevels() > 1;
            boolean noLevelOk = firstVertCoord; //  && hasMultipleLevels;  LOOK turned off for now 9/15/10
            List<GridVariable> list = vc.list;
            if (list.size() == 1) {
              GridVariable gv = list.get(0);
              String name = gv.getFirstRecord().cdmVariableName(lookup, !noLevelOk, false);
              ncfile.addVariable(hcs.getGroup(), gv.makeVariable(ncfile, hcs.getGroup(), name, raf));

            } else {
              for (GridVariable gv : list) { // more than one - disambiguate by stat name
                String name = gv.getFirstRecord().cdmVariableName(lookup, !noLevelOk, true);
                ncfile.addVariable(hcs.getGroup(), gv.makeVariable(ncfile, hcs.getGroup(), name, raf));
              }
            }
            firstVertCoord = false;
          }

        } // multiple vertical levels

      } // create variable

      // add coordinate variables at the end
      for (GridTimeCoord tcs : timeCoords) {
        tcs.addToNetcdfFile(ncfile, hcs.getGroup());
      }

      for (GridEnsembleCoord ens : ensembleCoords) {
        ens.addToNetcdfFile(ncfile, hcs.getGroup());
      }

      hcs.addToNetcdfFile(ncfile);

      for (GridVertCoord gvcs : vertCoords) {
        gvcs.addToNetcdfFile(ncfile, hcs.getGroup());
      }

    } // loop over hcs
    // TODO: check this,  in ToolsUI it caused problems
    //for (GridVertCoord gvcs : vertCoords) {
    //  gvcs.empty();
    //}

  }
Make coordinate system without missing data - means that we
have to make a coordinate axis for each unique set
of time or vertical levels.

@param ncfile     netCDF file
@param lookup     lookup  table
@param cancelTask cancel task
@throws IOException problem reading file