private void writeDataFinish() throws IOException {
    // finish global variables
    ArrayInt.D0 totalArray = new ArrayInt.D0();
    totalArray.set(profileIndex);
    try {
      ncfile.write(numProfilesTotalName, totalArray);
    } catch (InvalidRangeException e) {
      e.printStackTrace();
      throw new IllegalStateException(e);
    }

    // finish the station data
    int nstns = stnList.size();
    ArrayInt.D1 firstProfileArray = new ArrayInt.D1(nstns);
    ArrayInt.D1 numProfileArray = new ArrayInt.D1(nstns);
    ArrayInt.D1 nextProfileArray = new ArrayInt.D1(nprofiles);

    for (int i = 0; i < stnList.size(); i++) {
      ucar.unidata.geoloc.Station stn = stnList.get(i);
      StationTracker tracker = stationMap.get(stn.getName());

      numProfileArray.set(i, tracker.numChildren);

      int first = (tracker.link.size() > 0) ? tracker.link.get(0) : -1;
      firstProfileArray.set(i, first);

      if (tracker.link.size() > 0) {
        // construct forward link
        List<Integer> nextList = tracker.link;
        for (int j = 0; j < nextList.size() - 1; j++) {
          Integer curr = nextList.get(j);
          Integer next = nextList.get(j + 1);
          nextProfileArray.set(curr, next);
        }
        Integer curr = nextList.get(nextList.size() - 1);
        nextProfileArray.set(curr, -1);
      }
    }

    try {
      ncfile.write(firstProfileName, firstProfileArray);
      ncfile.write(numProfilesName, numProfileArray);
      ncfile.write(nextProfileName, nextProfileArray);

    } catch (InvalidRangeException e) {
      e.printStackTrace();
      throw new IllegalStateException(e);
    }

    // finish the profile data
    ArrayInt.D1 nextObsArray = new ArrayInt.D1(recno);
    ArrayInt.D1 firstObsArray = new ArrayInt.D1(nprofiles);
    ArrayInt.D1 numObsArray = new ArrayInt.D1(nprofiles);

    for (int i = 0; i < stnList.size(); i++) {
      ucar.unidata.geoloc.Station stn = stnList.get(i);
      StationTracker stnTracker = stationMap.get(stn.getName());

      Set<Date> dates = stnTracker.profileMap.keySet();
      for (Date date : dates) {
        ProfileTracker proTracker = stnTracker.profileMap.get(date);
        int trackerIndex = proTracker.parent_index;
        numObsArray.set(trackerIndex, proTracker.numChildren);

        int first = (proTracker.link.size() > 0) ? proTracker.link.get(0) : -1;
        firstObsArray.set(trackerIndex, first);

        if (proTracker.link.size() > 0) {
          // construct forward link
          List<Integer> nextList = proTracker.link;
          for (int j = 0; j < nextList.size() - 1; j++) {
            Integer curr = nextList.get(j);
            Integer next = nextList.get(j + 1);
            nextObsArray.set(curr, next);
          }
          Integer curr = nextList.get(nextList.size() - 1);
          nextObsArray.set(curr, -1);
        }
      }
    }

    try {
      ncfile.write(firstObsName, firstObsArray);
      ncfile.write(numObsName, numObsArray);
      ncfile.write(nextObsName, nextObsArray);

    } catch (InvalidRangeException e) {
      e.printStackTrace();
      throw new IllegalStateException(e);
    }

    // finish the obs data

    ncfile.updateAttribute(
        null, new Attribute("time_coverage_start", dateFormatter.toDateTimeStringISO(minDate)));
    ncfile.updateAttribute(
        null, new Attribute("time_coverage_end", dateFormatter.toDateTimeStringISO(maxDate)));
  }