All Downloads are FREE. Search and download functionalities are using the official Maven repository.

marytts.vocalizations.VocalizationSelector Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2010 DFKI GmbH.
 * All Rights Reserved.  Use is subject to license terms.
 *
 * This file is part of MARY TTS.
 *
 * MARY TTS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 */
package marytts.vocalizations;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.List;

import marytts.exceptions.MaryConfigurationException;
import marytts.features.FeatureDefinition;
import marytts.features.FeatureVector;
import marytts.modules.synthesis.Voice;
import marytts.server.MaryProperties;
import marytts.unitselection.data.Unit;
import marytts.unitselection.select.Target;
import marytts.unitselection.select.VocalizationFFRTargetCostFunction;
import marytts.util.MaryUtils;
import marytts.util.math.MathUtils;
import marytts.util.math.Polynomial;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.w3c.dom.Element;

/**
 * Select suitable vocalization for a given target using a cost function
 * 
 * @author sathish
 * 
 */
public class VocalizationSelector {

	protected VocalizationFeatureFileReader featureFileReader;
	protected FeatureDefinition featureDefinition;
	protected FeatureDefinition f0FeatureDefinition;
	protected VocalizationIntonationReader vIntonationReader;
	protected VocalizationUnitFileReader unitFileReader;
	protected VocalizationFFRTargetCostFunction vffrtUnitCostFunction = null;
	protected VocalizationFFRTargetCostFunction vffrtContourCostFunction = null;
	protected boolean f0ContourImposeSupport;
	protected boolean usePrecondition;
	protected double contourCostWeight;
	private DecimalFormat df;

	protected int noOfSuitableUnits = 1;

	protected Logger logger = MaryUtils.getLogger("Vocalization Selector");

	public VocalizationSelector(Voice voice) throws MaryConfigurationException {

		String unitFileName = MaryProperties.getFilename("voice." + voice.getName() + ".vocalization.unitfile");
		String featureFile = MaryProperties.getFilename("voice." + voice.getName() + ".vocalization.featurefile");
		String featureDefinitionFile = MaryProperties.getFilename("voice." + voice.getName()
				+ ".vocalization.featureDefinitionFile");
		f0ContourImposeSupport = MaryProperties.getBoolean("voice." + voice.getName() + ".f0ContourImposeSupport", false);
		df = new DecimalFormat("##.##");
		try {
			BufferedReader fDBufferedReader = new BufferedReader(new FileReader(new File(featureDefinitionFile)));
			this.featureDefinition = new FeatureDefinition(fDBufferedReader, true);
			this.featureFileReader = new VocalizationFeatureFileReader(featureFile);
			vffrtUnitCostFunction = new VocalizationFFRTargetCostFunction(this.featureFileReader, this.featureDefinition);
			unitFileReader = new VocalizationUnitFileReader(unitFileName);

			if (this.featureFileReader.getNumberOfUnits() != this.unitFileReader.getNumberOfUnits()) {
				throw new MaryConfigurationException("Feature file reader and unit file reader is not aligned properly");
			}

			if (this.f0ContourImposeSupport) {
				String intonationFDFile = MaryProperties.getFilename("voice." + voice.getName()
						+ ".vocalization.intonation.featureDefinitionFile");
				String intonationFile = MaryProperties.getFilename("voice." + voice.getName() + ".vocalization.intonationfile");
				usePrecondition = MaryProperties.getBoolean("voice." + voice.getName() + ".vocalization.usePrecondition", false);
				contourCostWeight = (new Double(MaryProperties.getProperty("voice." + voice.getName()
						+ ".vocalization.contourCostWeight", "0.5"))).doubleValue();
				if (contourCostWeight < 0 || contourCostWeight > 1.0) {
					throw new MaryConfigurationException("contourCostWeight should be between 0 and 1");
				}
				BufferedReader f0FDBufferedReader = new BufferedReader(new FileReader(new File(intonationFDFile)));
				f0FeatureDefinition = new FeatureDefinition(f0FDBufferedReader, true);
				vIntonationReader = new VocalizationIntonationReader(intonationFile);
				noOfSuitableUnits = MaryProperties.getInteger("voice." + voice.getName()
						+ ".vocalization.intonation.numberOfSuitableUnits");
				vffrtContourCostFunction = new VocalizationFFRTargetCostFunction(this.featureFileReader, this.f0FeatureDefinition);
			}
		} catch (IOException e) {
			throw new MaryConfigurationException("Problem loading vocalization files for voice ", e);
		}
	}

