private double calcPval(
     HashMap<Integer, String> singleGeneCaseValueMap, String profileType, String profileStableId)
     throws IllegalArgumentException {
   double _p_value = 0.0;
   if (profileType.equals(GeneticAlterationType.MUTATION_EXTENDED.toString())
       || profileType.equals(GeneticAlterationType.COPY_NUMBER_ALTERATION.toString())) {
     _p_value = runFisherExactTest(singleGeneCaseValueMap, profileType);
   } else if (profileType.equals(GeneticAlterationType.MRNA_EXPRESSION.toString())
       || profileType.equals(GeneticAlterationType.PROTEIN_LEVEL.toString())) {
     _p_value = runTTest(singleGeneCaseValueMap, profileStableId);
   }
   return _p_value;
 }
  private double runFisherExactTest(
      HashMap<Integer, String> singleGeneCaseValueMap, String profileType) {

    int a = 0, // non altered
        b = 0, // x non altered, y altered
        c = 0, // x altered, y non altered
        d = 0; // both alered

    for (Integer alteredSampleId : alteredSampleIds) {
      if (singleGeneCaseValueMap.containsKey(alteredSampleId)) {
        if (profileType.equals(GeneticAlterationType.COPY_NUMBER_ALTERATION.toString())) {
          try {
            Double value = Double.parseDouble(singleGeneCaseValueMap.get(alteredSampleId));
            if (copyNumType.equals("del")) {
              if (value == -2.0) {
                d += 1;
              } else {
                c += 1;
              }
            } else if (copyNumType.equals("amp")) {
              if (value == 2.0) {
                d += 1;
              } else {
                c += 1;
              }
            }
          } catch (NumberFormatException e) {
            e.getStackTrace();
          }
        } else if (profileType.equals(GeneticAlterationType.MUTATION_EXTENDED.toString())) {
          String value = singleGeneCaseValueMap.get(alteredSampleId);
          if (value.equals("Non")) {
            c += 1;
          } else {
            d += 1;
          }
        }
      }
    }

    for (Integer unalteredSampleId : unalteredSampleIds) {
      if (singleGeneCaseValueMap.containsKey(unalteredSampleId)) {
        if (profileType.equals(GeneticAlterationType.COPY_NUMBER_ALTERATION.toString())) {
          try {
            Double value = Double.parseDouble(singleGeneCaseValueMap.get(unalteredSampleId));
            if (copyNumType.equals("del")) {
              if (value == -2.0) {
                b += 1;
              } else {
                a += 1;
              }
            } else if (copyNumType.equals("amp")) {
              if (value == 2.0) {
                b += 1;
              } else {
                a += 1;
              }
            }
          } catch (NumberFormatException e) {
            e.getStackTrace();
          }
        } else if (profileType.equals(GeneticAlterationType.MUTATION_EXTENDED.toString())) {
          String value = singleGeneCaseValueMap.get(unalteredSampleId);
          if (value.equals("Non")) {
            a += 1;
          } else {
            b += 1;
          }
        }
      }
    }

    FisherExact fisher = new FisherExact(a + b + c + d);
    return fisher.getCumlativeP(a, b, c, d);
  }
  private double calcPct(
      HashMap<Integer, String> singleGeneCaseValueMap,
      String profileType,
      String groupType) { // group type: altered or unaltered

    double _result_pct = 0, _count = 0; // altered samples count

    if (profileType.equals(GeneticAlterationType.COPY_NUMBER_ALTERATION.toString())
        && copyNumType.equals("del")) {
      switch (groupType) {
        case "altered":
          for (Integer alteredSampleId : alteredSampleIds) {
            if (singleGeneCaseValueMap.containsKey(alteredSampleId)) {
              try {
                if (Double.parseDouble(singleGeneCaseValueMap.get(alteredSampleId)) == -2.0) {
                  _count += 1;
                }
              } catch (NumberFormatException e) {
                e.getStackTrace();
              }
            }
          }
          _result_pct = _count / alteredSampleIds.size();
          break;
        case "unaltered":
          for (Integer unalteredSampleId : unalteredSampleIds) {
            if (singleGeneCaseValueMap.containsKey(unalteredSampleId)) {
              try {
                if (Double.parseDouble(singleGeneCaseValueMap.get(unalteredSampleId)) == -2.0) {
                  _count += 1;
                }
              } catch (NumberFormatException e) {
                e.getStackTrace();
              }
            }
          }
          _result_pct = _count / unalteredSampleIds.size();
          break;
      }
    } else if (profileType.equals(GeneticAlterationType.COPY_NUMBER_ALTERATION.toString())
        && copyNumType.equals("amp")) {
      switch (groupType) {
        case "altered":
          for (Integer alteredSampleId : alteredSampleIds) {
            if (singleGeneCaseValueMap.containsKey(alteredSampleId)) {
              try {
                if (Double.parseDouble(singleGeneCaseValueMap.get(alteredSampleId)) == 2.0) {
                  _count += 1;
                }
              } catch (NumberFormatException e) {
                e.getStackTrace();
              }
            }
          }
          _result_pct = _count / alteredSampleIds.size();
          break;
        case "unaltered":
          for (Integer unalteredSampleId : unalteredSampleIds) {
            if (singleGeneCaseValueMap.containsKey(unalteredSampleId)) {
              try {
                if (Double.parseDouble(singleGeneCaseValueMap.get(unalteredSampleId)) == 2.0) {
                  _count += 1;
                }
              } catch (NumberFormatException e) {
                e.getStackTrace();
              }
            }
          }
          _result_pct = _count / unalteredSampleIds.size();
          break;
      }
    } else if (profileType.equals(GeneticAlterationType.MUTATION_EXTENDED.toString())) {
      switch (groupType) {
        case "altered":
          for (Integer alteredSampleId : alteredSampleIds) {
            if (singleGeneCaseValueMap.containsKey(alteredSampleId)) {
              if (!singleGeneCaseValueMap.get(alteredSampleId).equals("Non")) {
                _count += 1;
              }
            }
          }
          _result_pct = _count / alteredSampleIds.size();
          break;
        case "unaltered":
          for (Integer unalteredSampleId : unalteredSampleIds) {
            if (singleGeneCaseValueMap.containsKey(unalteredSampleId)) {
              if (!singleGeneCaseValueMap.get(unalteredSampleId).equals("Non")) {
                _count += 1;
              }
            }
          }
          _result_pct = _count / unalteredSampleIds.size();
          break;
      }
    }

    return _result_pct;
  }
  @Override
  public ObjectNode process(long entrezGeneId, String[] values, ArrayList<Integer> sampleList) {

    ObjectNode _datum = mapper.createObjectNode();

    // create map to pair sample and value
    HashMap<Integer, String> mapSampleValue = new HashMap<>();
    for (int i = 0; i < values.length; i++) {
      String value = values[i];
      Integer sampleId = sampleList.get(i);
      mapSampleValue.put(sampleId, value);
    }

    // remove empty entry
    Iterator it = mapSampleValue.entrySet().iterator();
    while (it.hasNext()) {
      Map.Entry pair = (Map.Entry) it.next();
      if (pair.getValue().equals("NA")
          || pair.getValue().equals("NaN")
          || pair.getValue().equals("null")) {
        it.remove();
      }
    }

    // get Gene Name and Cytoband
    DaoGeneOptimized daoGeneOptimized = DaoGeneOptimized.getInstance();
    String geneName = daoGeneOptimized.getGene(entrezGeneId).getHugoGeneSymbolAllCaps();
    String cytoband = daoGeneOptimized.getGene(entrezGeneId).getCytoband();

    // statistics analysis
    if (profileType.equals(GeneticAlterationType.COPY_NUMBER_ALTERATION.toString())) {
      if (!(Arrays.asList(queriedGenes)).contains(geneName)) { // remove queried genes from result
        _datum.put(COL_NAME_GENE, geneName);
        _datum.put(COL_NAME_CYTOBAND, cytoband);
        _datum.put(
            COL_NAME_PCT_ALTERED,
            Integer.toString(countAltered(mapSampleValue, profileType, "altered"))
                + "////"
                + Double.toString(calcPct(mapSampleValue, profileType, "altered")));
        _datum.put(
            COL_NAME_PCT_UNALTERED,
            Integer.toString(countAltered(mapSampleValue, profileType, "unaltered"))
                + "////"
                + Double.toString(calcPct(mapSampleValue, profileType, "unaltered")));
        _datum.put(
            COL_NAME_RATIO,
            calcRatio(
                calcPct(mapSampleValue, profileType, "altered"),
                calcPct(mapSampleValue, profileType, "unaltered")));
        _datum.put(COL_NAME_DIRECTION, "place holder"); // calculation is done by the front-end
        _datum.put(COL_NAME_P_VALUE, calcPval(mapSampleValue, profileType, geneticProfileStableId));
        if (!(calcPct(mapSampleValue, profileType, "altered") == 0.0
                && calcPct(mapSampleValue, profileType, "unaltered") == 0.0)
            && !Double.isNaN(calcPval(mapSampleValue, profileType, geneticProfileStableId))) {
          return _datum;
        }
      }
    } else if (profileType.equals(GeneticAlterationType.MRNA_EXPRESSION.toString())) {
      _datum.put(COL_NAME_GENE, geneName);
      _datum.put(COL_NAME_CYTOBAND, cytoband);
      _datum.put(
          COL_NAME_MEAN_ALTERED, calcMean(mapSampleValue, "altered", geneticProfileStableId));
      _datum.put(
          COL_NAME_MEAN_UNALTERED, calcMean(mapSampleValue, "unaltered", geneticProfileStableId));
      _datum.put(
          COL_NAME_STDEV_ALTERED, calcSTDev(mapSampleValue, "altered", geneticProfileStableId));
      _datum.put(
          COL_NAME_STDEV_UNALTERED, calcSTDev(mapSampleValue, "unaltered", geneticProfileStableId));
      _datum.put(COL_NAME_P_VALUE, calcPval(mapSampleValue, profileType, geneticProfileStableId));
      if (!Double.isNaN(calcPval(mapSampleValue, profileType, geneticProfileStableId))) {
        return _datum;
      }
    } else if (profileType.equals(GeneticAlterationType.PROTEIN_LEVEL.toString())) {
      _datum.put(COL_NAME_GENE, geneName);
      _datum.put(COL_NAME_CYTOBAND, cytoband);
      _datum.put(
          COL_NAME_MEAN_ALTERED, calcMean(mapSampleValue, "altered", geneticProfileStableId));
      _datum.put(
          COL_NAME_MEAN_UNALTERED, calcMean(mapSampleValue, "unaltered", geneticProfileStableId));
      _datum.put(
          COL_NAME_STDEV_ALTERED, calcSTDev(mapSampleValue, "altered", geneticProfileStableId));
      _datum.put(
          COL_NAME_STDEV_UNALTERED, calcSTDev(mapSampleValue, "unaltered", geneticProfileStableId));
      _datum.put(COL_NAME_P_VALUE, calcPval(mapSampleValue, profileType, geneticProfileStableId));
      if (!Double.isNaN(calcPval(mapSampleValue, profileType, geneticProfileStableId))) {
        return _datum;
      }
    }

    return null;
  }