Example usage for com.google.common.collect Range lowerEndpoint

List of usage examples for com.google.common.collect Range lowerEndpoint

Introduction

In this page you can find the example usage for com.google.common.collect Range lowerEndpoint.

Prototype

public C lowerEndpoint() 

Source Link

Document

Returns the lower endpoint of this range.

Usage

From source file:it.units.malelab.ege.util.Utils.java

public static List<Range<Integer>> slices(Range<Integer> range, List<Integer> sizes) {
    int length = range.upperEndpoint() - range.lowerEndpoint();
    int sumOfSizes = 0;
    for (int size : sizes) {
        sumOfSizes = sumOfSizes + size;//from w w w. j a  v a2  s  . com
    }
    if (sumOfSizes > length) {
        List<Integer> originalSizes = new ArrayList<>(sizes);
        sizes = new ArrayList<>(sizes.size());
        int oldSumOfSizes = sumOfSizes;
        sumOfSizes = 0;
        for (int originalSize : originalSizes) {
            int newSize = (int) Math.round((double) originalSize / (double) oldSumOfSizes);
            sizes.add(newSize);
            sumOfSizes = sumOfSizes + newSize;
        }
    }
    int minSize = (int) Math.floor((double) length / (double) sumOfSizes);
    int missing = length - minSize * sumOfSizes;
    int[] rangeSize = new int[sizes.size()];
    for (int i = 0; i < rangeSize.length; i++) {
        rangeSize[i] = minSize * sizes.get(i);
    }
    int c = 0;
    while (missing > 0) {
        rangeSize[c % rangeSize.length] = rangeSize[c % rangeSize.length] + 1;
        c = c + 1;
        missing = missing - 1;
    }
    List<Range<Integer>> ranges = new ArrayList<>(sizes.size());
    int offset = range.lowerEndpoint();
    for (int i = 0; i < rangeSize.length; i++) {
        ranges.add(Range.closedOpen(offset, offset + rangeSize[i]));
        offset = offset + rangeSize[i];
    }
    return ranges;
}

From source file:com.github.rinde.opt.localsearch.Swaps.java

static <C, T> Iterator<Swap<T>> oneItemSwapIterator(Schedule<C, T> schedule, IntList startIndices, T item,
        int fromRow) {
    final IntList indices = indices(schedule.routes.get(fromRow), item);
    final ImmutableList.Builder<Iterator<Swap<T>>> iteratorBuilder = ImmutableList.builder();

    Range<Integer> range;
    if (indices.size() == 1) {
        range = Range.closedOpen(fromRow, fromRow + 1);
    } else {//w  ww . j  a v  a  2 s. c  om
        range = Range.closedOpen(0, schedule.routes.size());
    }

    for (int i = range.lowerEndpoint(); i < range.upperEndpoint(); i++) {
        int rowSize = schedule.routes.get(i).size();
        if (fromRow == i) {
            rowSize -= indices.size();
        }
        Iterator<IntList> it = new InsertionIndexGenerator(indices.size(), rowSize, startIndices.getInt(i));
        // filter out swaps that have existing result
        if (fromRow == i) {
            it = Iterators.filter(it, Predicates.not(Predicates.equalTo(indices)));
        }
        iteratorBuilder.add(Iterators.transform(it, new IndexToSwapTransform<T>(item, fromRow, i)));
    }
    return Iterators.concat(iteratorBuilder.build().iterator());
}

From source file:org.apache.kylin.common.util.RangeUtil.java

/**
 * for NavigableMap sorted by C, given a range of C, return the sub map whose key falls in the range
 *//* www. j  a va 2s  .  c  o m*/
public static <C extends Comparable<?>, V> NavigableMap<C, V> filter(NavigableMap<C, V> values,
        Range<C> filterRange) {
    if (filterRange == null || filterRange.isEmpty()) {
        return Maps.newTreeMap();
    } else if (filterRange.equals(Range.all())) {
        return values;
    }

    if (filterRange.hasUpperBound() && !filterRange.hasLowerBound()) {
        return values.headMap(filterRange.upperEndpoint(), upperBoundInclusive(filterRange));
    } else if (filterRange.hasLowerBound() && !filterRange.hasUpperBound()) {
        return values.tailMap(filterRange.lowerEndpoint(), lowerBoundInclusive(filterRange));
    } else {
        return values.subMap(filterRange.lowerEndpoint(), lowerBoundInclusive(filterRange), //
                filterRange.upperEndpoint(), upperBoundInclusive(filterRange));
    }
}

