public static Range computeScale(List<Range> ranges) {

    float min = 0;
    float max = 0;

    if (ranges.size() > 0) {
      max = ranges.get(0).max;
      min = ranges.get(0).min;

      for (int i = 1; i < ranges.size(); i++) {

        Range r = ranges.get(i);
        max = Math.max(r.max, max);
        min = Math.min(r.min, min);
      }
    }

    return new Range(min, max);
  }
  private void autoscaleGroup(List<Track> trackList) {

    List<ReferenceFrame> frames =
        FrameManager.isGeneListMode()
            ? FrameManager.getFrames()
            : Arrays.asList(FrameManager.getDefaultFrame());

    List<Range> inViewRanges = new ArrayList<Range>();

    synchronized (trackList) {
      for (Track track : trackList) {
        if (track instanceof ScalableTrack) {
          for (ReferenceFrame frame : frames) {
            Range range = ((ScalableTrack) track).getInViewRange(frame);
            if (range != null) {
              inViewRanges.add(range);
            }
          }
        }
      }

      if (inViewRanges.size() > 0) {

        Range inter = computeScale(inViewRanges);

        for (Track track : trackList) {

          DataRange dr = track.getDataRange();
          float min = Math.min(0, inter.min);
          float base = Math.max(min, dr.getBaseline());
          float max = inter.max;
          // Pathological case where min ~= max  (no data in view)
          if (max - min <= (2 * Float.MIN_VALUE)) {
            max = min + 1;
          }

          DataRange newDR = new DataRange(min, base, max, dr.isDrawBaseline());
          newDR.setType(dr.getType());
          track.setDataRange(newDR);
        }
      }
    }
  }