private void displayRoutine(
     PatternFeatureID featureID, PatternFeature feature, double modelValue, double error) {
   if (display) {
     String displayString = "\t" + featureID;
     if (feature.isRange()) {
       displayString +=
           "\t("
               + GeneralUtils.formatTwoDecimal(feature.getValueMin())
               + ", "
               + GeneralUtils.formatTwoDecimal(feature.getValueMax())
               + ")";
     } else {
       displayString += "\t" + GeneralUtils.formatTwoDecimal(feature.getValue());
     }
     displayString += "\t" + GeneralUtils.formatTwoDecimal(modelValue);
     displayString += "\t" + GeneralUtils.formatThreeDecimal(error) + "\t/";
     System.out.println(displayString);
   }
 }
 private double NormalizedErrorObsNormed(PatternFeature feature, double modelValue) {
   /*
    * the w here is manual weight assigned in JSON. only for special cases!! like 3-000 to get D.ASP.
    * shouldn't be confused with dynamic W calculated in spikepatternclassifier
    * Typically, w is 0 in JSON, so that this manual weight is ignored!
    */
   double w = feature.getWeight();
   if (GeneralUtils.isCloseEnough(w, 0, 0.001)) {
     w = 1;
   }
   if (feature.isRange()) {
     return w
         * StatUtil.calculateObsNormalizedError(
             feature.getValueMin(), feature.getValueMax(), modelValue);
   } else {
     return w * StatUtil.calculateObsNormalizedError(feature.getValue(), modelValue);
   }
 }
  public double burstFeatureError() {
    BurstFeature expBurstFeature = expSpikePatternData.getBurstFeatures();
    ArrayList<HashMap<BurstFeatureID, Double>> expBurstFeatures = expBurstFeature.getValue();

    double error = 0;
    /*	if(display) {
    	System.out.print("\tBursts:");
    	modelSpikePattern.getBurstPattern().displayBursts();
    	System.out.println("\n");
    }*/
    for (int i = 0; i < expBurstFeatures.size(); i++) {
      error += singleBurstError(i, expBurstFeatures.get(i));
    }
    error = expBurstFeature.getTotalWeight() * (error / (1.0f * expBurstFeatures.size()));

    if (display) {
      System.out.print("\t" + GeneralUtils.formatThreeDecimal(error) + "\n");
    }

    return error;
  }
  private double singleBurstError(
      int burstIdx, HashMap<BurstFeatureID, Double> expSingleBurstFeatures) {
    if (burstIdx >= modelSpikePattern.getBurstPattern().getNBursts()) {
      return 1;
    }

    double errorBW = 0;
    double errorIBI = 0;
    double errorNspikes = 0;

    // 2. BW error
    double bw = -1;
    if (expSingleBurstFeatures.containsKey(BurstFeatureID.b_w)) {
      bw = expSingleBurstFeatures.get(BurstFeatureID.b_w);
      double modelBw = modelSpikePattern.getBurstPattern().getBW(burstIdx);
      errorBW = StatUtil.calculateObsNormalizedError(bw, modelBw);
    }

    // 3. IBI error
    double pbi = -1;
    if (expSingleBurstFeatures.containsKey(BurstFeatureID.pbi)) {
      pbi = expSingleBurstFeatures.get(BurstFeatureID.pbi);
      double modelPbi = modelSpikePattern.getBurstPattern().getIBI(burstIdx);
      errorIBI = StatUtil.calculateObsNormalizedError(pbi, modelPbi);
    }

    // 4. N spikes error
    double nspikes = expSingleBurstFeatures.get(BurstFeatureID.nspikes);
    errorNspikes =
        StatUtil.calculateObsNormalizedError(
            nspikes, modelSpikePattern.getBurstPattern().getNSpikes(burstIdx));

    /*
     * display
     */
    if (display) {
      System.out.print("\t");
      if (expSingleBurstFeatures.containsKey(BurstFeatureID.b_w)) {
        String displayString = "\tb_w\t" + GeneralUtils.formatTwoDecimal(bw);
        displayString +=
            "\t"
                + GeneralUtils.formatTwoDecimal(
                    modelSpikePattern.getBurstPattern().getBW(burstIdx));
        displayString += "\t" + GeneralUtils.formatThreeDecimal(errorBW) + "\t/";
        System.out.print(displayString);
      }

      if (expSingleBurstFeatures.containsKey(BurstFeatureID.pbi)) {
        String displayString = "\tibi\t" + GeneralUtils.formatTwoDecimal(pbi);
        displayString +=
            "\t"
                + GeneralUtils.formatTwoDecimal(
                    modelSpikePattern.getBurstPattern().getIBI(burstIdx));
        displayString += "\t" + GeneralUtils.formatThreeDecimal(errorIBI) + "\t/";
        System.out.print(displayString);
      }

      String displayString = "\tnspikes\t" + GeneralUtils.formatTwoDecimal(nspikes);
      displayString +=
          "\t"
              + GeneralUtils.formatTwoDecimal(
                  modelSpikePattern.getBurstPattern().getNSpikes(burstIdx));
      displayString += "\t" + GeneralUtils.formatThreeDecimal(errorNspikes) + "\t/";
      System.out.print(displayString + "\n");
    }

    return ((expSpikePatternData.getBurstFeatures().getFeatureWeight(BurstFeatureID.b_w) * errorBW)
        + (expSpikePatternData.getBurstFeatures().getFeatureWeight(BurstFeatureID.pbi) * errorIBI)
        + (expSpikePatternData.getBurstFeatures().getFeatureWeight(BurstFeatureID.nspikes)
            * errorNspikes));
  }
  public float calculatePatternError() {
    float patternError = Float.MAX_VALUE;
    float patternValidityErrorVmin = 0;
    float patternValidityErrorVrest = 0;

    if (modelSpikePattern == null) {
      if (display) {
        System.out.println(
            "**NULL compartment SPIKE PATTERN** SPEvaluatorV2:calculatePatternError()");
      }
      return patternError;
    }
    // && Math.abs(Float.MAX_VALUE - modelError)>10.0f
    if (checkForPatternValidity) {
      if (expSpikePatternData.getType() == PatternType.SPIKES) {
        // if(!modelSpikePattern.isValidSpikesPattern(modelVmin, modelVr)) { if(display) {
        // System.out.println("**Invalid SPIKEs Pattern**");	   }
        if (!modelSpikePattern.isValidSpikesPattern()) {
          if (display) {
            System.out.println("**Invalid SPIKEs Pattern** SPEvaluatorV2:calculatePatternError()");
          }
          return patternError;
        }
        /*else{
        //	    	if(!expSpikePatternData.getFeaturesToEvaluate().contains(PatternFeatureID.bursts))
        	    	{
        	    		patternValidityErrorVmin = nonBurstBelowVminError(modelVmin);
        	    	}
        	        patternValidityErrorVrest = spikesBelowVrestError(modelVr);
        	    }*/
        if (modelSpikePattern.getISIs() == null) {
          if (display) {
            System.out.println("**Null ISIs** SPEvaluatorV2:calculatePatternError()");
          }
          return patternError;
        }
      }
    } /*else{

        	if(modelSpikePattern.getSpikeTimes().length < 1
        			||
        		(modelSpikePattern.getSpikeTimes()[modelSpikePattern.getSpikeTimes().length-1] - modelSpikePattern.getTimeMin()) > (modelSpikePattern.getDurationOfCurrentInjection()+10))  {
      	return patternError;
      }
        	if(modelSpikePattern.getISIs() == null ) { if(display) {System.out.println("**Null ISIs**");      }
       			return patternError;
        	}
        }*/
    // System.out.println("SPE:: patternWeighted Avg Error will..");

    patternError = patternWeightedAvgError();
    // System.out.println("SPE:: patternWeighted Avg Error done..");

    float avgPatternError;
    if (expSpikePatternData.getType() == PatternType.SPIKES
        || expSpikePatternData.getType() == PatternType.RBASE) {
      avgPatternError =
          (float)
              (patternRepairWeights[0] * patternError
                  + patternRepairWeights[1] * patternValidityErrorVmin
                  + patternRepairWeights[2] * patternValidityErrorVrest);
    } else {
      avgPatternError = patternError;
    }
    if (display) {
      System.out.print(
          "\nPatternFeatError\t"
              + GeneralUtils.formatThreeDecimal(patternError)
              + "\nPatternValidityErrorVmin\t"
              + GeneralUtils.formatThreeDecimal(patternValidityErrorVmin)
              + "\nPatternValidityErrorVrest\t"
              + GeneralUtils.formatThreeDecimal(patternValidityErrorVrest));
    }
    return avgPatternError * expSpikePatternData.getPatternWeight();
  }
  private void displayRoutineForSFA(PatternFeature[] exp, double[] model, double error) {
    String displayString = "";

    displayString = "\ty=";
    if (exp[0].isRange()) {
      displayString +=
          "("
              + GeneralUtils.formatThreeDecimal(exp[0].getValueMin())
              + ", "
              + GeneralUtils.formatThreeDecimal(exp[0].getValueMax())
              + ")"
              + "x+"
              + "("
              + GeneralUtils.formatThreeDecimal(exp[1].getValueMin())
              + ", "
              + GeneralUtils.formatThreeDecimal(exp[1].getValueMax())
              + ")";
      displayString +=
          "\tnISIs: "
              + "("
              + GeneralUtils.formatThreeDecimal(exp[2].getValueMin())
              + ", "
              + GeneralUtils.formatThreeDecimal(exp[2].getValueMax())
              + ")";
    } else {
      displayString +=
          GeneralUtils.formatThreeDecimal(exp[0].getValue())
              + "x+"
              + GeneralUtils.formatThreeDecimal(exp[1].getValue());
      displayString += "\tnISIs: " + GeneralUtils.formatThreeDecimal(exp[2].getValue());
    }

    displayString += "\ty=";
    if (exp[3].isRange()) {
      displayString +=
          "("
              + GeneralUtils.formatThreeDecimal(exp[3].getValueMin())
              + ", "
              + GeneralUtils.formatThreeDecimal(exp[3].getValueMax())
              + ")"
              + "x+"
              + "("
              + GeneralUtils.formatThreeDecimal(exp[4].getValueMin())
              + ", "
              + GeneralUtils.formatThreeDecimal(exp[4].getValueMax())
              + ")";
      displayString +=
          "\tnISIs: "
              + "("
              + GeneralUtils.formatThreeDecimal(exp[5].getValueMin())
              + ", "
              + GeneralUtils.formatThreeDecimal(exp[5].getValueMax())
              + ")";
    } else {
      displayString +=
          GeneralUtils.formatThreeDecimal(exp[3].getValue())
              + "x+"
              + GeneralUtils.formatThreeDecimal(exp[4].getValue());
      displayString += "\tnISIs: " + GeneralUtils.formatThreeDecimal(exp[5].getValue());
    }

    displayString +=
        "\n\ty="
            + GeneralUtils.formatThreeDecimal(model[0])
            + "x+"
            + GeneralUtils.formatThreeDecimal(model[1]);
    displayString += "\tnISIs: " + model[2];
    displayString +=
        "\ty="
            + GeneralUtils.formatThreeDecimal(model[3])
            + "x+"
            + GeneralUtils.formatThreeDecimal(model[4]);
    displayString += "\tnISIs: " + model[5];
    displayString += "\t" + GeneralUtils.formatThreeDecimal(error) + "\t/";
    System.out.println(displayString);
  }