From source file:org.pshdl.model.simulation.HDLSimulator.java

private static HDLRange createRange(Range<BigInteger> newRange) {
    if (newRange.lowerEndpoint().equals(newRange.upperEndpoint()))
        return new HDLRange().setTo(HDLLiteral.get(newRange.upperEndpoint()));
    return new HDLRange().setTo(HDLLiteral.get(newRange.lowerEndpoint()))
            .setFrom(HDLLiteral.get(newRange.upperEndpoint()));
}

From source file:eu.itesla_project.modules.histo.HistoDbUtil.java

public static void fixVoltageLimits(Network network, HistoDbClient histoDbClient, Interval interval)
        throws IOException, InterruptedException {
    // resize voltage limits with historical data
    Set<HistoDbAttributeId> attributeIds = new LinkedHashSet<>();
    for (VoltageLevel vl : network.getVoltageLevels()) {
        attributeIds.add(createVoltageAttributeId(vl));
    }// w w w  .ja  v  a  2s . co  m
    HistoDbStats stats = histoDbClient.queryStats(attributeIds, interval, HistoDbHorizon.SN, true);
    for (VoltageLevel vl : network.getVoltageLevels()) {
        HistoDbNetworkAttributeId attributeId = createVoltageAttributeId(vl);

        Range<Float> histoVoltageRangePu = Range.closed(
                stats.getValue(HistoDbStatsType.P0_1, attributeId, Float.NaN) / vl.getNominalV(),
                stats.getValue(HistoDbStatsType.P99_9, attributeId, Float.NaN) / vl.getNominalV());

        Set<EnergySource> energySources = EnumSet.noneOf(EnergySource.class);
        for (Generator g : vl.getGenerators()) {
            energySources.add(g.getEnergySource());
        }

        Range<Float> networkVoltageRangePu = Float.isNaN(vl.getLowVoltageLimit())
                || Float.isNaN(vl.getHighVoltageLimit()) ? Range.closed(Float.NaN, Float.NaN)
                        : Range.closed(vl.getLowVoltageLimit() / vl.getNominalV(),
                                vl.getHighVoltageLimit() / vl.getNominalV());

        LOGGER.trace("Fix voltage range of {}: histo={}, network={}, energySources={}", vl.getId(),
                histoVoltageRangePu, networkVoltageRangePu, energySources);

        Range<Float> rangeToEnclosePu;
        if (energySources.isEmpty()) {
            rangeToEnclosePu = Range.closed(
                    Float.isNaN(networkVoltageRangePu.lowerEndpoint()) ? VOLTAGE_RANGE_NO_GEN.lowerEndpoint()
                            : networkVoltageRangePu.lowerEndpoint(),
                    Float.isNaN(networkVoltageRangePu.upperEndpoint()) ? VOLTAGE_RANGE_NO_GEN.upperEndpoint()
                            : networkVoltageRangePu.upperEndpoint());
        } else {
            if (energySources.contains(EnergySource.NUCLEAR) || energySources.contains(EnergySource.THERMAL)) {
                rangeToEnclosePu = VOLTAGE_RANGE_NUCL_THE_PU;
            } else if (energySources.contains(EnergySource.HYDRO)) {
                rangeToEnclosePu = VOLTAGE_RANGE_HYD_PU;
            } else if (energySources.contains(EnergySource.SOLAR) || energySources.contains(EnergySource.WIND)
                    || energySources.contains(EnergySource.OTHER)) {
                rangeToEnclosePu = VOLTAGE_RANGE_DEFAULT_GEN_PU;
            } else {
                throw new AssertionError();
            }
        }
        Range<Float> rangePu = span(histoVoltageRangePu, rangeToEnclosePu);
        Range<Float> range = Range.closed(rangePu.lowerEndpoint() * vl.getNominalV(),
                rangePu.upperEndpoint() * vl.getNominalV());

        LOGGER.debug("Voltage range of {}: {} Kv ({} pu)", vl.getId(), range, rangePu);

        // check that we have 0.1pu at least for each of the substation
        //            if (rangePu.upperEndpoint() - rangePu.lowerEndpoint() < 0.1) {
        //                throw new RuntimeException("Too tight voltage range " + rangePu  + " for voltage level " + vl.getId() + " " + rangeToEnclosePu);
        //            }

        vl.setLowVoltageLimit(range.lowerEndpoint()).setHighVoltageLimit(range.upperEndpoint());
    }
}

