Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map variables #94

Merged
merged 46 commits into from Mar 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ac2f228
add mapping type for target concepts
Oct 1, 2020
7a2f336
add buttons for each mapping type
Oct 1, 2020
8e363da
read mappingtype from save file
Oct 1, 2020
b7d9b08
do not display regular on button
Oct 1, 2020
f5569f5
add ignored status and button to toggle
Oct 1, 2020
c1727d3
add toggling of ignore button
Oct 1, 2020
faafae8
refactor approve actions and add ignoreSelected
Oct 1, 2020
b879adb
refactor clear all to clear selected
Oct 1, 2020
407304a
clear existing mappings if status set to ignored
Oct 1, 2020
66ecd58
set rendering of ignored rows grey text on white
Oct 1, 2020
8545396
prevent approving of ignored and ignoring of approved mappings
Oct 1, 2020
9cc0655
render background of ignored rows as normal
Oct 1, 2020
d95490e
Merge pull request #92 from OHDSI/target-types
Oct 1, 2020
22e0e1a
Merge branch 'map-variables' into ignore-status
Oct 1, 2020
fdcb9f1
Merge pull request #93 from OHDSI/ignore-status
Oct 1, 2020
8f89c98
add author and time details to mappings
Oct 2, 2020
026a720
simplify approve/ignore author and date
Oct 2, 2020
3dc5be4
assign concept added by as <auto> upon import
Oct 2, 2020
682e13d
save and load provenance fields
Oct 2, 2020
fc3aee5
format provenance
Oct 2, 2020
9ca258f
change order of fields in usagi save file
Oct 2, 2020
cd1a3e5
refactor ImportDialog
Oct 5, 2020
bef371c
read value code, value name and unit on import
Oct 5, 2020
cc2f99c
display new source code attributes
Oct 5, 2020
c89b8dd
frequency at the end in source code panel
Oct 5, 2020
b05afe8
allow auto querying by value or unit name
Oct 5, 2020
92916a1
make value and unit fields optional in Usagi save file
Oct 5, 2020
396db8e
display term, value, unit toggle properly
Oct 5, 2020
9ce9245
flag button
Oct 5, 2020
649a298
toggle flag button upon ignore and approve
Oct 5, 2020
2dbd56c
render flagged cells with red text
Oct 5, 2020
5d3d7e9
add comboBox to change mapping target type
Oct 5, 2020
87a2b17
rename mapping type regular to event
Oct 5, 2020
bc7220d
Merge pull request #95 from OHDSI/map-provenance
Oct 5, 2020
db896f6
Merge branch 'map-variables' into import-value-unit
Oct 5, 2020
ea865b7
Merge pull request #96 from OHDSI/import-value-unit
Oct 5, 2020
4bfe5c2
Merge pull request #97 from OHDSI/flag-status
Oct 5, 2020
e6e1b11
Merge branch 'map-variables' into change-mapping-type
Oct 5, 2020
2122e69
Merge pull request #98 from OHDSI/change-mapping-type
Oct 5, 2020
943800e
fix old regular type
Oct 6, 2020
ebc1ea6
bump version
Oct 6, 2020
f16a84d
fix opening of file with value codes - sourcecode/value is unique
Oct 26, 2020
dfbd052
Merge pull request #99 from OHDSI/fix-open
Oct 26, 2020
75e362d
fix issue with loading provenance
Oct 22, 2020
437e231
save empty target without creation date
Oct 22, 2020
29e55f1
escape quote in csv with two quotes
Oct 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -11,6 +11,8 @@ DomainIds.txt
VocabularyIds.txt
vocabularyVersion.txt

local_files/