	/**
	 * Get feature definition used to select suitable candidate
	 * 
	 * @return Feature Definition
	 */
	public FeatureDefinition getFeatureDefinition() {
		return this.featureDefinition;
	}

	/**
	 * Get best candidate pair to impose F0 contour on other
	 * 
	 * @param domElement
	 *            xml request for vocalization
	 * @return SourceTargetPair best candidate pair
	 */
	public SourceTargetPair getBestCandidatePairtoImposeF0(Element domElement) {

		VocalizationCandidate[] vCosts = getBestMatchingCandidates(domElement);
		VocalizationCandidate[] vIntonationCosts = getBestIntonationCandidates(domElement);

		int noOfSuitableF0Units;
		if (usePrecondition) {
			noOfSuitableF0Units = getNumberContoursAboveThreshold(vCosts, vIntonationCosts);
		} else {
			noOfSuitableF0Units = noOfSuitableUnits;
		}

		if (noOfSuitableF0Units == 0) {
			return new SourceTargetPair(vCosts[0].unitIndex, vCosts[0].unitIndex, 0);
		}

		VocalizationCandidate[] suitableCandidates = new VocalizationCandidate[noOfSuitableUnits];
		System.arraycopy(vCosts, 0, suitableCandidates, 0, noOfSuitableUnits);
		VocalizationCandidate[] suitableF0Candidates = new VocalizationCandidate[noOfSuitableF0Units];
		System.arraycopy(vIntonationCosts, 0, suitableF0Candidates, 0, noOfSuitableF0Units);

		Target targetUnit = createTarget(domElement);
		if (logger.getEffectiveLevel().equals(Level.DEBUG)) {
			debugLogCandidates(targetUnit, suitableCandidates, suitableF0Candidates);
		}

		SourceTargetPair[] sortedImposeF0Data = vocalizationF0DistanceComputer(suitableCandidates, suitableF0Candidates,
				domElement);

		return sortedImposeF0Data[0];
	}

	/**
	 * compute a threshold according to precondition and get number of contours above computed threshold
	 * 
	 * formula : for all CC(j) < CCmax where j1, j2, j3 ... are contour candidates CCmax (threshold) = min (CC(i1), CC(i2),
	 * CC(i3)....) where i1, i2, i3 .. are unit candidates
	 * 
	 * @param vCosts
	 *            VocalizationCandidates
	 * @param vIntonationCosts
	 *            VocalizationF0Candidates
	 * @return int number of contours above computed threshold
	 */
	private int getNumberContoursAboveThreshold(VocalizationCandidate[] vCosts, VocalizationCandidate[] vIntonationCosts) {

		// get minimum cc cost for all units
		double[] costs = new double[noOfSuitableUnits];
		for (int i = 0; i < costs.length; i++) {
			int unitIndex = vCosts[i].unitIndex;
			VocalizationCandidate contourCandidate = getCandidateByIndex(vIntonationCosts, unitIndex);
			if (contourCandidate != null) {
				costs[i] = contourCandidate.cost;
			} else {
				costs[i] = Double.MAX_VALUE;
			}
		}

		double threshold = MathUtils.min(costs);
		int contourSetSize = 0;
		for (int i = 0; i < vIntonationCosts.length; i++) {
			if (vIntonationCosts[i].cost < threshold) {
				contourSetSize = i + 1;
			} else {
				break;
			}
		}

		return contourSetSize;
	}

	/**
	 * search candidate by unitindex
	 * 
	 * @param vIntonationCosts
	 *            VocalizationF0Candidates
	 * @param unitIndex
	 *            unitindex
	 * @return VocalizationCandidate of given index
	 */
	private VocalizationCandidate getCandidateByIndex(VocalizationCandidate[] vIntonationCosts, int unitIndex) {

		for (int i = 0; i < vIntonationCosts.length; i++) {
			if (vIntonationCosts[i].unitIndex == unitIndex) {
				return vIntonationCosts[i];
			}
		}
		return null;
	}