From source file:org.pshdl.model.simulation.HDLSimulator.java

private static HDLUnit createBitRanges(HDLEvaluationContext context, HDLUnit insulin) {
    final HDLVariableRef[] refs = insulin.getAllObjectsOf(HDLVariableRef.class, true);
    final Map<HDLQualifiedName, List<RangeVal>> ranges = new LinkedHashMap<HDLQualifiedName, List<RangeVal>>();
    final Map<HDLQualifiedName, Range<BigInteger>> fullRanges = new LinkedHashMap<HDLQualifiedName, Range<BigInteger>>();
    for (final HDLVariableRef ref : refs)
        if (ref.getContainer() instanceof HDLAssignment) {
            final HDLAssignment ass = (HDLAssignment) ref.getContainer();
            if (ass.getLeft() == ref) {
                final Optional<HDLVariable> resolved = ref.resolveVar();
                if (!resolved.isPresent())
                    throw new IllegalArgumentException("Can not resolve:" + ref.getVarRefName());
                final HDLVariable resolveVar = resolved.get();
                if (resolveVar.getDirection() != HDLDirection.IN) {
                    final HDLQualifiedName varRefName = ref.getVarRefName();
                    if (ref.getBits().size() > 0) {
                        List<RangeVal> set = ranges.get(varRefName);
                        if (set == null) {
                            set = new LinkedList<RangeVal>();
                            ranges.put(varRefName, set);
                        }/*from   w  ww.  ja  va2 s .c o m*/
                        for (final HDLRange r : ref.getBits()) {
                            final Optional<Range<BigInteger>> determineRange = RangeExtension.rangeOf(r,
                                    context);
                            if (!determineRange.isPresent())
                                throw new IllegalArgumentException("Can not determine Range for:" + r);
                            set.add(new RangeVal(determineRange.get().lowerEndpoint(), 1));
                            set.add(new RangeVal(determineRange.get().upperEndpoint(), -1));
                        }
                    } else {
                        final HDLExpression width = TypeExtension.getWidth(resolveVar);
                        if (width != null) {
                            final Optional<BigInteger> bWidth = ConstantEvaluate.valueOf(width, context);
                            if (!bWidth.isPresent())
                                throw new IllegalArgumentException("Given the context this should be constant");
                            fullRanges.put(varRefName, RangeTool.createRange(BigInteger.ZERO,
                                    bWidth.get().subtract(BigInteger.ONE)));
                        }
                    }
                }
            }
        }
    final ModificationSet ms = new ModificationSet();
    final Map<HDLQualifiedName, SortedSet<Range<BigInteger>>> splitRanges = new LinkedHashMap<HDLQualifiedName, SortedSet<Range<BigInteger>>>();
    for (final Map.Entry<HDLQualifiedName, List<RangeVal>> entry : ranges.entrySet()) {
        final List<RangeVal> value = entry.getValue();
        final HDLQualifiedName varName = entry.getKey();
        if (fullRanges.containsKey(varName)) {
            final Range<BigInteger> fullWidth = fullRanges.get(varName);
            value.add(new RangeVal(fullWidth.lowerEndpoint(), 1));
            value.add(new RangeVal(fullWidth.upperEndpoint(), -1));
        }
        final SortedSet<Range<BigInteger>> split = RangeTool.split(value);
        splitRanges.put(varName, split);
    }
    // Change bit access to broken down ranges
    for (final HDLVariableRef ref : refs) {
        final SortedSet<Range<BigInteger>> list = splitRanges.get(ref.getVarRefName());
        if (list != null) {
            final ArrayList<HDLRange> newRanges = new ArrayList<HDLRange>();
            if (!ref.getBits().isEmpty()) {
                for (final HDLRange bit : ref.getBits())
                    if (bit.getFrom() != null) { // Singular ranges don't do
                        // anything
                        final Optional<Range<BigInteger>> range = RangeExtension.rangeOf(bit, context);
                        if (!range.isPresent())
                            throw new IllegalArgumentException("Can not determine Range of:" + bit);
                        for (final Range<BigInteger> newRange : list)
                            if (range.get().isConnected(newRange)) {
                                newRanges.add(0, createRange(newRange));
                            }
                    } else {
                        newRanges.add(0, bit);
                    }
            } else {
                for (final Range<BigInteger> vRange : list) {
                    newRanges.add(0, createRange(vRange));
                }
            }
            if (newRanges.size() != 0) {
                ms.replace(ref, ref.setBits(newRanges));
            }
        }
    }
    final HDLUnit apply = ms.apply(insulin);
    return Insulin.handleMultiBitAccess(apply, context);
}