### Intellij ###
# Created by https://www.gitignore.io/api/intellij
# Edit at https://www.gitignore.io/?templates=intellij
Expand Down
54 changes: 37 additions & 17 deletions src/org/ohdsi/usagi/CodeMapping.java
@@ -1,12 +1,12 @@
/*******************************************************************************
* Copyright 2019 Observational Health Data Sciences and Informatics
*
* Copyright 2020 Observational Health Data Sciences and Informatics & The Hyve
*
* 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.
Expand All @@ -20,23 +20,43 @@

/**
* Data class for holding information on a single source code and its mapping
*
*
* @author MSCHUEMI
*
*/
public class CodeMapping {
public static enum MappingStatus {
APPROVED, UNCHECKED, AUTO_MAPPED, AUTO_MAPPED_TO_1, INVALID_TARGET
};
public enum MappingStatus {
APPROVED, UNCHECKED, AUTO_MAPPED, AUTO_MAPPED_TO_1, INVALID_TARGET, IGNORED, FLAGGED
};

public SourceCode sourceCode;
public double matchScore;
public MappingStatus mappingStatus;
public List<Concept> targetConcepts = new ArrayList<Concept>(1);
public String comment;
public SourceCode sourceCode;
public double matchScore;
public MappingStatus mappingStatus;
public List<MappingTarget> targetConcepts = new ArrayList<>(1);
public String comment;
public String statusSetBy;
public long statusSetOn;

public CodeMapping(SourceCode sourceCode) {
this.sourceCode = sourceCode;
}
public CodeMapping(SourceCode sourceCode) {
this.sourceCode = sourceCode;
}

public void setStatus(MappingStatus mappingStatus, String author) {
this.mappingStatus = mappingStatus;
this.statusSetOn = System.currentTimeMillis();
this.statusSetBy = author;
}

public void setUnchecked() {
this.mappingStatus = MappingStatus.UNCHECKED;
this.statusSetOn = 0;
this.statusSetBy = "";
}

public void approve(String approvedBy) {
setStatus(MappingStatus.APPROVED, approvedBy);
}

public void ignore(String ignoredBy) {
setStatus(MappingStatus.IGNORED, ignoredBy);
}
}
71 changes: 71 additions & 0 deletions src/org/ohdsi/usagi/MappingTarget.java
@@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright 2020 Observational Health Data Sciences and Informatics & The Hyve
*
* 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;

