/**
  * Sets properties for the TE calculator. New property values are not guaranteed to take effect
  * until the next call to an initialise method.
  *
  * <p>Valid property names, and what their values should represent, include:
  *
  * <ul>
  *   <li>{@link #PROP_KRASKOV_ALG_NUM} -- which Kraskov algorithm number to use (1 or 2).
  *   <li>Any properties accepted by {@link
  *       TransferEntropyCalculatorViaCondMutualInfo#setProperty(String, String)}
  *   <li>Or properties accepted by the underlying {@link
  *       ConditionalMutualInfoCalculatorMultiVariateKraskov#setProperty(String, String)}
  *       implementation.
  * </ul>
  *
  * <p>One should set {@link ConditionalMutualInfoCalculatorMultiVariateKraskov#PROP_K} here, the
  * number of neighbouring points one should count up to in determining the joint kernel size.
  *
  * <p><b>Note:</b> further properties may be defined by child classes.
  *
  * <p>Unknown property values are ignored.
  *
  * @param propertyName name of the property
  * @param propertyValue value of the property.
  * @throws Exception if there is a problem with the supplied value).
  */
 public void setProperty(String propertyName, String propertyValue) throws Exception {
   if (propertyName.equalsIgnoreCase(PROP_KRASKOV_ALG_NUM)) {
     int previousAlgNumber = kraskovAlgorithmNumber;
     kraskovAlgorithmNumber = Integer.parseInt(propertyValue);
     if ((kraskovAlgorithmNumber != 1) && (kraskovAlgorithmNumber != 2)) {
       throw new Exception(
           "Kraskov algorithm number (" + kraskovAlgorithmNumber + ") must be either 1 or 2");
     }
     if (kraskovAlgorithmNumber != previousAlgNumber) {
       algChanged = true;
     }
     if (debug) {
       System.out.println(
           this.getClass().getSimpleName()
               + ": Set property "
               + propertyName
               + " to "
               + propertyValue);
     }
   } else {
     // Assume it was a property for the parent class or underlying conditional MI calculator
     super.setProperty(propertyName, propertyValue);
     props.put(
         propertyName,
         propertyValue); // This will keep properties for the super class as well as the cond MI
     // calculator, but this is ok
   }
 }
  /* (non-Javadoc)
   * @see infodynamics.measures.continuous.TransferEntropyCalculatorViaCondMutualInfo#initialise(int, int, int, int, int)
   */
  @Override
  public void initialise(int k, int k_tau, int l, int l_tau, int delay) throws Exception {
    if (algChanged) {
      // The algorithm number was changed in a setProperties call:
      String newCalcName = COND_MI_CALCULATOR_KRASKOV1;
      if (kraskovAlgorithmNumber == 2) {
        newCalcName = COND_MI_CALCULATOR_KRASKOV2;
      }
      @SuppressWarnings("unchecked")
      Class<ConditionalMutualInfoCalculatorMultiVariate> condMiClass =
          (Class<ConditionalMutualInfoCalculatorMultiVariate>) Class.forName(newCalcName);
      ConditionalMutualInfoCalculatorMultiVariate newCondMiCalc = condMiClass.newInstance();
      construct(newCondMiCalc);
      // Set the properties for the Kraskov MI calculators (may pass in properties for our super
      // class
      //  as well, but they should be ignored)
      for (String key : props.keySet()) {
        newCondMiCalc.setProperty(key, props.get(key));
      }
      algChanged = false;
    }

    super.initialise(k, k_tau, l, l_tau, delay);
  }