From source file:annis.visualizers.component.grid.EventExtractor.java

public static void removeEmptySpace(LinkedHashMap<String, ArrayList<Row>> rowsByAnnotation, Row tokenRow) {
    List<Range<Integer>> gaps = new LinkedList<>();

    BitSet totalOccupancyGrid = new BitSet();
    for (Map.Entry<String, ArrayList<Row>> layer : rowsByAnnotation.entrySet()) {
        for (Row r : layer.getValue()) {
            totalOccupancyGrid.or(r.getOccupancyGridCopy());
        }/*from   w  ww  .java  2 s  . c  o  m*/
    }
    // We always include the token row in the occupancy grid since it is not
    // a gap. Otherwise empty token would trigger gaps if the token list
    // is included in the visualizer output.
    // See https://github.com/korpling/ANNIS/issues/281 for the corresponding
    // bug report.
    if (tokenRow != null) {
        totalOccupancyGrid.or(tokenRow.getOccupancyGridCopy());
    }

    // The Range class can give us the next bit that is not set. Use this
    // to detect gaps. A gap starts from the next non-set bit and goes to
    // the next set bit.
    Range<Integer> gap = Range.closed(-1, totalOccupancyGrid.nextSetBit(0));
    while (true) {
        int gapStart = totalOccupancyGrid.nextClearBit(gap.upperEndpoint() + 1);
        int gapEnd = totalOccupancyGrid.nextSetBit(gapStart);
        if (gapEnd <= 0) {
            break;
        }
        gap = Range.closed(gapStart, gapEnd - 1);
        gaps.add(gap);

    }

    int gapID = 0;
    int totalOffset = 0;
    for (Range<Integer> gRaw : gaps) {
        // adjust the space range itself
        Range<Integer> g = Range.closed(gRaw.lowerEndpoint() - totalOffset, gRaw.upperEndpoint() - totalOffset);
        int offset = g.upperEndpoint() - g.lowerEndpoint();
        totalOffset += offset;

        for (Entry<String, ArrayList<Row>> rowEntry : rowsByAnnotation.entrySet()) {
            ArrayList<Row> rows = rowEntry.getValue();
            for (Row r : rows) {
                List<GridEvent> eventsCopy = new LinkedList<>(r.getEvents());
                for (GridEvent e : eventsCopy) {
                    if (e.getLeft() >= g.upperEndpoint()) {

                        r.removeEvent(e);
                        e.setLeft(e.getLeft() - offset);
                        e.setRight(e.getRight() - offset);
                        r.addEvent(e);
                    }
                }

                // add a special space event
                String spaceCaption = "";
                if ("tok".equalsIgnoreCase(rowEntry.getKey())) {
                    spaceCaption = "(...)";
                }
                GridEvent spaceEvent = new GridEvent("gap-" + gapID, g.lowerEndpoint(), g.lowerEndpoint(),
                        spaceCaption);
                spaceEvent.setSpace(true);
                r.addEvent(spaceEvent);
                gapID++;
            }
        }
    }
}

From source file:net.sf.mzmine.util.ScanUtils.java

/**
 * This method bins values on x-axis. Each bin is assigned biggest y-value
 * of all values in the same bin./*from  www .  j  ava 2  s . c o m*/
 * 
 * @param x
 *            X-coordinates of the data
 * @param y
 *            Y-coordinates of the data
 * @param firstBinStart
 *            Value at the "left"-edge of the first bin
 * @param lastBinStop
 *            Value at the "right"-edge of the last bin
 * @param numberOfBins
 *            Number of bins
 * @param interpolate
 *            If true, then empty bins will be filled with interpolation
 *            using other bins
 * @param binningType
 *            Type of binning (sum of all 'y' within a bin, max of 'y', min
 *            of 'y', avg of 'y')
 * @return Values for each bin
 */