	/**
	 * polynomial distance computer between two units
	 * 
	 * @param suitableCandidates
	 *            vocalization candidates
	 * @param suitableF0Candidates
	 *            intonation candidates
	 * @return an array of candidate pairs
	 */
	private SourceTargetPair[] vocalizationF0DistanceComputer(VocalizationCandidate[] suitableCandidates,
			VocalizationCandidate[] suitableF0Candidates, Element domElement) {

		int noPossibleImpositions = suitableCandidates.length * suitableF0Candidates.length;
		SourceTargetPair[] imposeF0Data = new SourceTargetPair[noPossibleImpositions];
		int count = 0;

		for (int i = 0; i < suitableCandidates.length; i++) {
			for (int j = 0; j < suitableF0Candidates.length; j++) {
				int sourceIndex = suitableCandidates[i].unitIndex;
				int targetIndex = suitableF0Candidates[j].unitIndex;

				double contourCost = getContourCostDistance(sourceIndex, targetIndex);
				double mergeCost = getMergeCost(sourceIndex, targetIndex, domElement);
				double cost = (contourCost * contourCostWeight) + (mergeCost * (1 - contourCostWeight));
				logger.debug("Unit Index " + sourceIndex + " & Contour Index " + targetIndex + " :: Countour cost: "
						+ df.format(contourCost) + " + Merge Cost: " + df.format(mergeCost) + " --> TotalCost: "
						+ df.format(cost));
				imposeF0Data[count++] = new SourceTargetPair(sourceIndex, targetIndex, cost);
			}
		}

		Arrays.sort(imposeF0Data);

		return imposeF0Data;
	}

	/**
	 * Compute mergeCost for unit and contour candidates Formula = segmentalformCost(u(i)) + intonationCost(c(i)) +
	 * voiceQualityCost(u(i)) + 0.5 * (meaningCost(u(i)) + meaningCost(c(i)) )
	 * 
	 * @param sourceIndex
	 *            unit index
	 * @param targetIndex
	 *            unit index
	 * @return double merge cost
	 */
	private double getMergeCost(int sourceIndex, int targetIndex, Element domElement) {

		Target targetUnit = createTarget(domElement);
		Target targetContour = createIntonationTarget(domElement);

		Unit unitCandidate = this.unitFileReader.getUnit(sourceIndex);
		Unit contourCandidate = this.unitFileReader.getUnit(targetIndex);

		// unit features
		double segmentalCost = vffrtUnitCostFunction.featureCost(targetUnit, unitCandidate, "name");
		double voiceQualityCost = vffrtUnitCostFunction.featureCost(targetUnit, unitCandidate, "voicequality");
		double meaningUnitCost = 0;
		String[] meaningFeatureNames = vffrtUnitCostFunction.getFeatureDefinition().getContinuousFeatureNameArray();
		for (int i = 0; i < meaningFeatureNames.length; i++) {
			meaningUnitCost += vffrtUnitCostFunction.featureCost(targetUnit, unitCandidate, meaningFeatureNames[i]);
		}

		// contour features
		double intonationCost = this.vffrtContourCostFunction.featureCost(targetContour, contourCandidate, "intonation");
		double meaningContourCost = 0;
		String[] meaningContourFeatures = vffrtContourCostFunction.getFeatureDefinition().getContinuousFeatureNameArray();
		for (int i = 0; i < meaningContourFeatures.length; i++) {
			meaningContourCost += vffrtContourCostFunction
					.featureCost(targetContour, contourCandidate, meaningContourFeatures[i]);
		}

		double mergeCost = segmentalCost + voiceQualityCost + intonationCost + 0.5 * (meaningUnitCost + meaningContourCost);

		return mergeCost;
	}

	/**
	 * compute contour distance (polynomial distance)
	 * 
	 * @param sourceIndex
	 *            unit index
	 * @param targetIndex
	 *            unit index
	 * @return polynomial distance measure
	 */
	private double getContourCostDistance(int sourceIndex, int targetIndex) {
		double distance;
		if (targetIndex == sourceIndex) {
			distance = 0;
		} else {
			double[] targetCoeffs = vIntonationReader.getIntonationCoeffs(targetIndex);
			double[] sourceCoeffs = vIntonationReader.getIntonationCoeffs(sourceIndex);
			if (targetCoeffs != null && sourceCoeffs != null && targetCoeffs.length == sourceCoeffs.length) {
				distance = Polynomial.polynomialDistance(sourceCoeffs, targetCoeffs);
			} else {
				distance = Double.MAX_VALUE;
			}
		}
		return distance;
	}

