com.vangent.hieos.empi.match.ScoredRecord.java Source code

Java tutorial

Introduction

Here is the source code for com.vangent.hieos.empi.match.ScoredRecord.java

Source

/*
 * This code is subject to the HIEOS License, Version 1.0
 *
 * Copyright(c) 2011 Vangent, Inc.  All rights reserved.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.vangent.hieos.empi.match;

import com.vangent.hieos.empi.config.MatchFieldConfig;
import com.vangent.hieos.empi.config.MatchConfig;
import com.vangent.hieos.empi.match.MatchAlgorithm.MatchType;
import java.math.BigDecimal;
import java.util.List;
import org.apache.commons.lang.builder.ToStringBuilder;

/**
 *
 * @author Bernie Thuman
 */
public class ScoredRecord {

    private double score;
    private double goodnessOfFitScore;
    private Record record;
    private MatchConfig matchConfig;
    private double[] scores;
    private double[] distances;

    /**
     *
     * @param matchConfig
     */
    public ScoredRecord(MatchConfig matchConfig) {
        this.matchConfig = matchConfig;
        List<MatchFieldConfig> matchFieldConfigs = matchConfig.getMatchFieldConfigs();
        int numFields = matchFieldConfigs.size();
        this.scores = new double[numFields];
        this.distances = new double[numFields];
    }

    /**
     * 
     * @param fieldIndex
     * @param distance
     */
    public void setDistance(int fieldIndex, double distance) {
        this.distances[fieldIndex] = distance;
    }

    /**
     *
     * @param matchType
     */
    public void computeScores(MatchType matchType) {
        List<MatchFieldConfig> matchFieldConfigs = matchConfig.getMatchFieldConfigs();

        // Compute field-level scores.
        int fieldIndex = 0;
        double fieldWeightSum = 0.0;
        double fieldScoreSum = 0.0;
        for (MatchFieldConfig matchFieldConfig : matchFieldConfigs) {
            //if (matchType == MatchType.SUBJECT_FEED && !matchFieldConfig.isEnabledDuringSubjectAdd()) {
            // Divorce this field from any calculations.
            //    scores[fieldIndex] = -1.0;  // Not used (just an indicator for debugging).
            //} else {
            if (distances[fieldIndex] != -1.0) {
                double fieldScore = this.computeFieldScore(fieldIndex, matchFieldConfig);
                scores[fieldIndex] = fieldScore;
                fieldScore *= matchFieldConfig.getWeight();
                fieldWeightSum += matchFieldConfig.getWeight();
                fieldScoreSum += fieldScore;
            }
            //}
            ++fieldIndex;
        }

        // Compute record score.
        this.score = fieldScoreSum / fieldWeightSum;

        // Compute "goodness of fit" score (for the record).
        this.goodnessOfFitScore = this.computeGoodnessOfFitScore();
    }

    /**
     * 
     * @return
     */
    public double getScore() {
        return score;
    }

    /**
     * 
     * @return
     */
    public int getMatchScorePercentage() {
        // Round-up match score.
        BigDecimal bd = new BigDecimal(this.getScore() * 100.0);
        bd = bd.setScale(0, BigDecimal.ROUND_HALF_UP);
        return bd.intValue();
    }

    /**
     *
     * @param score
     */
    public void setScore(double score) {
        this.score = score;
    }

    /**
     *
     * @return
     */
    public Record getRecord() {
        return record;
    }

    /**
     *
     * @param record
     */
    public void setRecord(Record record) {
        this.record = record;
    }

    /**
     *
     * @return
     */
    public double[] getDistances() {
        return distances;
    }

    /**
     *
     * @return
     */
    public double getGoodnessOfFitScore() {
        return goodnessOfFitScore;
    }

    /**
     *
     * @return
     */
    public double[] getScores() {
        return scores;
    }

    /**
     *
     * @return
     */
    private double computeGoodnessOfFitScore() {
        double recordAcceptThreshold = matchConfig.getAcceptThreshold();
        double recordRejectThreshold = matchConfig.getRejectThreshold();
        double gofScore;
        if (this.score >= recordAcceptThreshold) {
            // Match.
            gofScore = 1.0;
        } else if (this.score < recordRejectThreshold) {
            // No match.
            gofScore = 0.0;
        } else {
            // Possible match.
            gofScore = (this.score - recordRejectThreshold) / (recordAcceptThreshold - recordRejectThreshold);
        }
        return gofScore;
    }

    /**
     *
     * @param fieldIndex
     * @param fieldConfig
     * @return
     */
    private double computeFieldScore(int fieldIndex, MatchFieldConfig fieldConfig) {
        double fieldAcceptThreshold = fieldConfig.getAcceptThreshold();
        double fieldRejectThreshold = fieldConfig.getRejectThreshold();
        double fieldScore;
        double fieldDistance = distances[fieldIndex];
        if (fieldDistance >= fieldAcceptThreshold) {
            // FIXME: THIS HAS BEEN CHANGED BACK TO THE ORIGINAL FRIL (inverted) implementation.
            // NOTE (BHT): The FRIL algorithm says to set the field score = 1.0 if the field
            // distances is >= the accept threshold for the field.  This FRIL implementation 
            // sets the field score equal to the field distance.
            fieldScore = 1.0;
            //fieldScore = fieldDistance;
        } else if (fieldDistance < fieldRejectThreshold) {
            // FIXME: ?
            // NOTE (BHT): Should we consider setting the field score to the field distance as above?
            fieldScore = 0.0;
        } else {
            fieldScore = (fieldDistance - fieldRejectThreshold) / (fieldAcceptThreshold - fieldRejectThreshold);
        }
        return fieldScore;
    }

    /**
     *
     * @return
     */
    @Override
    public String toString() {
        return new ToStringBuilder(this).append("record", record).append("scores", scores)
                .append("distances", distances).append("score", score).append("gofScore", goodnessOfFitScore)
                .toString();
    }
}