Skip to content

Commit

Permalink
Added option to apply an old mapping to a new set of codes. This can be
Browse files Browse the repository at this point in the history
helpful when the vocabulary and/or the source data has updated.
  • Loading branch information
schuemie committed Jan 30, 2017
1 parent 6f8d827 commit 6ca6cd8
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 18 deletions.
60 changes: 42 additions & 18 deletions src/org/ohdsi/usagi/UsagiSearchEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -373,25 +373,10 @@ public List<ScoredConcept> search(String searchTerm, boolean useMlt, Collection<

recomputeScores(topDocs.scoreDocs, query);
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
Document document = reader.document(scoreDoc.doc);
int conceptId = Integer.parseInt(document.get("CONCEPT_ID"));
TargetConcept targetConcept = docIdToTargetConcept(scoreDoc.doc);
// If matchscore = 0 but it was the one concept that was automatically selected, still allow it:
if (scoreDoc.score > 0 || (filterConceptIds != null && filterConceptIds.size() == 1 && filterConceptIds.contains(conceptId))) {
TargetConcept targetConcept = new TargetConcept();
targetConcept.term = document.get("TERM");
targetConcept.conceptId = conceptId;
targetConcept.conceptName = document.get("CONCEPT_NAME");
targetConcept.conceptClass = document.get("CONCEPT_CLASS");
targetConcept.vocabulary = document.get("VOCABULARY");
targetConcept.conceptCode = document.get("CONCEPT_CODE");
targetConcept.validStartDate = document.get("VALID_START_DATE");
targetConcept.validEndDate = document.get("VALID_END_DATE");
targetConcept.invalidReason = document.get("INVALID_REASON");
for (String domain : document.get("DOMAINS").split("\n"))
targetConcept.domains.add(domain);
targetConcept.additionalInformation = document.get("ADDITIONAL_INFORMATION");
if (scoreDoc.score > 0 || (filterConceptIds != null && filterConceptIds.size() == 1 && filterConceptIds.contains(targetConcept.conceptId)))
results.add(new ScoredConcept(scoreDoc.score, targetConcept));
}
}
reorderTies(results);
removeDuplicateConcepts(results);
Expand All @@ -403,6 +388,46 @@ public List<ScoredConcept> search(String searchTerm, boolean useMlt, Collection<
return results;
}