	/**
	 * get a best matching candidate for a given target
	 * 
	 * @param domElement
	 *            xml request for vocalization
	 * @return unit index of best matching candidate
	 */
	public int getBestMatchingCandidate(Element domElement) {

		Target targetUnit = createTarget(domElement);
		int numberUnits = this.unitFileReader.getNumberOfUnits();
		double minCost = Double.MAX_VALUE;
		int index = 0;
		for (int i = 0; i < numberUnits; i++) {
			Unit singleUnit = this.unitFileReader.getUnit(i);
			double cost = vffrtUnitCostFunction.cost(targetUnit, singleUnit);
			if (cost < minCost) {
				minCost = cost;
				index = i;
			}
		}

		return index;
	}

	/**
	 * get a array of best candidates sorted according to cost
	 * 
	 * @param domElement
	 *            xml request for vocalization
	 * @return an array of best vocalization candidates
	 */
	public VocalizationCandidate[] getBestMatchingCandidates(Element domElement) {
		// FeatureDefinition featDef = this.featureFileReader.getFeatureDefinition();
		Target targetUnit = createTarget(domElement);
		int numberUnits = this.unitFileReader.getNumberOfUnits();
		VocalizationCandidate[] vocalizationCandidates = new VocalizationCandidate[numberUnits];
		for (int i = 0; i < numberUnits; i++) {
			Unit singleUnit = this.unitFileReader.getUnit(i);
			double cost = vffrtUnitCostFunction.cost(targetUnit, singleUnit);
			vocalizationCandidates[i] = new VocalizationCandidate(i, cost);
		}
		Arrays.sort(vocalizationCandidates);
		return vocalizationCandidates;
	}

	/**
	 * Debug messages for selected candidates
	 * 
	 * @param targetUnit
	 *            target unit
	 * @param suitableCandidates
	 *            suitable vocalization candidates
	 * @param suitableF0Candidates
	 *            suitable intonation candidates
	 */
	private void debugLogCandidates(Target targetUnit, VocalizationCandidate[] suitableCandidates,
			VocalizationCandidate[] suitableF0Candidates) {
		FeatureVector targetFeatures = targetUnit.getFeatureVector();
		FeatureDefinition fd = featureFileReader.getFeatureDefinition();
		int fiName = fd.getFeatureIndex("name");
		int fiIntonation = fd.getFeatureIndex("intonation");
		int fiVQ = fd.getFeatureIndex("voicequality");
		for (int i = 0; i < suitableCandidates.length; i++) {
			int unitIndex = suitableCandidates[i].unitIndex;
			double unitCost = suitableCandidates[i].cost;
			FeatureVector fv = featureFileReader.getFeatureVector(unitIndex);
			StringBuilder sb = new StringBuilder();
			sb.append("Candidate ").append(i).append(": ").append(unitIndex).append(" ( " + unitCost + " ) ").append(" -- ");
			byte bName = fv.getByteFeature(fiName);
			if (fv.getByteFeature(fiName) != 0 && targetFeatures.getByteFeature(fiName) != 0) {
				sb.append(" ").append(fv.getFeatureAsString(fiName, fd));
			}
			if (fv.getByteFeature(fiVQ) != 0 && targetFeatures.getByteFeature(fiName) != 0) {
				sb.append(" ").append(fv.getFeatureAsString(fiVQ, fd));
			}
			if (fv.getByteFeature(fiIntonation) != 0 && targetFeatures.getByteFeature(fiIntonation) != 0) {
				sb.append(" ").append(fv.getFeatureAsString(fiIntonation, fd));
			}
			for (int j = 0; j < targetFeatures.getLength(); j++) {
				if (targetFeatures.isContinuousFeature(j) && !Float.isNaN((Float) targetFeatures.getFeature(j))
						&& !Float.isNaN((Float) fv.getFeature(j))) {
					String featureName = fd.getFeatureName(j);
					sb.append(" ").append(featureName).append("=").append(fv.getFeature(j));
				}
			}
			logger.debug(sb.toString());
		}
		for (int i = 0; i < suitableF0Candidates.length; i++) {
			int unitIndex = suitableF0Candidates[i].unitIndex;
			double unitCost = suitableF0Candidates[i].cost;
			FeatureVector fv = featureFileReader.getFeatureVector(unitIndex);
			StringBuilder sb = new StringBuilder();
			sb.append("F0 Candidate ").append(i).append(": ").append(unitIndex).append(" ( " + unitCost + " ) ").append(" -- ");
			byte bName = fv.getByteFeature(fiName);
			if (fv.getByteFeature(fiName) != 0 && targetFeatures.getByteFeature(fiName) != 0) {
				sb.append(" ").append(fv.getFeatureAsString(fiName, fd));
			}
			if (fv.getByteFeature(fiVQ) != 0 && targetFeatures.getByteFeature(fiName) != 0) {
				sb.append(" ").append(fv.getFeatureAsString(fiVQ, fd));
			}
			if (fv.getByteFeature(fiIntonation) != 0 && targetFeatures.getByteFeature(fiIntonation) != 0) {
				sb.append(" ").append(fv.getFeatureAsString(fiIntonation, fd));
			}
			for (int j = 0; j < targetFeatures.getLength(); j++) {
				if (targetFeatures.isContinuousFeature(j) && !Float.isNaN((Float) targetFeatures.getFeature(j))
						&& !Float.isNaN((Float) fv.getFeature(j))) {
					String featureName = fd.getFeatureName(j);
					sb.append(" ").append(featureName).append("=").append(fv.getFeature(j));
				}
			}
			logger.debug(sb.toString());
		}
	}