public static double[] binValues(double[] x, double[] y, Range<Double> binRange, int numberOfBins,
        boolean interpolate, BinningType binningType) {

    Double[] binValues = new Double[numberOfBins];
    double binWidth = (binRange.upperEndpoint() - binRange.lowerEndpoint()) / numberOfBins;

    double beforeX = Double.MIN_VALUE;
    double beforeY = 0.0f;
    double afterX = Double.MAX_VALUE;
    double afterY = 0.0f;

    double[] noOfEntries = null;

    // Binnings
    for (int valueIndex = 0; valueIndex < x.length; valueIndex++) {

        // Before first bin?
        if ((x[valueIndex] - binRange.lowerEndpoint()) < 0) {
            if (x[valueIndex] > beforeX) {
                beforeX = x[valueIndex];
                beforeY = y[valueIndex];
            }
            continue;
        }

        // After last bin?
        if ((binRange.upperEndpoint() - x[valueIndex]) < 0) {
            if (x[valueIndex] < afterX) {
                afterX = x[valueIndex];
                afterY = y[valueIndex];
            }
            continue;
        }

        int binIndex = (int) ((x[valueIndex] - binRange.lowerEndpoint()) / binWidth);

        // in case x[valueIndex] is exactly lastBinStop, we would overflow
        // the array
        if (binIndex == binValues.length)
            binIndex--;

        switch (binningType) {
        case MAX:
            if (binValues[binIndex] == null) {
                binValues[binIndex] = y[valueIndex];
            } else {
                if (binValues[binIndex] < y[valueIndex]) {
                    binValues[binIndex] = y[valueIndex];
                }
            }
            break;
        case MIN:
            if (binValues[binIndex] == null) {
                binValues[binIndex] = y[valueIndex];
            } else {
                if (binValues[binIndex] > y[valueIndex]) {
                    binValues[binIndex] = y[valueIndex];
                }
            }
            break;
        case AVG:
            if (noOfEntries == null) {
                noOfEntries = new double[binValues.length];
            }
            if (binValues[binIndex] == null) {
                noOfEntries[binIndex] = 1;
                binValues[binIndex] = y[valueIndex];
            } else {
                noOfEntries[binIndex]++;
                binValues[binIndex] += y[valueIndex];
            }
            break;

        case SUM:
        default:
            if (binValues[binIndex] == null) {
                binValues[binIndex] = y[valueIndex];
            } else {
                binValues[binIndex] += y[valueIndex];
            }
            break;

        }

    }

    // calculate the AVG
    if (binningType.equals(BinningType.AVG)) {
        assert noOfEntries != null;
        for (int binIndex = 0; binIndex < binValues.length; binIndex++) {
            if (binValues[binIndex] != null) {
                binValues[binIndex] /= noOfEntries[binIndex];
            }
        }
    }

    // Interpolation
    if (interpolate) {

        for (int binIndex = 0; binIndex < binValues.length; binIndex++) {
            if (binValues[binIndex] == null) {

                // Find exisiting left neighbour
                double leftNeighbourValue = beforeY;
                int leftNeighbourBinIndex = (int) Math.floor((beforeX - binRange.lowerEndpoint()) / binWidth);
                for (int anotherBinIndex = binIndex - 1; anotherBinIndex >= 0; anotherBinIndex--) {
                    if (binValues[anotherBinIndex] != null) {
                        leftNeighbourValue = binValues[anotherBinIndex];
                        leftNeighbourBinIndex = anotherBinIndex;
                        break;
                    }
                }

                // Find existing right neighbour
                double rightNeighbourValue = afterY;
                int rightNeighbourBinIndex = (binValues.length - 1)
                        + (int) Math.ceil((afterX - binRange.upperEndpoint()) / binWidth);
                for (int anotherBinIndex = binIndex
                        + 1; anotherBinIndex < binValues.length; anotherBinIndex++) {
                    if (binValues[anotherBinIndex] != null) {
                        rightNeighbourValue = binValues[anotherBinIndex];
                        rightNeighbourBinIndex = anotherBinIndex;
                        break;
                    }
                }

                double slope = (rightNeighbourValue - leftNeighbourValue)
                        / (rightNeighbourBinIndex - leftNeighbourBinIndex);
                binValues[binIndex] = new Double(
                        leftNeighbourValue + slope * (binIndex - leftNeighbourBinIndex));

            }

        }

    }

    double[] res = new double[binValues.length];
    for (int binIndex = 0; binIndex < binValues.length; binIndex++) {
        res[binIndex] = binValues[binIndex] == null ? 0 : binValues[binIndex];
    }
    return res;

}

