com.google.common.collect.Range#contains ( )源码实例Demo

下面列出了com.google.common.collect.Range#contains ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: Bats   文件: DateRangeRules.java
private boolean next(Calendar c, TimeUnitRange timeUnit, int v, Range<Calendar> r, boolean strict) {
    final Calendar original = (Calendar) c.clone();
    final int code = TIME_UNIT_CODES.get(timeUnit);
    for (;;) {
        c.set(code, v);
        int v2 = c.get(code);
        if (v2 < v) {
            // E.g. when we set DAY=30 on 2014-02-01, we get 2014-02-30 because
            // February has 28 days.
            continue;
        }
        if (strict && original.compareTo(c) == 0) {
            c.add(TIME_UNIT_CODES.get(TIME_UNIT_PARENTS.get(timeUnit)), 1);
            continue;
        }
        if (!r.contains(c)) {
            return false;
        }
        return true;
    }
}
 
源代码2 项目: PGM   文件: TextParser.java
/**
 * Parses text into an integer.
 *
 * <p>Accepts infinity as "+oo" or "-oo".
 *
 * @param text The text.
 * @param range A range of acceptable integers.
 * @return An integer.
 * @throws TextException If the text is invalid or out of range.
 */
public static int parseInteger(String text, Range<Integer> range) throws TextException {
  checkNotNull(text, "cannot parse integer from null");

  final int number;
  if (INF.matcher(text).matches()) {
    number = text.startsWith("-") ? Integer.MIN_VALUE : Integer.MAX_VALUE;
  } else {
    try {
      number = Integer.parseInt(text, 10); // Base 10
    } catch (NumberFormatException e) {
      throw invalidFormat(text, int.class, e);
    }
  }

  if (range != null && !range.contains(number)) {
    throw outOfRange(text, range);
  }

  return number;
}
 
源代码3 项目: mzmine3   文件: LipidSearchTask.java
private void searchModifications(PeakListRow rows, double lipidIonMass, LipidIdentity lipid,
    double[] lipidModificationMasses, Range<Double> mzTolModification) {
  for (int j = 0; j < lipidModificationMasses.length; j++) {
    if (mzTolModification.contains(lipidIonMass + (lipidModificationMasses[j]))) {
      // Calc relativ mass deviation
      double relMassDev = ((lipidIonMass + (lipidModificationMasses[j]) - rows.getAverageMZ())
          / (lipidIonMass + lipidModificationMasses[j])) * 1000000;
      // Add row identity
      rows.addPeakIdentity(new SimplePeakIdentity(lipid + " " + lipidModification[j]), false);
      rows.setComment("Ionization: " + ionizationType.getAdduct() + " " + lipidModification[j]
          + ", Δ " + NumberFormat.getInstance().format(relMassDev) + " ppm");
      logger.info("Found modified lipid: " + lipid.getName() + " " + lipidModification[j] + ", Δ "
          + NumberFormat.getInstance().format(relMassDev) + " ppm");
    }
  }
}
 
源代码4 项目: mzmine3   文件: ComplexSearchTask.java
/**
 * Check if candidate peak may be a possible complex of given two peaks
 *
 */
private boolean checkComplex(PeakListRow complexRow, PeakListRow row1, PeakListRow row2) {

  // Check retention time condition
  Range<Double> rtRange = rtTolerance.getToleranceRange(complexRow.getAverageRT());
  if (!rtRange.contains(row1.getAverageRT()))
    return false;
  if (!rtRange.contains(row2.getAverageRT()))
    return false;

  // Check mass condition
  double expectedMass = row1.getAverageMZ() + row2.getAverageMZ() - (2 * ionType.getAddedMass());
  double detectedMass = complexRow.getAverageMZ() - ionType.getAddedMass();
  Range<Double> mzRange = mzTolerance.getToleranceRange(detectedMass);
  if (!mzRange.contains(expectedMass))
    return false;

  // Check height condition
  if ((complexRow.getAverageHeight() > row1.getAverageHeight() * maxComplexHeight)
      || (complexRow.getAverageHeight() > row2.getAverageHeight() * maxComplexHeight))
    return false;

  return true;

}
 