	/**
	 * get a array of best candidates sorted according to cost (cost computed on f0_feature_definition features only)
	 * 
	 * @param domElement
	 *            xml request for vocalization
	 * @return VocalizationCandidate[] a array of best candidates
	 */
	private VocalizationCandidate[] getBestIntonationCandidates(Element domElement) {

		Target targetUnit = createIntonationTarget(domElement);
		int numberUnits = this.unitFileReader.getNumberOfUnits();
		VocalizationCandidate[] vocalizationCandidates = new VocalizationCandidate[numberUnits];
		for (int i = 0; i < numberUnits; i++) {
			Unit singleUnit = this.unitFileReader.getUnit(i);
			double cost = vffrtContourCostFunction.cost(targetUnit, singleUnit);
			vocalizationCandidates[i] = new VocalizationCandidate(i, cost);
		}
		Arrays.sort(vocalizationCandidates);
		return vocalizationCandidates;
	}

	/**
	 * create target from XML request
	 * 
	 * @param domElement
	 *            xml request for vocalization
	 * @return Target target represents xml request
	 */
	private Target createTarget(Element domElement) {

		// FeatureDefinition featDef = this.featureFileReader.getFeatureDefinition();
		FeatureDefinition featDef = this.featureDefinition;
		int numFeatures = featDef.getNumberOfFeatures();
		int numByteFeatures = featDef.getNumberOfByteFeatures();
		int numShortFeatures = featDef.getNumberOfShortFeatures();
		int numContiniousFeatures = featDef.getNumberOfContinuousFeatures();
		byte[] byteFeatures = new byte[numByteFeatures];
		short[] shortFeatures = new short[numShortFeatures];
		float[] floatFeatures = new float[numContiniousFeatures];
		int byteCount = 0;
		int shortCount = 0;
		int floatCount = 0;

		for (int i = 0; i < numFeatures; i++) {

			String featName = featDef.getFeatureName(i);
			String featValue = "0";

			if (featDef.isByteFeature(featName) || featDef.isShortFeature(featName)) {
				if (domElement.hasAttribute(featName)) {
					featValue = domElement.getAttribute(featName);
				}

				boolean hasFeature = featDef.hasFeatureValue(featName, featValue);
				if (!hasFeature)
					featValue = "0";

				if (featDef.isByteFeature(i)) {
					byteFeatures[byteCount++] = featDef.getFeatureValueAsByte(i, featValue);
				} else if (featDef.isShortFeature(i)) {
					shortFeatures[shortCount++] = featDef.getFeatureValueAsShort(i, featValue);
				}
			} else {
				if (domElement.hasAttribute("meaning")) {
					featValue = domElement.getAttribute("meaning");
				}
				// float contFeature = getMeaningScaleValue ( featName, featValue );
				floatFeatures[floatCount++] = getMeaningScaleValue(featName, featValue);
			}
		}

		FeatureVector newFV = featDef.toFeatureVector(0, byteFeatures, shortFeatures, floatFeatures);

		String name = "0";
		if (domElement.hasAttribute("name")) {
			name = domElement.getAttribute("name");
		}

		Target newTarget = new Target(name, domElement);
		newTarget.setFeatureVector(newFV);

		return newTarget;
	}