From source file:dollar.api.types.DollarFactory.java

/**
 * To json./*from  www .  j a v a2 s . c om*/
 *
 * @param value the value
 * @return the object
 */
@Nullable
public static Object toJson(@NotNull Value value) {
    Type i = value.$type();
    if (i.is(Type._VOID) || i.is(Type._INTEGER) || i.is(Type._BOOLEAN) || i.is(Type._DECIMAL)
            || i.is(Type._STRING)) {
        return value.toJavaObject();
    } else if (i.is(Type._DATE)) {
        final JsonObject jsonObject = new JsonObject();
        jsonObject.putString(TYPE_KEY, value.$type().name());
        jsonObject.putString(TEXT_KEY, value.$S());
        jsonObject.putNumber(MILLISECOND_KEY, (long) (value.toDouble() * 24 * 60 * 60 * 1000));
        return jsonObject;
    } else if (i.is(Type._URI)) {
        final JsonObject uriJsonObject = new JsonObject();
        uriJsonObject.putString(TYPE_KEY, value.$type().name());
        uriJsonObject.putString(VALUE_KEY, value.$S());
        return uriJsonObject;
    } else if (i.is(Type._ERROR)) {
        final JsonObject errorJsonObject = new JsonObject();
        errorJsonObject.putString(TYPE_KEY, value.$type().name());
        errorJsonObject.putValue(VALUE_KEY, value.toJsonType());
        return errorJsonObject;
    } else if (i.is(Type._INFINITY)) {
        final JsonObject infinityJsonObject = new JsonObject();
        infinityJsonObject.putString(TYPE_KEY, value.$type().name());
        infinityJsonObject.putValue(POSITIVE_KEY, value.positive());
        return infinityJsonObject;
    } else if (i.is(Type._LIST) || i.is(Type._QUEUE)) {
        final JsonArray array = new JsonArray();
        ImmutableList<Value> arrayList = value.toVarList();
        for (Value v : arrayList) {
            array.add(toJson(v));
        }

        return array;
    } else if (i.is(Type._MAP)) {
        return mapToJsonInternal(value);
    } else if (i.is(Type._RANGE)) {
        final JsonObject rangeObject = new JsonObject();
        rangeObject.putString(TYPE_KEY, value.$type().name());
        final Range<Value> range = value.toJavaObject();
        rangeObject.putValue(LOWERBOUND_KEY, toJson(range.lowerEndpoint()));
        rangeObject.putValue(UPPERBOUND_KEY, toJson(range.upperEndpoint()));
        return rangeObject;
    } else if (i.is(Type._ANY)) {
        return null;
    } else {
        return mapToJsonInternal(value);
    }
}

From source file:net.sf.mzmine.modules.visualization.peaklisttable.PeakListTablePopupMenu.java

/**
 * Get a peak's m/z range.// w w w.j  a v a2 s .co m
 * 
 * @param peak
 *            the peak.
 * @return The peak's m/z range.
 */
private static Range<Double> getPeakMZRange(final Feature peak) {

    final Range<Double> peakMZRange = peak.getRawDataPointsMZRange();

    // By default, open the visualizer with the m/z range of
    // "peak_width x 2", but no smaller than 0.1 m/z, because with smaller
    // ranges VisAD tends to show nasty anti-aliasing artifacts.
    // For example of such artifacts, set mzMin = 440.27, mzMax = 440.28 and
    // mzResolution = 500
    final double minRangeCenter = (peakMZRange.upperEndpoint() + peakMZRange.lowerEndpoint()) / 2.0;
    final double minRangeWidth = Math.max(0.1, (peakMZRange.upperEndpoint() - peakMZRange.lowerEndpoint()) * 2);
    double mzMin = minRangeCenter - (minRangeWidth / 2);
    if (mzMin < 0)
        mzMin = 0;
    double mzMax = minRangeCenter + (minRangeWidth / 2);
    return Range.closed(mzMin, mzMax);
}