源代码5 项目: ProjectAres   文件: FeatureParser.java
public List<T> parseChildList(Element parent, Range<Integer> count) throws InvalidXMLException {
    final List<T> list = parseChildren(parent).collect(Collectors.toList());
    if(count.contains(list.size())) return list;

    final Optional<Integer> min = Ranges.minimum(count), max = Ranges.maximum(count);

    if(!max.isPresent()) {
        throw new InvalidXMLException("Expected " + min.get() + " or more child elements", parent);
    } else if(!min.isPresent()) {
        throw new InvalidXMLException("Expected no more than " + max.get() + " child elements", parent);
    } else if(min.equals(max)) {
        throw new InvalidXMLException("Expected exactly " + min.get() + " child elements", parent);
    } else {
        throw new InvalidXMLException("Expected between " + min.get() + " and " + max.get() + " child elements", parent);
    }
}
 
源代码6 项目: onos   文件: RoadmPortViewMessageHandler.java
@Override
public void process(ObjectNode payload) {
    DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
    PortNumber portNumber = PortNumber.portNumber(payload.get(ID).asLong());
    Range<Double> range = roadmService.targetPortPowerRange(deviceId, portNumber);
    if (range == null) {
        log.warn("Unable to determine target power range for device {}", deviceId);
        return;
    }
    Double targetPower = payload.get(TARGET_POWER).asDouble();
    boolean validTargetPower = range.contains(targetPower);
    if (validTargetPower) {
        roadmService.setTargetPortPower(deviceId, portNumber, targetPower);
    }
    ObjectNode rootNode = objectNode();
    rootNode.put(ID, payload.get(ID).asText());
    rootNode.put(RoadmUtil.VALID, validTargetPower);
    rootNode.put(RoadmUtil.MESSAGE, String.format(TARGET_POWER_ERR_MSG, range.toString()));
    sendMessage(ROADM_SET_TARGET_POWER_RESP, rootNode);
}
 
源代码7 项目: ProjectAres   文件: FilterDefinitionParser.java
@MethodParser("random")
public Filter parseRandom(Element el) throws InvalidXMLException {
    Node node = new Node(el);
    Range<Double> chance;
    try {
        chance = Range.closedOpen(0d, XMLUtils.parseNumber(node, Double.class));
    } catch(InvalidXMLException e) {
        chance = XMLUtils.parseNumericRange(node, Double.class);
    }

    Range<Double> valid = Range.closed(0d, 1d);
    if (valid.encloses(chance)) {
        return proto.isNoOlderThan(ProtoVersions.EVENT_QUERIES) ? new RandomFilter(chance)
                                                                : new LegacyRandomFilter(chance);
    } else {
        double lower = chance.hasLowerBound() ? chance.lowerEndpoint() : Double.NEGATIVE_INFINITY;
        double upper = chance.hasUpperBound() ? chance.upperEndpoint() : Double.POSITIVE_INFINITY;
        double invalid;
        if(!valid.contains(lower)) {
            invalid = lower;
        } else {
            invalid = upper;
        }

        throw new InvalidXMLException("chance value (" + invalid + ") is not between 0 and 1", el);
    }
}
 
源代码8 项目: PGM   文件: TextParser.java
/**
 * Parses text into an enum.
 *
 * @param text The text.
 * @param type The enum class.
 * @param range A range of acceptable enums.
 * @param fuzzyMatch Whether non-exact matches can be returned.
 * @param <E> The enum type.
 * @return An enum.
 * @throws TextException If the text is invalid or out of range.
 */
public static <E extends Enum<E>> E parseEnum(
    String text, Class<E> type, Range<E> range, boolean fuzzyMatch) throws TextException {
  checkNotNull(text, "cannot parse enum " + type.getSimpleName().toLowerCase() + "  from null");

  double maxScore = 0;
  E value = null;

  for (E each : type.getEnumConstants()) {
    final double score = LiquidMetal.score(each.name(), text.replace(' ', '_'));
    if (score >= maxScore) {
      maxScore = score;
      value = each;
    }
    if (score >= 1) break;
  }

  if (maxScore < 0.25 || (!fuzzyMatch && maxScore < 1)) {
    throw invalidFormat(text, type, value.name().toLowerCase(), null);
  }

  if (range != null && !range.contains(value)) {
    throw outOfRange(text, range);
  }

  return value;
}
 