	/**
	 * create F0 target from XML request
	 * 
	 * @param domElement
	 *            xml request for intonation
	 * @return Target target represents xml request
	 */
	private Target createIntonationTarget(Element domElement) {

		// FeatureDefinition featDef = this.featureFileReader.getFeatureDefinition();
		FeatureDefinition featDef = this.f0FeatureDefinition;
		int numFeatures = featDef.getNumberOfFeatures();
		int numByteFeatures = featDef.getNumberOfByteFeatures();
		int numShortFeatures = featDef.getNumberOfShortFeatures();
		int numContiniousFeatures = featDef.getNumberOfContinuousFeatures();
		byte[] byteFeatures = new byte[numByteFeatures];
		short[] shortFeatures = new short[numShortFeatures];
		float[] floatFeatures = new float[numContiniousFeatures];
		int byteCount = 0;
		int shortCount = 0;
		int floatCount = 0;

		for (int i = 0; i < numFeatures; i++) {

			String featName = featDef.getFeatureName(i);
			String featValue = "0";

			if (featDef.isByteFeature(featName) || featDef.isShortFeature(featName)) {
				if (domElement.hasAttribute(featName)) {
					featValue = domElement.getAttribute(featName);
				}

				boolean hasFeature = featDef.hasFeatureValue(featName, featValue);
				if (!hasFeature)
					featValue = "0";

				if (featDef.isByteFeature(i)) {
					byteFeatures[byteCount++] = featDef.getFeatureValueAsByte(i, featValue);
				} else if (featDef.isShortFeature(i)) {
					shortFeatures[shortCount++] = featDef.getFeatureValueAsShort(i, featValue);
				}
			} else {
				if (domElement.hasAttribute("meaning")) {
					featValue = domElement.getAttribute("meaning");
				}
				// float contFeature = getMeaningScaleValue ( featName, featValue );
				floatFeatures[floatCount++] = getMeaningScaleValue(featName, featValue);
			}
		}

		FeatureVector newFV = featDef.toFeatureVector(0, byteFeatures, shortFeatures, floatFeatures);

		String name = "0";
		if (domElement.hasAttribute("name")) {
			name = domElement.getAttribute("name");
		}

		Target newTarget = new Target(name, domElement);
		newTarget.setFeatureVector(newFV);

		return newTarget;
	}

	/**
	 * get value on meaning scale as a float value
	 * 
	 * @param featureName
	 *            feature names
	 * @param meaningAttribute
	 *            meaning attribute
	 * @return a float value for a meaning feature
	 */
	private float getMeaningScaleValue(String featureName, String meaningAttribute) {

		String[] categories = meaningAttribute.split("\\s+");
		List categoriesList = Arrays.asList(categories);

		if ("anger".equals(featureName) && categoriesList.contains("anger")) {
			return 5;
		} else if ("sadness".equals(featureName) && categoriesList.contains("sadness")) {
			return 5;
		} else if ("amusement".equals(featureName) && categoriesList.contains("amusement")) {
			return 5;
		} else if ("happiness".equals(featureName) && categoriesList.contains("happiness")) {
			return 5;
		} else if ("contempt".equals(featureName) && categoriesList.contains("contempt")) {
			return 5;
		} else if ("certain".equals(featureName) && categoriesList.contains("uncertain")) {
			return -2;
		} else if ("certain".equals(featureName) && categoriesList.contains("certain")) {
			return 2;
		} else if ("agreeing".equals(featureName) && categoriesList.contains("disagreeing")) {
			return -2;
		} else if ("agreeing".equals(featureName) && categoriesList.contains("agreeing")) {
			return 2;
		} else if ("interested".equals(featureName) && categoriesList.contains("uninterested")) {
			return -2;
		} else if ("interested".equals(featureName) && categoriesList.contains("interested")) {
			return 2;
		} else if ("anticipation".equals(featureName) && categoriesList.contains("low-anticipation")) {
			return -2;
		} else if ("anticipation".equals(featureName) && categoriesList.contains("anticipation")) {
			return 2;
		} else if ("anticipation".equals(featureName) && categoriesList.contains("high-anticipation")) {
			return 2;
		} else if ("solidarity".equals(featureName) && categoriesList.contains("solidarity")) {
			return 5;
		} else if ("solidarity".equals(featureName) && categoriesList.contains("low-solidarity")) {
			return 1;
		} else if ("solidarity".equals(featureName) && categoriesList.contains("high-solidarity")) {
			return 5;
		} else if ("antagonism".equals(featureName) && categoriesList.contains("antagonism")) {
			return 5;
		} else if ("antagonism".equals(featureName) && categoriesList.contains("high-antagonism")) {
			return 5;
		} else if ("antagonism".equals(featureName) && categoriesList.contains("low-antagonism")) {
			return 1;
		}

		return Float.NaN;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy