public void makeFiles(DateTime begin, double duration, String nsclSelectString, String mask) {
    cwbServer.query(begin, duration, nsclSelectString);
    if (cwbServer.hasNext()) {
      do {
        SacTimeSeries sac =
            makeTimeSeries(cwbServer.getNext(), begin, duration, this.fill, this.gaps, this.trim);
        if (sac != null) {
          if (this.event != null) {
            SacHeaders.setEventHeader(sac, this.event);
            if (this.picks) {
              if (this.synthetic == null) {
                SacHeaders.setPhasePicks(sac, this.event);
              } else {
                SacHeaders.setPhasePicks(sac, this.event, this.extendedPhases, this.synthetic);
              }
            } else {
              if (this.synthetic != null) {
                SacHeaders.setPhasePicks(sac, this.extendedPhases, this.synthetic);
              }
            }
          } else {
            if (this.customEvent != null) {
              SacHeaders.setEventHeader(
                  sac,
                  this.customEvent.getEventTime(),
                  this.customEvent.getEventLat(),
                  this.customEvent.getEventLon(),
                  this.customEvent.getEventDepth(),
                  this.customEvent.getEventMag(),
                  this.customEvent.getEventMagType().magNum(),
                  this.customEvent.getEventType().eventTypeNum());
            }
            if (this.synthetic != null) {
              SacHeaders.setPhasePicks(sac, this.extendedPhases, this.synthetic);
            }
          }

          outputFile(sac, begin, mask, this.pzunit);
        } else {
          // TODO logger message about null data
        }
      } while (cwbServer.hasNext());
    } else {
      logger.info(
          String.format(
              "No matching data for \"%s\", at begin time %s, duration %.2fs, on %s:%d",
              nsclSelectString,
              begin.toString("YYYY/MM/dd HH:mm:ss"),
              duration,
              cwbServer.getHost(),
              cwbServer.getPort()));
    }
  }
  public SacTimeSeries makeTimeSeries(
      TreeSet<MiniSeed> miniSeed,
      DateTime begin,
      double duration,
      Integer fill,
      boolean gaps,
      boolean trim) {
    // This logic isn't strictly the same as SacOutputter.
    if (!gaps && fill == null) {
      fill = 2147000000;
    }

    // Use the span to populate a sac file

    TimeZone tz = TimeZone.getTimeZone("GMT+0");
    TimeZone.setDefault(tz);
    GregorianCalendar start = new GregorianCalendar();
    start.setTimeInMillis(begin.getMillis());

    // build the zero filled area (either with exact limits or with all blocks)
    ZeroFilledSpan span = new ZeroFilledSpan(new ArrayList(miniSeed), start, duration, fill);
    if (span.getRate() <= 0.00) {
      return null; // There is no real data to put in SAC
    }

    NSCL nscl = NSCL.stringToNSCL(miniSeed.first().getSeedName());

    logger.fine("ZeroSpan=" + span.toString());

    int noval = span.getNMissingData();

    if (!gaps && span.hasGapsBeforeEnd()) {
      logger.warning("  ** " + nscl.toString() + " has gaps - discarded # missing =" + noval);
      return null;
    }

    // ZeroFilledSpan span = new ZeroFilledSpan(blks);

    SacTimeSeries sac = new SacTimeSeries();
    sac.npts = span.getNsamp();

    // Set the byteOrder based on native architecture and sac statics
    sac.nvhdr = 6; // Only format supported
    sac.b = 0.; // beginning time offsed
    sac.e = ((span.getNsamp() - 1) / span.getRate());
    sac.iftype = SacTimeSeries.ITIME;
    sac.leven = SacTimeSeries.TRUE;
    sac.delta = (1. / span.getRate());
    sac.depmin = span.getMin();
    sac.depmax = span.getMax();
    sac.nzyear = span.getStart().get(Calendar.YEAR);
    sac.nzjday = span.getStart().get(Calendar.DAY_OF_YEAR);
    sac.nzhour = span.getStart().get(Calendar.HOUR_OF_DAY);
    sac.nzmin = span.getStart().get(Calendar.MINUTE);
    sac.nzsec = span.getStart().get(Calendar.SECOND);
    sac.nzmsec = span.getStart().get(Calendar.MILLISECOND);
    sac.iztype = SacTimeSeries.IB;

    sac.knetwk = nscl.getNetwork().replaceAll("_", "").trim();
    sac.kstnm = nscl.getStation().replaceAll("_", "").trim();
    sac.kcmpnm = nscl.getChannel().replaceAll("_", "").trim();
    sac.khole = nscl.getLocation().replaceAll("_", "").trim();

    logger.finer(
        "Sac stla="
            + sac.stla
            + " stlo="
            + sac.stlo
            + " stel="
            + sac.stel
            + " cmpaz="
            + sac.cmpaz
            + " cmpinc="
            + sac.cmpinc
            + " stdp="
            + sac.stdp);
    sac.y = new double[span.getNsamp()]; // allocate space for data
    int nodata = 0;
    for (int i = 0; i < span.getNsamp(); i++) {
      sac.y[i] = span.getData(i);
      if (sac.y[i] == fill) {
        nodata++;
        // if(nodata <3) logger.finest(i+" nodata len="+span.getNsamp());
      }
    }
    if (nodata > 0) {
      logger.finest("#No data points = " + nodata + " fill=" + fill + " npts=" + sac.npts);
    }
    if (trim) {
      int trimmed = sac.trimNodataEnd(fill);
      if (trimmed > 0) {
        logger.info(trimmed + " data points trimmed from end containing no data");
      }
    }

    if (metaDataServer != null) {
      MetaDataQuery mdq = new MetaDataQuery(metaDataServer);
      ChannelMetaData md = mdq.getChannelMetaData(nscl, begin);
      sac = SacHeaders.setChannelHeader(sac, md);
    }

    return sac;
  }