源代码9 项目: mzmine3   文件: ProductIonFilterDataSet.java
public void updateOnRangeDataPoints(String rangeType) {

    ProductIonFilterPlot plot = visualizer.getPlot();
    Range<Double> prRange = plot.getHighlightedPrecursorRange();
    Range<Double> nlRange = plot.getHighlightedNeutralLossRange();

    // Set type of search
    int level = NEUTRALLOSS_LEVEL;
    if (rangeType.equals("HIGHLIGHT_PRECURSOR")) {
      level = PRECURSOR_LEVEL;
    }

    // Clean previous selection
    dataSeries.get(level).clear();

    ProductIonFilterDataPoint point;
    boolean b = false;
    for (int i = 0; i < dataSeries.get(RAW_LEVEL).size(); i++) {
      point = dataSeries.get(RAW_LEVEL).get(i);
      // Verify if the point is on range
      if (level == PRECURSOR_LEVEL) {
        b = prRange.contains(point.getPrecursorMass());
      } else {
        b = nlRange.contains(point.getProductMZ());
      }
      if (b) {
        dataSeries.get(level).add(point);
      }
    }

    refresh();
  }
 
private String findPossibleLipid(LipidIdentity lipid, double searchedMass) {
  String lipidAnnoation = "";
  double lipidIonMass = 0.0;
  double lipidMass = lipid.getMass();
  lipidIonMass = lipidMass + ionizationType.getAddedMass();
  logger.info("Searching for lipid " + lipid.getDescription() + ", " + lipidIonMass + " m/z");
  Range<Double> mzTolRange12C = mzTolerance.getToleranceRange(searchedMass);
  if (mzTolRange12C.contains(lipidIonMass)) {
    // Calc rel mass deviation;
    double relMassDev = ((lipidIonMass - searchedMass) / lipidIonMass) * 1000000;
    lipidAnnoation = lipid.getName() + ionizationType.getAdduct() + ", Δ "
        + NumberFormat.getInstance().format(relMassDev) + " ppm"; // Format relativ mass
  }
  return lipidAnnoation;
}
 
源代码11 项目: mzmine2   文件: MsMsDataSet.java
public Number getMaxZ(Range<Double> mzRange) {
  double max = 1.0;
  for (int row = 0; row < totalmsmsScans; row++) {
    if (mzRange.contains(mzValues[row])) {
      if (max < intensityValues[row]) {
        max = intensityValues[row];
      }
    }
  }
  return max;
}
 
源代码12 项目: mzmine3   文件: ScanUtils.java
/**
 * Returns the index of the datapoint with largest m/z within the given datapoints which is within
 * the given mass range
 * 
 * @param dataPoints sorted(!) list of datapoints
 * @param mzRange m/z range to search in
 * @return index of datapoint or -1, if no datapoint is in range
 */
public static int findLastPeakWithin(DataPoint[] dataPoints, Range<Double> mzRange) {
  final int insertionPoint =
      Arrays.binarySearch(dataPoints, new SimpleDataPoint(mzRange.upperEndpoint(), 0d),
          (u, v) -> Double.compare(u.getMZ(), v.getMZ()));
  if (insertionPoint < 0) {
    final int k = -insertionPoint - 2;
    if (k >= 0 && mzRange.contains(dataPoints[k].getMZ()))
      return k;
    else
      return -1;
  } else {
    return insertionPoint;
  }
}
 
源代码13 项目: mzmine3   文件: TwoDBottomPanel.java
/**
 * Returns a feature list with the top peaks defined by the parameter "threshold"
 */
PeakList getTopThresholdPeakList(int threshold) {

  PeakList selectedPeakList = peakListSelector.getSelectionModel().getSelectedItem();
  if (selectedPeakList == null)
    return null;
  SimplePeakList newList =
      new SimplePeakList(selectedPeakList.getName(), selectedPeakList.getRawDataFiles());

  Vector<PeakListRow> peakRows = new Vector<PeakListRow>();

  Range<Double> mzRange = selectedPeakList.getRowsMZRange();
  Range<Double> rtRange = selectedPeakList.getRowsRTRange();

  PeakThresholdMode selectedPeakOption = thresholdCombo.getSelectionModel().getSelectedItem();
  if (selectedPeakOption == PeakThresholdMode.TOP_PEAKS_AREA) {
    mzRange = masterFrame.getPlot().getXYPlot().getAxisRange();
    rtRange = masterFrame.getPlot().getXYPlot().getDomainRange();
  }

  for (PeakListRow peakRow : selectedPeakList.getRows()) {
    if (mzRange.contains(peakRow.getAverageMZ()) && rtRange.contains(peakRow.getAverageRT())) {
      peakRows.add(peakRow);
    }
  }

  Collections.sort(peakRows,
      new PeakListRowSorter(SortingProperty.Intensity, SortingDirection.Descending));

  if (threshold > peakRows.size())
    threshold = peakRows.size();
  for (int i = 0; i < threshold; i++) {
    newList.addRow(peakRows.elementAt(i));
  }
  return newList;
}
 