private TargetConcept docIdToTargetConcept(int docId) {
try {
Document document = reader.document(docId);
int conceptId = Integer.parseInt(document.get("CONCEPT_ID"));
TargetConcept targetConcept = new TargetConcept();
targetConcept.term = document.get("TERM");
targetConcept.conceptId = conceptId;
targetConcept.conceptName = document.get("CONCEPT_NAME");
targetConcept.conceptClass = document.get("CONCEPT_CLASS");
targetConcept.vocabulary = document.get("VOCABULARY");
targetConcept.conceptCode = document.get("CONCEPT_CODE");
targetConcept.validStartDate = document.get("VALID_START_DATE");
targetConcept.validEndDate = document.get("VALID_END_DATE");
targetConcept.invalidReason = document.get("INVALID_REASON");
for (String domain : document.get("DOMAINS").split("\n"))
targetConcept.domains.add(domain);
targetConcept.additionalInformation = document.get("ADDITIONAL_INFORMATION");
return targetConcept;
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
return null;
}

public TargetConcept getTargetConcept(int conceptId) {
try {
Query query = conceptIdQueryParser.parse(Integer.toString(conceptId));
TopDocs topDocs = searcher.search(query, 1);
if (topDocs.totalHits > 0)
return docIdToTargetConcept(topDocs.scoreDocs[0].doc);
else
return null;
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
return null;
}

private void removeDuplicateConcepts(List<ScoredConcept> results) {
Set<Integer> seenConceptIds = new HashSet<Integer>();
Iterator<ScoredConcept> iterator = results.iterator();
Expand All @@ -428,7 +453,6 @@ else if (arg1.concept.term.toLowerCase().equals(arg1.concept.conceptName.toLower
return result;
}
});

}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/org/ohdsi/usagi/ui/Global.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@

import org.ohdsi.usagi.UsagiSearchEngine;
import org.ohdsi.usagi.ui.actions.AboutAction;
import org.ohdsi.usagi.ui.actions.ApplyPreviousMappingAction;
import org.ohdsi.usagi.ui.actions.ApproveAction;
import org.ohdsi.usagi.ui.actions.ApproveAllAction;
import org.ohdsi.usagi.ui.actions.ClearAllAction;
import org.ohdsi.usagi.ui.actions.ConceptInformationAction;
import org.ohdsi.usagi.ui.actions.ExitAction;
import org.ohdsi.usagi.ui.actions.ExportSourceToConceptMapAction;
import org.ohdsi.usagi.ui.actions.ImportAction;
import org.ohdsi.usagi.ui.actions.OpenAction;
Expand All @@ -43,6 +45,7 @@ public class Global {
public static UsagiStatusBar statusBar;

public static OpenAction openAction;
public static ApplyPreviousMappingAction applyPreviousMappingAction;
public static ImportAction importAction;
public static SaveAction saveAction;
public static SaveAsAction saveAsAction;
Expand All @@ -53,4 +56,5 @@ public class Global {
public static AboutAction aboutAction;
public static ExportSourceToConceptMapAction exportAction;
public static RebuildIndexAction rebuildIndexAction;
public static ExitAction exitAction;
}
1 change: 1 addition & 0 deletions src/org/ohdsi/usagi/ui/ImportDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ public void run() {
progressBar.setValue(Math.round(100 * Global.mapping.size() / sourceCodes.size()));
}
dialog.setVisible(false);
Global.applyPreviousMappingAction.setEnabled(true);
Global.saveAction.setEnabled(true);
Global.saveAsAction.setEnabled(true);
Global.exportAction.setEnabled(true);
Expand Down
5 changes: 5 additions & 0 deletions src/org/ohdsi/usagi/ui/UsagiMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@

import org.ohdsi.usagi.UsagiSearchEngine;
import org.ohdsi.usagi.ui.actions.AboutAction;
import org.ohdsi.usagi.ui.actions.ApplyPreviousMappingAction;
import org.ohdsi.usagi.ui.actions.ApproveAction;
import org.ohdsi.usagi.ui.actions.ApproveAllAction;
import org.ohdsi.usagi.ui.actions.ClearAllAction;
import org.ohdsi.usagi.ui.actions.ConceptInformationAction;
import org.ohdsi.usagi.ui.actions.ExitAction;
import org.ohdsi.usagi.ui.actions.ExportSourceToConceptMapAction;
import org.ohdsi.usagi.ui.actions.ImportAction;
import org.ohdsi.usagi.ui.actions.OpenAction;
Expand Down Expand Up @@ -68,6 +70,7 @@ public UsagiMain(String[] args) {
Global.conceptInformationDialog = new ConceptInformationDialog();
Global.frame = frame;
Global.openAction = new OpenAction();
Global.applyPreviousMappingAction = new ApplyPreviousMappingAction();
Global.importAction = new ImportAction();
Global.exportAction = new ExportSourceToConceptMapAction();
Global.saveAction = new SaveAction();
Expand All @@ -77,7 +80,9 @@ public UsagiMain(String[] args) {
Global.aboutAction = new AboutAction();
Global.approveAllAction = new ApproveAllAction();
Global.rebuildIndexAction = new RebuildIndexAction();
Global.exitAction = new ExitAction();

Global.applyPreviousMappingAction.setEnabled(false);
Global.saveAction.setEnabled(false);
Global.saveAsAction.setEnabled(false);
Global.exportAction.setEnabled(false);
Expand Down
2 changes: 2 additions & 0 deletions src/org/ohdsi/usagi/ui/UsagiMenubar.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ public UsagiMenubar() {

fileMenu.add(Global.openAction);
fileMenu.add(Global.importAction);
fileMenu.add(Global.applyPreviousMappingAction);
fileMenu.add(Global.exportAction);
fileMenu.add(Global.saveAction);
fileMenu.add(Global.saveAsAction);
fileMenu.add(Global.exitAction);

JMenu editMenu = new JMenu("Edit");
editMenu.setMnemonic(new Integer(KeyEvent.VK_E));
Expand Down
90 changes: 90 additions & 0 deletions src/org/ohdsi/usagi/ui/actions/ApplyPreviousMappingAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*******************************************************************************
* Copyright 2016 Observational Health Data Sciences and Informatics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.ohdsi.usagi.ui.actions;

import java.awt.event.ActionEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;

import org.ohdsi.usagi.CodeMapping;
import org.ohdsi.usagi.TargetConcept;
import org.ohdsi.usagi.ui.Global;
import org.ohdsi.usagi.ui.Mapping;

public class ApplyPreviousMappingAction extends AbstractAction {

private static final long serialVersionUID = 3420357922150237898L;

public ApplyPreviousMappingAction() {
putValue(Action.NAME, "Apply previous mapping");
putValue(Action.SHORT_DESCRIPTION, "Apply previous mapping to current code set");
}

@Override
public void actionPerformed(ActionEvent arg0) {
JFileChooser fileChooser = new JFileChooser(Global.folder);
FileFilter csvFilter = new FileNameExtensionFilter("CSV files", "csv");
fileChooser.setFileFilter(csvFilter);
if (fileChooser.showOpenDialog(Global.frame) == JFileChooser.APPROVE_OPTION) {
int mappingsUsed = 0;
int mappingsFailed = 0;
File file = fileChooser.getSelectedFile();
Mapping mapping = new Mapping();
mapping.loadFromFile(file.getAbsolutePath());
Map<String, List<TargetConcept>> codeToTargetConcept = new HashMap<String, List<TargetConcept>>();
for (CodeMapping codeMapping : mapping)
if (codeMapping.mappingStatus.equals(CodeMapping.MappingStatus.APPROVED))
codeToTargetConcept.put(codeMapping.sourceCode.sourceCode, codeMapping.targetConcepts);

for (CodeMapping codeMapping : Global.mapping) {
List<TargetConcept> targetConcepts = codeToTargetConcept.get(codeMapping.sourceCode.sourceCode);
if (targetConcepts != null) {
List<TargetConcept> newTargetConcepts = new ArrayList<TargetConcept>(targetConcepts.size());
for (TargetConcept targetConcept : targetConcepts) {
TargetConcept newTargetConcept = Global.usagiSearchEngine.getTargetConcept(targetConcept.conceptId);
if (newTargetConcept == null)
mappingsFailed++;
else
newTargetConcepts.add(newTargetConcept);

}
if (newTargetConcepts.size() > 0) {
codeMapping.targetConcepts = newTargetConcepts;
mappingsUsed++;
}
if (newTargetConcepts.size() == targetConcepts.size())
codeMapping.mappingStatus = CodeMapping.MappingStatus.APPROVED;
}
}
String message = "The old mapping contained " + codeToTargetConcept.size() + " approved mappings of which " + mappingsUsed
+ " were applied to the current mapping. " + mappingsFailed + " old target concepts could not be found in the new vocabulary.";
Global.mappingTablePanel.updateUI();
Global.mappingDetailPanel.updateUI();
JOptionPane.showMessageDialog(Global.frame, message);
}
}

}
37 changes: 37 additions & 0 deletions src/org/ohdsi/usagi/ui/actions/ExitAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright 2016 Observational Health Data Sciences and Informatics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.ohdsi.usagi.ui.actions;

import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;

public class ExitAction extends AbstractAction {

private static final long serialVersionUID = 3420357922150237898L;

public ExitAction() {
putValue(Action.NAME, "Exit");
putValue(Action.SHORT_DESCRIPTION, "Exit Usagi");
}

@Override
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}

}
1 change: 1 addition & 0 deletions src/org/ohdsi/usagi/ui/actions/OpenAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public void actionPerformed(ActionEvent arg0) {
Global.usagiSearchEngine.close();
Global.usagiSearchEngine.createDerivedIndex(Global.mapping.getSourceCodes(), Global.frame);
Global.mappingDetailPanel.doSearch();
Global.applyPreviousMappingAction.setEnabled(true);
Global.saveAction.setEnabled(true);
Global.saveAsAction.setEnabled(true);
Global.exportAction.setEnabled(true);
Expand Down

0 comments on commit 6ca6cd8

Please sign in to comment.