public void writeRecord(String stnName, Date obsDate, StructureData sdata) throws IOException {
    StationTracker stnTracker = stationMap.get(stnName);
    ProfileTracker proTracker = stnTracker.profileMap.get(obsDate);

    if (proTracker == null) {
      proTracker = new ProfileTracker(profileIndex);
      stnTracker.profileMap.put(obsDate, proTracker);

      stnTracker.link.add(profileIndex);
      stnTracker.lastChild = profileIndex;
      stnTracker.numChildren++;

      try {
        originTime[0] = profileIndex; // 2d index
        timeArray.set(0, dateFormatter.toDateTimeStringISO(obsDate));
        parentArray.set(0, stnTracker.parent_index);
        ncfile.writeStringData(timeName, originTime, timeArray);
        ncfile.write(parentStationIndex, originTime, parentArray);
      } catch (InvalidRangeException e) {
        e.printStackTrace();
        throw new IllegalStateException(e);
      }

      profileIndex++;
    }

    // needs to be wrapped as an ArrayStructure, even though we are only writing one at a time.
    ArrayStructureW sArray = new ArrayStructureW(sdata.getStructureMembers(), new int[] {1});
    sArray.setStructureData(sdata, 0);

    // track the min and max date
    if ((minDate == null) || minDate.after(obsDate)) minDate = obsDate;
    if ((maxDate == null) || maxDate.before(obsDate)) maxDate = obsDate;

    timeArray.set(0, dateFormatter.toDateTimeStringISO(obsDate));
    parentArray.set(0, proTracker.parent_index);

    proTracker.link.add(recno);
    proTracker.lastChild = recno; // not currently used
    proTracker.numChildren++;

    // write the recno record
    origin[0] = recno; // 1d index
    originTime[0] = recno; // 2d index
    try {
      ncfile.write("record", origin, sArray);
      ncfile.write(parentProfileIndex, originTime, parentArray);
    } catch (InvalidRangeException e) {
      e.printStackTrace();
      throw new IllegalStateException(e);
    }

    recno++;
  }
  public static void main(String args[]) throws Exception {
    long start = System.currentTimeMillis();
    Map<String, ucar.unidata.geoloc.Station> staHash =
        new HashMap<String, ucar.unidata.geoloc.Station>();

    String location = "R:/testdata/sounding/netcdf/Upperair_20070401_0000.nc";
    NetcdfDataset ncfile = NetcdfDataset.openDataset(location);
    ncfile.sendIospMessage(NetcdfFile.IOSP_MESSAGE_ADD_RECORD_STRUCTURE);

    // look through record varibles, for those that have "manLevel" dimension
    // make a StructureData object for those
    StructureMembers sm = new StructureMembers("manLevel");
    Dimension manDim = ncfile.findDimension("manLevel");
    Structure record = (Structure) ncfile.findVariable("record");
    List<Variable> allList = record.getVariables();
    List<VariableSimpleIF> varList = new ArrayList<VariableSimpleIF>();
    for (Variable v : allList) {
      if ((v.getRank() == 1) && v.getDimension(0).equals(manDim)) {
        // public VariableDS(NetcdfDataset ds, Group group, Structure parentStructure, String
        // shortName, DataType dataType,
        // String dims, String units, String desc) {
        varList.add(
            new VariableDS(
                ncfile,
                null,
                null,
                v.getShortName(),
                v.getDataType(),
                "",
                v.getUnitsString(),
                v.getDescription()));
        // (String name, String desc, String units, DataType dtype, int []shape)
        sm.addMember(
            v.getShortName(),
            v.getDescription(),
            v.getUnitsString(),
            v.getDataType(),
            new int[0]); // scalar
      }
    }

    ArrayStructureMA manAS = new ArrayStructureMA(sm, new int[] {manDim.getLength()});

    // need the date units
    Variable time = ncfile.findVariable("synTime");
    String timeUnits = ncfile.findAttValueIgnoreCase(time, "units", null);
    timeUnits = StringUtil.remove(timeUnits, '('); // crappy fsl'ism
    timeUnits = StringUtil.remove(timeUnits, ')');
    DateUnit timeUnit = new DateUnit(timeUnits);

    // extract stations
    int nrecs = 0;
    StructureDataIterator iter = record.getStructureIterator();
    while (iter.hasNext()) {
      StructureData sdata = iter.next();
      String name = sdata.getScalarString("staName");
      ucar.unidata.geoloc.Station s = staHash.get(name);
      if (s == null) {
        float lat = sdata.convertScalarFloat("staLat");
        float lon = sdata.convertScalarFloat("staLon");
        float elev = sdata.convertScalarFloat("staElev");
        s = new StationImpl(name, "", lat, lon, elev);
        staHash.put(name, s);
      }
      nrecs++;
    }
    List<ucar.unidata.geoloc.Station> stnList =
        Arrays.asList(staHash.values().toArray(new ucar.unidata.geoloc.Station[staHash.size()]));
    Collections.sort(stnList);

    // create the writer
    WriterProfileObsDataset writer =
        new WriterProfileObsDataset(location + ".out", "rewrite " + location);
    writer.writeHeader(stnList, varList, nrecs, "prMan");

    // extract records
    iter = record.getStructureIterator();
    while (iter.hasNext()) {
      StructureData sdata = iter.next();
      String name = sdata.getScalarString("staName");
      double timeValue = sdata.convertScalarDouble("synTime");
      Date date = timeUnit.makeDate(timeValue);

      // transfer to the ArrayStructure
      List<String> names = sm.getMemberNames();
      for (String mname : names) {
        manAS.setMemberArray(mname, sdata.getArray(mname));
      }

      // each level is weritten as a seperate structure
      int numMand = sdata.getScalarInt("numMand");
      if (numMand >= manDim.getLength()) continue;

      for (int i = 0; i < numMand; i++) {
        StructureData useData = manAS.getStructureData(i);
        writer.writeRecord(name, date, useData);
      }
    }

    writer.finish();

    long took = System.currentTimeMillis() - start;
    System.out.println("That took = " + took);
  }
 private MyEarthLocation(StructureData sdata) {
   this.latitude = sdata.convertScalarDouble(SingleTrajectory.this.latVar.getShortName());
   this.longitude = sdata.convertScalarDouble(SingleTrajectory.this.lonVar.getShortName());
   this.elevation = sdata.convertScalarDouble(SingleTrajectory.this.elevVar.getShortName());
   if (elevVarUnitsConversionFactor != 1.0) this.elevation *= elevVarUnitsConversionFactor;
 }
 private MyPointObsDatatype(int point, StructureData sdata) {
   this.point = point;
   this.sdata = sdata;
   this.time = sdata.convertScalarDouble(SingleTrajectory.this.timeVar.getShortName());
   this.earthLoc = new MyEarthLocation(sdata);
 }