源代码14 项目: attic-aurora   文件: SlaAlgorithm.java
@Override
public Number calculate(Iterable<IScheduledTask> tasks, Range<Long> timeFrame) {
  Iterable<IScheduledTask> activeTasks = FluentIterable.from(tasks)
      .filter(
          Predicates.compose(Predicates.in(Tasks.ACTIVE_STATES), IScheduledTask::getStatus));

  List<Long> waitTimes = Lists.newLinkedList();
  for (IScheduledTask task : activeTasks) {
    long pendingTs = 0;
    for (ITaskEvent event : task.getTaskEvents()) {
      if (event.getStatus() == PENDING) {
        pendingTs = event.getTimestamp();
      } else if (event.getStatus() == status && timeFrame.contains(event.getTimestamp())) {

        if (pendingTs == 0) {
          throw new IllegalArgumentException("SLA: missing PENDING status for:"
              + task.getAssignedTask().getTaskId());
        }

        waitTimes.add(event.getTimestamp() - pendingTs);
        break;
      }
    }
  }

  return SlaUtil.percentile(waitTimes, 50.0);
}
 
源代码15 项目: mzmine2   文件: RTScore.java
public double calculateScore(AlignmentPath path, PeakListRow peak, ParameterSet parameters) {
  try {
    rtTolerance = parameters.getParameter(PathAlignerParameters.RTTolerance).getValue();
    mzTolerance = parameters.getParameter(PathAlignerParameters.MZTolerance).getValue();
    Range<Double> rtRange = rtTolerance.getToleranceRange(path.getRT());
    Range<Double> mzRange = mzTolerance.getToleranceRange(path.getMZ());

    if (!rtRange.contains(peak.getAverageRT()) || !mzRange.contains(peak.getAverageMZ())) {
      return WORST_SCORE;
    }

    double mzDiff = Math.abs(path.getMZ() - peak.getAverageMZ());

    double rtDiff = Math.abs(path.getRT() - peak.getAverageRT());

    double score = ((mzDiff / (RangeUtils.rangeLength(mzRange) / 2.0)))
        + ((rtDiff / (RangeUtils.rangeLength(rtRange) / 2.0)));

    if (parameters.getParameter(PathAlignerParameters.SameChargeRequired).getValue()) {
      if (!PeakUtils.compareChargeState(path.convertToAlignmentRow(0), peak)) {
        return WORST_SCORE;
      }
    }

    if (parameters.getParameter(PathAlignerParameters.SameIDRequired).getValue()) {
      if (!PeakUtils.compareIdentities(path.convertToAlignmentRow(0), peak)) {
        return WORST_SCORE;
      }
    }

    if (parameters.getParameter(PathAlignerParameters.compareIsotopePattern).getValue()) {
      IsotopePattern ip1 = path.convertToAlignmentRow(0).getBestIsotopePattern();
      IsotopePattern ip2 = peak.getBestIsotopePattern();

      if ((ip1 != null) && (ip2 != null)) {
        ParameterSet isotopeParams = parameters
            .getParameter(PathAlignerParameters.compareIsotopePattern).getEmbeddedParameters();

        if (!IsotopePatternScoreCalculator.checkMatch(ip1, ip2, isotopeParams)) {
          return WORST_SCORE;
        }
      }
    }

    return score;
  } catch (NullPointerException e) {
    e.printStackTrace();
    return WORST_SCORE;
  }
}
 
源代码16 项目: nomulus   文件: FormField.java
private void checkRangeContains(Range<Integer> range, int value, String message) {
  if (!range.contains(value)) {
    throw new FormFieldException(
        String.format("%s (%,d) not in range %s", message, value, range));
  }
}
 