/**
* Class for holding information about a single (target) concept in the Vocabulary
*/
public class MappingTarget{
public enum Type {
EVENT, VALUE, UNIT // Maybe also OPERATOR, TYPE, etc.
};

public Concept concept;
public Type mappingType;
public String createdBy;
public long createdOn;

public MappingTarget() {
this.concept = Concept.createEmptyConcept();
this.mappingType = Type.EVENT;
this.createdBy = "";
this.createdOn = 0;
}

public MappingTarget(Concept concept, String createdBy) {
this(concept, Type.EVENT, createdBy);
}

public MappingTarget(Concept concept, Type mappingType, String createdBy) {
this.concept = concept;
this.mappingType = mappingType;
this.createdBy = createdBy;
this.createdOn = System.currentTimeMillis();
}

public MappingTarget(Concept concept, Type mappingType, String createdBy, long createdOn) {
this.concept = concept;
this.mappingType = mappingType;
this.createdBy = createdBy;
this.createdOn = createdOn;
}

public Concept getConcept() {
return concept;
}

public void setConcept(Concept concept) {
this.concept = concept;
}

public Type getMappingType() {
return mappingType;
}

public void setMappingType(Type mappingType) {
this.mappingType = mappingType;
}
}
37 changes: 25 additions & 12 deletions src/org/ohdsi/usagi/ReadCodeMappingsFromFile.java
@@ -1,12 +1,12 @@
/*******************************************************************************
* Copyright 2019 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.
Expand All @@ -23,7 +23,7 @@
import org.ohdsi.utilities.files.Row;

public class ReadCodeMappingsFromFile implements Iterable<CodeMapping> {
private String filename;
private final String filename;

public ReadCodeMappingsFromFile(String filename) {
this.filename = filename;
Expand All @@ -36,9 +36,9 @@ public Iterator<CodeMapping> iterator() {

public class RowIterator implements Iterator<CodeMapping> {

private Iterator<Row> iterator;
private CodeMapping buffer;
private Row row;
private Iterator<Row> iterator;
private CodeMapping buffer;
private Row row;

public RowIterator() {
iterator = new ReadCSVFileWithHeader(filename).iterator();
Expand All @@ -58,20 +58,35 @@ private void readNext() {
buffer = new CodeMapping(new SourceCode(row));
buffer.matchScore = row.getDouble("matchScore");
buffer.mappingStatus = MappingStatus.valueOf(row.get("mappingStatus"));

// Status provenance fields might not be available in older Usagi files
buffer.statusSetBy = row.get("statusSetBy", "");
buffer.statusSetOn = row.getLong("statusSetOn", "0");

try {
buffer.comment = row.get("comment");
} catch (Exception e) {
buffer.comment = "";
}
while (row != null && new SourceCode(row).sourceCode.equals(buffer.sourceCode.sourceCode)
&& new SourceCode(row).sourceName.equals(buffer.sourceCode.sourceName)) {
while (row != null
&& new SourceCode(row).sourceCode.equals(buffer.sourceCode.sourceCode)
&& new SourceCode(row).sourceName.equals(buffer.sourceCode.sourceName) // MM: is this needed?
&& new SourceCode(row).sourceValueCode.equals(buffer.sourceCode.sourceValueCode)) {
if (row.getInt("conceptId") != 0) {
Concept concept = Global.dbEngine.getConcept(row.getInt("conceptId"));

if (concept == null) {
buffer.mappingStatus = MappingStatus.INVALID_TARGET;
buffer.comment = "Invalid existing target: " + row.get("conceptId");
} else {
buffer.targetConcepts.add(concept);
// Type and provenance might not be available in older Usagi files
MappingTarget mappingTarget = new MappingTarget(
concept,
MappingTarget.Type.valueOf(row.get("mappingType", "EVENT")),
row.get("createdBy", ""),
row.getLong("createdOn", "0")
);
buffer.targetConcepts.add(mappingTarget);
}
}
if (iterator.hasNext())
Expand All @@ -98,7 +113,5 @@ public CodeMapping next() {
public void remove() {
throw new RuntimeException("Remove not supported");
}

}

}
14 changes: 13 additions & 1 deletion src/org/ohdsi/usagi/SourceCode.java
Expand Up @@ -32,16 +32,22 @@ public class SourceCode {

public String sourceCode;
public String sourceName;
public String sourceValueCode;
public String sourceValueName;
public String sourceUnitName;
public int sourceFrequency;
public Set<Integer> sourceAutoAssignedConceptIds = new HashSet<Integer>();
public List<Pair<String, String>> sourceAdditionalInfo = new ArrayList<Pair<String, String>>();

private static String ADDITIONAL_INFO_PREFIX = "ADD_INFO:";
private final static String ADDITIONAL_INFO_PREFIX = "ADD_INFO:";

public Row toRow() {
Row row = new Row();
row.add("sourceCode", sourceCode);
row.add("sourceName", sourceName);
row.add("sourceValueCode", sourceValueCode);
row.add("sourceValueName", sourceValueName);
row.add("sourceUnitName", sourceUnitName);
row.add("sourceFrequency", sourceFrequency);
row.add("sourceAutoAssignedConceptIds", StringUtilities.join(sourceAutoAssignedConceptIds, ";"));
for (Pair<String, String> pair : sourceAdditionalInfo) {
Expand All @@ -56,6 +62,12 @@ public SourceCode() {
public SourceCode(Row row) {
sourceCode = row.get("sourceCode");
sourceName = row.get("sourceName");
if (row.getFieldNames().contains("sourceValueCode")) {
// Assume that if source value code exists, then other new fields as well
sourceValueCode = row.get("sourceValueCode");
sourceValueName = row.get("sourceValueName");
sourceUnitName = row.get("sourceUnitName");
}
sourceFrequency = row.getInt("sourceFrequency");
sourceAutoAssignedConceptIds = parse(row.get("sourceAutoAssignedConceptIds"));
for (String field : row.getFieldNames())
Expand Down
17 changes: 11 additions & 6 deletions src/org/ohdsi/usagi/WriteCodeMappingsToFile.java
Expand Up @@ -32,18 +32,23 @@ public WriteCodeMappingsToFile(String filename) {
}

public void write(CodeMapping codeMapping) {
List<Concept> targetConcepts;
List<MappingTarget> mappingTargets;
if (codeMapping.targetConcepts.size() == 0) {
targetConcepts = new ArrayList<Concept>(1);
targetConcepts.add(Concept.EMPTY_CONCEPT);
mappingTargets = new ArrayList<>(1);
mappingTargets.add(new MappingTarget());
} else
targetConcepts = codeMapping.targetConcepts;
for (Concept targetConcept : targetConcepts) {
mappingTargets = codeMapping.targetConcepts;
for (MappingTarget targetConcept : mappingTargets) {
Row row = codeMapping.sourceCode.toRow();
row.add("matchScore", codeMapping.matchScore);
row.add("mappingStatus", codeMapping.mappingStatus.toString());
row.add("conceptId", targetConcept.conceptId);
row.add("statusSetBy", codeMapping.statusSetBy);
row.add("statusSetOn", codeMapping.statusSetOn);
row.add("conceptId", targetConcept.concept.conceptId);
row.add("mappingType", targetConcept.mappingType.toString());
row.add("comment", codeMapping.comment);
row.add("createdBy", targetConcept.createdBy);
row.add("createdOn", targetConcept.createdOn);
out.write(row);
}
}
Expand Down
10 changes: 3 additions & 7 deletions src/org/ohdsi/usagi/dataImport/ImportData.java
Expand Up @@ -19,13 +19,9 @@
import java.util.List;
import java.util.Vector;

import org.ohdsi.usagi.CodeMapping;
import org.ohdsi.usagi.*;
import org.ohdsi.usagi.CodeMapping.MappingStatus;
import org.ohdsi.usagi.SourceCode;
import org.ohdsi.usagi.Concept;
import org.ohdsi.usagi.UsagiSearchEngine;
import org.ohdsi.usagi.UsagiSearchEngine.ScoredConcept;
import org.ohdsi.usagi.WriteCodeMappingsToFile;
import org.ohdsi.utilities.collections.Pair;
import org.ohdsi.utilities.files.ReadCSVFileWithHeader;
import org.ohdsi.utilities.files.Row;
Expand Down Expand Up @@ -78,10 +74,10 @@ private void createInitialMapping(List<SourceCode> sourceCodes, ImportSettings s
List<ScoredConcept> concepts = usagiSearchEngine.search(sourceCode.sourceName, true, sourceCode.sourceAutoAssignedConceptIds,
settings.filterDomains, settings.filterConceptClasses, settings.filterVocabularies, settings.filterStandard, settings.includeSourceTerms);
if (concepts.size() > 0) {
codeMapping.targetConcepts.add(concepts.get(0).concept);
codeMapping.targetConcepts.add(new MappingTarget(concepts.get(0).concept, "<auto>"));
codeMapping.matchScore = concepts.get(0).matchScore;
} else {
codeMapping.targetConcepts.add(Concept.EMPTY_CONCEPT);
codeMapping.targetConcepts.add(new MappingTarget(Concept.EMPTY_CONCEPT, "<auto>"));
codeMapping.matchScore = 0;
}
codeMapping.mappingStatus = MappingStatus.UNCHECKED;
Expand Down
63 changes: 63 additions & 0 deletions src/org/ohdsi/usagi/ui/AuthorDialog.java
@@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright 2020 Observational Health Data Sciences and Informatics & The Hyve
*
* 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;

import javax.swing.*;
import java.awt.*;

public class AuthorDialog extends JDialog {

private static final long serialVersionUID = 8239922540117895957L;

public AuthorDialog() {
setTitle("Author");
setLayout(new GridBagLayout());
GridBagConstraints g = new GridBagConstraints();
g.fill = GridBagConstraints.BOTH;
g.ipadx = 5;
g.ipady = 5;

g.gridx = 0;
g.gridy = 0;
add(new JLabel("Author:"), g);

g.gridx = 1;
g.gridy = 0;
JTextFieldLimit authorField = new JTextFieldLimit(20);
authorField.setToolTipText("Please enter your name");
authorField.setPreferredSize(new Dimension(100, 10));
add(authorField, g);

g.gridx = 0;
g.gridy = 2;
g.gridwidth = 2;
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
buttonPanel.add(Box.createHorizontalGlue());
JButton saveButton = new JButton("Save");
saveButton.setToolTipText("Save your name");
saveButton.addActionListener(event -> {
Global.author = authorField.getText();
setVisible(false);
});
buttonPanel.add(saveButton);
add(buttonPanel, g);

pack();
setModal(true);
setLocationRelativeTo(Global.frame);
}
}