源代码17 项目: mzmine3   文件: SavitzkyGolayPeakDetector.java
@Override
public ResolvedPeak[] resolvePeaks(final Feature chromatogram, ParameterSet parameters,
    RSessionWrapper rSession, CenterFunction mzCenterFunction, double msmsRange,
    double rTRangeMSMS) {

  int scanNumbers[] = chromatogram.getScanNumbers();
  final int scanCount = scanNumbers.length;
  double retentionTimes[] = new double[scanCount];
  double intensities[] = new double[scanCount];
  RawDataFile dataFile = chromatogram.getDataFile();
  for (int i = 0; i < scanCount; i++) {
    final int scanNum = scanNumbers[i];
    retentionTimes[i] = dataFile.getScan(scanNum).getRetentionTime();
    DataPoint dp = chromatogram.getDataPoint(scanNum);
    if (dp != null)
      intensities[i] = dp.getIntensity();
    else
      intensities[i] = 0.0;
  }

  // Calculate intensity statistics.
  double maxIntensity = 0.0;
  double avgIntensity = 0.0;
  for (final double intensity : intensities) {

    maxIntensity = Math.max(intensity, maxIntensity);
    avgIntensity += intensity;
  }

  avgIntensity /= scanCount;

  final List<Feature> resolvedPeaks = new ArrayList<Feature>(2);

  // If the current chromatogram has characteristics of background or just
  // noise return an empty array.
  if (avgIntensity <= maxIntensity / 2.0) {

    // Calculate second derivatives of intensity values.
    final double[] secondDerivative =
        SGDerivative.calculateDerivative(intensities, false, SG_FILTER_LEVEL);

    // Calculate noise threshold.
    final double noiseThreshold = calcDerivativeThreshold(secondDerivative,
        parameters.getParameter(DERIVATIVE_THRESHOLD_LEVEL).getValue());

    // Search for peaks.
    Arrays.sort(scanNumbers);
    final Feature[] resolvedOriginalPeaks = peaksSearch(chromatogram, scanNumbers,
        secondDerivative, noiseThreshold, mzCenterFunction, msmsRange, rTRangeMSMS);

    final Range<Double> peakDuration = parameters.getParameter(PEAK_DURATION).getValue();
    final double minimumPeakHeight = parameters.getParameter(MIN_PEAK_HEIGHT).getValue();

    // Apply final filter of detected peaks, according with setup
    // parameters.
    for (final Feature p : resolvedOriginalPeaks) {

      if (peakDuration.contains(RangeUtils.rangeLength(p.getRawDataPointsRTRange()))
          && p.getHeight() >= minimumPeakHeight) {

        resolvedPeaks.add(p);
      }
    }
  }

  return resolvedPeaks.toArray(new ResolvedPeak[resolvedPeaks.size()]);
}
 
源代码18 项目: mzmine3   文件: BaselinePeakDetector.java
@Override
public ResolvedPeak[] resolvePeaks(final Feature chromatogram, ParameterSet parameters,
    RSessionWrapper rSession, CenterFunction mzCenterFunction, double msmsRange,
    double rTRangeMSMS) {

  int scanNumbers[] = chromatogram.getScanNumbers();
  final int scanCount = scanNumbers.length;
  double retentionTimes[] = new double[scanCount];
  double intensities[] = new double[scanCount];
  RawDataFile dataFile = chromatogram.getDataFile();
  for (int i = 0; i < scanCount; i++) {
    final int scanNum = scanNumbers[i];
    retentionTimes[i] = dataFile.getScan(scanNum).getRetentionTime();
    DataPoint dp = chromatogram.getDataPoint(scanNum);
    if (dp != null)
      intensities[i] = dp.getIntensity();
    else
      intensities[i] = 0.0;
  }

  // Get parameters.
  final double minimumPeakHeight = parameters.getParameter(MIN_PEAK_HEIGHT).getValue();
  final double baselineLevel = parameters.getParameter(BASELINE_LEVEL).getValue();
  final Range<Double> durationRange = parameters.getParameter(PEAK_DURATION).getValue();

  final List<ResolvedPeak> resolvedPeaks = new ArrayList<ResolvedPeak>(2);

  // Current region is a region of consecutive scans which all have
  // intensity above baseline level.
  for (int currentRegionStart = 0; currentRegionStart < scanCount; currentRegionStart++) {

    // Find a start of the region.
    final DataPoint startPeak = chromatogram.getDataPoint(scanNumbers[currentRegionStart]);
    if (startPeak != null && startPeak.getIntensity() >= baselineLevel) {

      double currentRegionHeight = startPeak.getIntensity();

      // Search for end of the region
      int currentRegionEnd;
      for (currentRegionEnd =
          currentRegionStart + 1; currentRegionEnd < scanCount; currentRegionEnd++) {

        final DataPoint endPeak = chromatogram.getDataPoint(scanNumbers[currentRegionEnd]);
        if (endPeak == null || endPeak.getIntensity() < baselineLevel) {

          break;
        }

        currentRegionHeight = Math.max(currentRegionHeight, endPeak.getIntensity());
      }

      // Subtract one index, so the end index points at the last data
      // point of current region.
      currentRegionEnd--;

      // Check current region, if it makes a good peak.
      if (durationRange
          .contains(retentionTimes[currentRegionEnd] - retentionTimes[currentRegionStart])
          && currentRegionHeight >= minimumPeakHeight) {

        // Create a new ResolvedPeak and add it.
        resolvedPeaks.add(new ResolvedPeak(chromatogram, currentRegionStart, currentRegionEnd,
            mzCenterFunction, msmsRange, rTRangeMSMS));
      }

      // Find next peak region, starting from next data point.
      currentRegionStart = currentRegionEnd;

    }
  }

  return resolvedPeaks.toArray(new ResolvedPeak[resolvedPeaks.size()]);
}
 
源代码19 项目: mzmine3   文件: RTScore.java
public double calculateScore(AlignmentPath path, PeakListRow peak, ParameterSet parameters) {
  try {
    rtTolerance = parameters.getParameter(PathAlignerParameters.RTTolerance).getValue();
    mzTolerance = parameters.getParameter(PathAlignerParameters.MZTolerance).getValue();
    Range<Double> rtRange = rtTolerance.getToleranceRange(path.getRT());
    Range<Double> mzRange = mzTolerance.getToleranceRange(path.getMZ());

    if (!rtRange.contains(peak.getAverageRT()) || !mzRange.contains(peak.getAverageMZ())) {
      return WORST_SCORE;
    }

    double mzDiff = Math.abs(path.getMZ() - peak.getAverageMZ());

    double rtDiff = Math.abs(path.getRT() - peak.getAverageRT());

    double score = ((mzDiff / (RangeUtils.rangeLength(mzRange) / 2.0)))
        + ((rtDiff / (RangeUtils.rangeLength(rtRange) / 2.0)));

    if (parameters.getParameter(PathAlignerParameters.SameChargeRequired).getValue()) {
      if (!PeakUtils.compareChargeState(path.convertToAlignmentRow(0), peak)) {
        return WORST_SCORE;
      }
    }

    if (parameters.getParameter(PathAlignerParameters.SameIDRequired).getValue()) {
      if (!PeakUtils.compareIdentities(path.convertToAlignmentRow(0), peak)) {
        return WORST_SCORE;
      }
    }

    if (parameters.getParameter(PathAlignerParameters.compareIsotopePattern).getValue()) {
      IsotopePattern ip1 = path.convertToAlignmentRow(0).getBestIsotopePattern();
      IsotopePattern ip2 = peak.getBestIsotopePattern();

      if ((ip1 != null) && (ip2 != null)) {
        ParameterSet isotopeParams = parameters
            .getParameter(PathAlignerParameters.compareIsotopePattern).getEmbeddedParameters();

        if (!IsotopePatternScoreCalculator.checkMatch(ip1, ip2, isotopeParams)) {
          return WORST_SCORE;
        }
      }
    }

    return score;
  } catch (NullPointerException e) {
    e.printStackTrace();
    return WORST_SCORE;
  }
}
 
源代码20 项目: luna   文件: PlayerAppearance.java
/**
 * Determines if {@code value} is a valid model for {@code gender} and body part
 * {@code model}.
 *
 * @param model The body part identifier.
 * @param gender The gender value.
 * @param value The model value.
 * @return {@code true} if {@code value} is a valid model for {@code gender} and body part
 * {@code model}.
 */
public static boolean isModelValid(int model, int gender, int value) {
    Range<Integer> validModels = VALID_MODELS.get(gender, model);
    return validModels != null && validModels.contains(value);
}