diff --git a/.classpath b/.classpath new file mode 100644 index 00000000..d8923924 --- /dev/null +++ b/.classpath @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5e56e040 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin diff --git a/.project b/.project new file mode 100644 index 00000000..ebaa3b16 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + WhiteRabbit + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/com.wdev91.eclipse.copyright.xml b/.settings/com.wdev91.eclipse.copyright.xml new file mode 100644 index 00000000..83008237 --- /dev/null +++ b/.settings/com.wdev91.eclipse.copyright.xml @@ -0,0 +1,41 @@ + + + + +
+
+
+ + + +
+
+ + + +
+
+
+ + + ]]> + ]]> +
+ diff --git a/jarDesc/WhiteRabbit.MF b/jarDesc/WhiteRabbit.MF new file mode 100644 index 00000000..ea937919 --- /dev/null +++ b/jarDesc/WhiteRabbit.MF @@ -0,0 +1,11 @@ +Manifest-Version: 1.0 +Class-Path: . WhiteRabbit_lib/jtds-1.3.0.jar WhiteRabbit_lib/ojdbc5.ja + r WhiteRabbit_lib/ojdbc6.jar WhiteRabbit_lib/postgresql-9.3-1101.jdbc + 41.jar WhiteRabbit_lib/sqljdbc4.jar WhiteRabbit_lib/mysql-connector-j + ava-5.1.30-bin.jar WhiteRabbit_lib/dom4j-1.6.1.jar WhiteRabbit_lib/po + i-3.9-20121203.jar WhiteRabbit_lib/poi-excelant-3.9-20121203.jar Whit + eRabbit_lib/poi-ooxml-3.9-20121203.jar WhiteRabbit_lib/poi-ooxml-sche + mas-3.9-20121203.jar WhiteRabbit_lib/stax-api-1.0.1.jar WhiteRabbit_l + ib/xmlbeans-2.3.0.jar +Main-Class: org.ohdsi.whiteRabbit.interactiveMapping.RabbitInAHat + diff --git a/jarDesc/WhiteRabbit.jardesc b/jarDesc/WhiteRabbit.jardesc new file mode 100644 index 00000000..4bfe056a --- /dev/null +++ b/jarDesc/WhiteRabbit.jardesc @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/dom4j-1.6.1.jar b/lib/dom4j-1.6.1.jar new file mode 100644 index 00000000..c8c4dbb9 Binary files /dev/null and b/lib/dom4j-1.6.1.jar differ diff --git a/lib/jtds-1.3.0.jar b/lib/jtds-1.3.0.jar new file mode 100644 index 00000000..60f119ca Binary files /dev/null and b/lib/jtds-1.3.0.jar differ diff --git a/lib/mysql-connector-java-5.1.30-bin.jar b/lib/mysql-connector-java-5.1.30-bin.jar new file mode 100644 index 00000000..afef9b2d Binary files /dev/null and b/lib/mysql-connector-java-5.1.30-bin.jar differ diff --git a/lib/ojdbc5.jar b/lib/ojdbc5.jar new file mode 100644 index 00000000..e85e3ea3 Binary files /dev/null and b/lib/ojdbc5.jar differ diff --git a/lib/ojdbc6.jar b/lib/ojdbc6.jar new file mode 100644 index 00000000..b663cd24 Binary files /dev/null and b/lib/ojdbc6.jar differ diff --git a/lib/poi-3.9-20121203.jar b/lib/poi-3.9-20121203.jar new file mode 100644 index 00000000..0f462880 Binary files /dev/null and b/lib/poi-3.9-20121203.jar differ diff --git a/lib/poi-excelant-3.9-20121203.jar b/lib/poi-excelant-3.9-20121203.jar new file mode 100644 index 00000000..cb403fa6 Binary files /dev/null and b/lib/poi-excelant-3.9-20121203.jar differ diff --git a/lib/poi-ooxml-3.9-20121203.jar b/lib/poi-ooxml-3.9-20121203.jar new file mode 100644 index 00000000..8792d463 Binary files /dev/null and b/lib/poi-ooxml-3.9-20121203.jar differ diff --git a/lib/poi-ooxml-schemas-3.9-20121203.jar b/lib/poi-ooxml-schemas-3.9-20121203.jar new file mode 100644 index 00000000..eda4ef49 Binary files /dev/null and b/lib/poi-ooxml-schemas-3.9-20121203.jar differ diff --git a/lib/postgresql-9.3-1101.jdbc41.jar b/lib/postgresql-9.3-1101.jdbc41.jar new file mode 100644 index 00000000..06fd9984 Binary files /dev/null and b/lib/postgresql-9.3-1101.jdbc41.jar differ diff --git a/lib/sqljdbc4.jar b/lib/sqljdbc4.jar new file mode 100644 index 00000000..d6b7f6da Binary files /dev/null and b/lib/sqljdbc4.jar differ diff --git a/lib/stax-api-1.0.1.jar b/lib/stax-api-1.0.1.jar new file mode 100644 index 00000000..d9a16651 Binary files /dev/null and b/lib/stax-api-1.0.1.jar differ diff --git a/lib/xmlbeans-2.3.0.jar b/lib/xmlbeans-2.3.0.jar new file mode 100644 index 00000000..ccd81634 Binary files /dev/null and b/lib/xmlbeans-2.3.0.jar differ diff --git a/src/org/ohdsi/databases/DbType.java b/src/org/ohdsi/databases/DbType.java new file mode 100644 index 00000000..e7273821 --- /dev/null +++ b/src/org/ohdsi/databases/DbType.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.databases; + +public class DbType { + public static DbType MYSQL = new DbType("mysql"); + public static DbType MSSQL = new DbType("mssql"); + public static DbType ORACLE = new DbType("oracle"); + public static DbType POSTGRESQL = new DbType("postgresql"); + + private enum Type { + MYSQL, MSSQL, ORACLE, POSTGRESQL + }; + + private Type type; + + public DbType(String type) { + this.type = Type.valueOf(type.toUpperCase()); + } + + public boolean equals(Object other) { + if (other instanceof DbType && ((DbType) other).type == type) + return true; + else + return false; + } +} diff --git a/src/org/ohdsi/databases/QueryDB.java b/src/org/ohdsi/databases/QueryDB.java new file mode 100644 index 00000000..535a2742 --- /dev/null +++ b/src/org/ohdsi/databases/QueryDB.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.databases; + +import java.io.InputStream; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Iterator; +import java.util.Map; + +import org.ohdsi.utilities.files.ReadTextFile; +import org.ohdsi.utilities.files.Row; + +public class QueryDB implements Iterable{ + private String sql; + private Connection connection; + + public QueryDB(InputStream sqlStream, Connection connection){ + this(sqlStream,null,connection); + } + + public QueryDB(InputStream sqlStream, Map parameterToValue, Connection connection){ + this.connection = connection; + sql = loadSQL(sqlStream); + if (parameterToValue != null) + for (String parameter : parameterToValue.keySet()) + sql = sql.replaceAll(parameter, parameterToValue.get(parameter)); + trimSQL(); + } + + public QueryDB(String sql, Connection connection){ + this.connection = connection; + this.sql = sql; + trimSQL(); + } + + private void trimSQL() { + sql = sql.trim(); + if (sql.endsWith(";")) + sql = sql.substring(0,sql.length()-1); + } + + private String loadSQL(InputStream sqlStream) { + StringBuilder sql = new StringBuilder(); + for (String line : new ReadTextFile(sqlStream)){ + sql.append(line.trim()); + sql.append('\n'); + } + return sql.substring(0, sql.lastIndexOf(";")); + } + + public boolean execute(){ + boolean result = false; + for (String subQuery : sql.split(";")) + try { + Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + result = statement.execute(subQuery.toString()); + } catch (SQLException e) { + if (e.getMessage().contains("ORA-00942") && sql.toUpperCase().startsWith("DROP")) + System.out.println("Tried dropping non-existing table"); + else { + System.err.println("SQL: " + subQuery); + e.printStackTrace(); + } + } + try { + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + return result; + } + + @Override + public Iterator iterator() { + return new DBRowIterator(sql); + } + public class DBRowIterator implements Iterator{ + + private ResultSet resultSet; + + private boolean hasNext; + + public DBRowIterator(String sql) { + try { + Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + resultSet = statement.executeQuery(sql.toString()); + hasNext = resultSet.next(); + if (!hasNext) + connection.close(); + } catch (SQLException e){ + System.err.println(sql.toString()); + System.err.println(e.getMessage()); + throw new RuntimeException(e); + } + } + + @Override + public boolean hasNext() { + return hasNext; + } + + @Override + public Row next() { + try { + Row row = new Row(); + ResultSetMetaData metaData; + metaData = resultSet.getMetaData(); + for (int i = 1; i < metaData.getColumnCount()+1; i++) { + String columnName = metaData.getColumnName(i); + String value = resultSet.getString(i); + if (value == null) + value = ""; + row.add(columnName, value.replace(" 00:00:00", "")); + } + hasNext = resultSet.next(); + if (!hasNext) + connection.close(); + return row; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + @Override + public void remove() { + } + } +} diff --git a/src/org/ohdsi/databases/QueryParameters.java b/src/org/ohdsi/databases/QueryParameters.java new file mode 100644 index 00000000..059c497e --- /dev/null +++ b/src/org/ohdsi/databases/QueryParameters.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.databases; + +import java.util.HashMap; +import java.util.Map; + +public class QueryParameters { + private Map key2Value = new HashMap(); + public void set(String key, String value){ + key2Value.put(key, value); + } + + public void set(String key, int value){ + key2Value.put(key, Integer.toString(value)); + } + + protected Map getMap() { + return key2Value; + } + +} diff --git a/src/org/ohdsi/databases/RichConnection.java b/src/org/ohdsi/databases/RichConnection.java new file mode 100644 index 00000000..bd690f22 --- /dev/null +++ b/src/org/ohdsi/databases/RichConnection.java @@ -0,0 +1,772 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.databases; + +import java.io.InputStream; +import java.sql.BatchUpdateException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.ohdsi.utilities.SimpleCounter; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.files.ReadCSVFileWithHeader; +import org.ohdsi.utilities.files.ReadTextFile; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.utilities.files.WriteCSVFileWithHeader; + +public class RichConnection { + public static int INSERT_BATCH_SIZE = 100000; + private Connection connection; + private Class context; // Used for locating resources + private boolean verbose = false; + private static DecimalFormat decimalFormat = new DecimalFormat("#.#"); + private Map localVariables = new HashMap(); + private DbType dbType; + + public RichConnection(String server, String domain, String user, String password, DbType dbType) { + this.connection = DBConnector.connect(server, domain, user, password, dbType); + this.dbType = dbType; + } + + /** + * Executes the SQL statement specified in the resource. The first parameter string is the parameter name, the second string the value, etc. + * + * @param resourceName + * @param parameters + */ + public void executeResource(String resourceName, Object... parameters) { + QueryParameters parameterMap = new QueryParameters(); + for (int i = 0; i < parameters.length; i += 2) + parameterMap.set(parameters[i].toString(), parameters[i + 1].toString()); + executeResource(resourceName, parameterMap); + } + + /** + * Executes the SQL statement specified in the resource + * + * @param resourceName + * @param parameters + */ + public void executeResource(String resourceName, QueryParameters parameters) { + executeResource(context.getResourceAsStream(resourceName), parameters); + } + + /** + * Executes the SQL statement specified in the resource + * + * @param sqlStream + * @param parameters + */ + public void executeResource(InputStream sqlStream, QueryParameters parameters) { + String sql = loadSQL(sqlStream); + if (parameters != null) + sql = applyVariables(sql, parameters.getMap()); + execute(sql); + } + + /** + * Executes the SQL statement specified in the resource + * + * @param sqlStream + */ + public void executeResource(InputStream sqlStream) { + executeResource(sqlStream, null); + } + + /** + * Executes the SQL statement specified in the resource + * + * @param sql + */ + public void executeResource(String sql) { + if (context == null) + throw new RuntimeException("Context not specified, unable to load resource"); + executeResource(context.getResourceAsStream(sql)); + } + + public void executeAsOne(String sql) { + try { + Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + statement.execute(sql); + } catch (SQLException e) { + System.err.println(sql); + e.printStackTrace(); + } + } + + /** + * Execute the given SQL statement. + * + * @param sql + */ + public void execute(String sql) { + try { + sql = handleSQLDefineStatements(sql); + if (sql.length() == 0) + return; + Statement statement = null; + + statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + for (String subQuery : sql.split(";")) { + if (verbose) { + String abbrSQL = subQuery.replace('\n', ' ').replace('\t', ' ').trim(); + if (abbrSQL.length() > 100) + abbrSQL = abbrSQL.substring(0, 100).trim() + "..."; + System.out.println("Adding query to batch: " + abbrSQL); + } + + statement.addBatch(subQuery); + } + long start = System.currentTimeMillis(); + if (verbose) + System.out.println("Executing batch"); + statement.executeBatch(); + if (verbose) + outputQueryStats(statement, System.currentTimeMillis() - start); + statement.close(); + } catch (SQLException e) { + System.err.println(sql); + e.printStackTrace(); + } + } + + private String handleSQLDefineStatements(String sql) { + sql = extractSQLDefineStatements(sql); + sql = applyVariables(sql, localVariables); + return sql; + } + + private String applyVariables(String sql, Map key2Value) { + List sortedKeys = new ArrayList(key2Value.keySet()); + Collections.sort(sortedKeys, new Comparator() { + + @Override + public int compare(String o1, String o2) { + if (o1.length() > o2.length()) + return 1; + else if (o1.length() < o2.length()) + return -1; + else + return 0; + } + }); + for (String key : sortedKeys) + sql = sql.replaceAll(key, key2Value.get(key)); + return sql.trim(); + } + + private String extractSQLDefineStatements(String sql) { + int start = sql.toLowerCase().indexOf("sqldefine"); + + while (start != -1) { + int end = sql.indexOf(";", start); + if (end == -1) + throw new RuntimeException("No closing semicolon found for SQLDEFINE in:\n" + sql); + + String definition = sql.substring(start, end); + int as = definition.toLowerCase().indexOf(" as"); + if (as == -1) + as = definition.toLowerCase().indexOf("\nas"); + if (as == -1) + as = definition.toLowerCase().indexOf("\tas"); + if (as == -1) + throw new RuntimeException("No AS found for SQLDEFINE in:\n" + sql); + String variableName = definition.substring("SQLDEFINE".length(), as).trim(); + String variableValue = definition.substring(as + 3).trim(); + variableValue = applyVariables(variableValue, localVariables); + if (verbose) + System.out.println("Found definition for " + variableName); + localVariables.put(variableName, variableValue); + sql = sql.substring(0, start) + " " + sql.substring(end + 1); + + start = sql.toLowerCase().indexOf("sqldefine"); + } + return sql; + } + + private void outputQueryStats(Statement statement, long ms) throws SQLException { + Throwable warning = statement.getWarnings(); + if (warning != null) + System.out.println("- SERVER: " + warning.getMessage()); + String timeString; + if (ms < 1000) + timeString = ms + " ms"; + else if (ms < 60000) + timeString = decimalFormat.format(ms / 1000d) + " seconds"; + else if (ms < 3600000) + timeString = decimalFormat.format(ms / 60000d) + " minutes"; + else + timeString = decimalFormat.format(ms / 3600000d) + " hours"; + System.out.println("- Query completed in " + timeString); + } + + public QueryResult queryResource(String resourceName) { + return queryResource(resourceName, new QueryParameters()); + } + + public QueryResult queryResource(String resourceName, QueryParameters parameters) { + if (context == null) + throw new RuntimeException("Context not specified, unable to load resource"); + return queryResource(context.getResourceAsStream(resourceName), parameters); + } + + /** + * Query the database using the SQL statement specified in the resource + * + * @param sqlStream + * @param parameters + * @return + */ + public QueryResult queryResource(InputStream sqlStream, QueryParameters parameters) { + String sql = loadSQL(sqlStream); + sql = applyVariables(sql, parameters.getMap()); + return query(sql); + } + + /** + * Query the database using the SQL statement specified in the resource + * + * @param sqlStream + * @return + */ + public QueryResult queryResource(InputStream sqlStream) { + return queryResource(sqlStream, null); + } + + /** + * Query the database using the provided SQL statement. + * + * @param sql + * @return + */ + public QueryResult query(String sql) { + return new QueryResult(sql); + } + + /** + * Switch the database to use. + * + * @param database + */ + public void use(String database) { + if (database == null) + return; + if (dbType == DbType.ORACLE) + execute("ALTER SESSION SET current_schema = " + database); + else if (dbType == DbType.POSTGRESQL) + execute("SET search_path TO " + database); + else + execute("USE " + database); + } + + public List getDatabaseNames() { + List names = new ArrayList(); + String query = null; + if (dbType == DbType.MYSQL) + query = "SHOW DATABASES"; + else if (dbType == DbType.MSSQL) + query = "SELECT name FROM master..sysdatabases"; + else + throw new RuntimeException("Database type not supported"); + + for (Row row : query(query)) + names.add(row.get(row.getFieldNames().get(0))); + return names; + } + + public List getTableNames(String database) { + List names = new ArrayList(); + String query = null; + if (dbType == DbType.MYSQL) { + if (database == null) + query = "SHOW TABLES"; + else + query = "SHOW TABLES IN " + database; + } else if (dbType == DbType.MSSQL) { + query = "SELECT name FROM " + database + ".sys.tables "; + } else if (dbType == DbType.ORACLE) { + query = "SELECT table_name FROM all_tables WHERE owner='" + database.toUpperCase() + "'"; + } else if (dbType == DbType.POSTGRESQL) { + query = "SELECT table_name FROM information_schema.tables WHERE table_schema = '" + database + "'"; + } + + for (Row row : query(query)) + names.add(row.get(row.getFieldNames().get(0))); + return names; + } + + public List getFieldNames(String table) { + List names = new ArrayList(); + if (dbType == DbType.MSSQL) { + for (Row row : query("SELECT name FROM syscolumns WHERE id=OBJECT_ID('" + table + "')")) + names.add(row.get("name")); + } else if (dbType == DbType.MYSQL) + for (Row row : query("SHOW COLUMNS FROM " + table)) + names.add(row.get("COLUMN_NAME")); + else + throw new RuntimeException("DB type not supported"); + + return names; + } + + public void dropTableIfExists(String table) { + if (dbType == DbType.ORACLE) { + try { + Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + if (verbose) { + System.out.println("Executing: TRUNCATE TABLE " + table); + } + statement.execute("TRUNCATE TABLE " + table); + if (verbose) { + System.out.println("Executing: DROP TABLE " + table); + } + statement.execute("DROP TABLE " + table); + statement.close(); + } catch (Exception e) { + if (verbose) + System.out.println(e.getMessage()); + } + } else if (dbType == DbType.MSSQL) { + execute("IF OBJECT_ID('" + table + "', 'U') IS NOT NULL DROP TABLE " + table + ";"); + } else { + execute("DROP TABLE " + table + " IF EXISTS"); + } + } + + public void dropDatabaseIfExists(String database) { + execute("DROP DATABASE " + database); + } + + /** + * Returns the row count of the specified table. + * + * @param tableName + * @return + */ + public long getTableSize(String tableName) { + if (dbType == DbType.MSSQL) + return Long.parseLong(query("SELECT COUNT(*) FROM [" + tableName + "];").iterator().next().getCells().get(0)); + else + return Long.parseLong(query("SELECT COUNT(*) FROM " + tableName + ";").iterator().next().getCells().get(0)); + } + + /** + * Close the connection to the database. + */ + public void close() { + try { + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public boolean isVerbose() { + return verbose; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + private String loadSQL(InputStream sqlStream) { + StringBuilder sql = new StringBuilder(); + for (String line : new ReadTextFile(sqlStream)) { + line = line.replaceAll("--.*", ""); // Remove comments + line = line.trim(); + if (line.length() != 0) { + sql.append(line.trim()); + sql.append('\n'); + } + } + return sql.toString(); + } + + public Class getContext() { + return context; + } + + public void setContext(Class context) { + this.context = context; + } + + public class QueryResult implements Iterable { + private String sql; + + private List iterators = new ArrayList(); + + public QueryResult(String sql) { + this.sql = sql; + } + + @Override + public Iterator iterator() { + DBRowIterator iterator = new DBRowIterator(sql); + iterators.add(iterator); + return iterator; + } + + public void close() { + for (DBRowIterator iterator : iterators) { + iterator.close(); + } + } + } + + /** + * Writes the results of a query to the specified file in CSV format. + * + * @param queryResult + * @param filename + */ + public void writeToFile(QueryResult queryResult, String filename) { + WriteCSVFileWithHeader out = new WriteCSVFileWithHeader(filename); + for (Row row : queryResult) + out.write(row); + out.close(); + } + + /** + * Reads a table from a file in CSV format, and inserts it into the database. + * + * @param filename + * @param table + * @param create + * If true, the data format is determined based on the first batch of rows and used to create the table structure. + */ + public void readFromFile(String filename, String table, boolean create) { + insertIntoTable(new ReadCSVFileWithHeader(filename).iterator(), table, create); + } + + /** + * Inserts the rows into a table in the database. + * + * @param iterator + * @param tableName + * @param create + * If true, the data format is determined based on the first batch of rows and used to create the table structure. + */ + public void insertIntoTable(Iterator iterator, String table, boolean create) { + List batch = new ArrayList(INSERT_BATCH_SIZE); + + boolean first = true; + SimpleCounter counter = new SimpleCounter(1000000, true); + while (iterator.hasNext()) { + if (batch.size() == INSERT_BATCH_SIZE) { + if (first && create) + createTable(table, batch); + insert(table, batch); + batch.clear(); + first = false; + } + batch.add(iterator.next()); + counter.count(); + } + if (batch.size() != 0) { + if (first && create) + createTable(table, batch); + insert(table, batch); + } + } + + // private Map getNumericFieldsInPostgreSQL(String table) { + // Map fieldToType = new HashMap(); + // for (Row row : query("SELECT column_name, data_type FROM information_schema.columns WHERE table_name = '" + table + "'")) + // fieldToType.put(row.get("column_name"), row.get("data_type")); + // return fieldToType; + // } + + private void insert(String tableName, List rows) { + List columns = null; + columns = rows.get(0).getFieldNames(); + for (int i = 0; i < columns.size(); i++) + columns.set(i, columnNameToSqlName(columns.get(i))); + + String sql = "INSERT INTO " + tableName; + sql = sql + " (" + StringUtilities.join(columns, ",") + ")"; + sql = sql + " VALUES (?"; + for (int i = 1; i < columns.size(); i++) + sql = sql + ",?"; + sql = sql + ")"; + try { + connection.setAutoCommit(false); + PreparedStatement statement = connection.prepareStatement(sql); + for (Row row : rows) { + for (int i = 0; i < columns.size(); i++) { + String value = row.get(columns.get(i)); + if (value == null) + System.out.println(row.toString()); + if (value.length() == 0) + value = null; + // System.out.println(value); + if (dbType == DbType.POSTGRESQL) // PostgreSQL does not allow unspecified types + statement.setObject(i + 1, value, Types.OTHER); + else if (dbType == DbType.ORACLE) { + if (isDate(value)) { + // System.out.println(value); + statement.setDate(i + 1, java.sql.Date.valueOf(value)); + + } else + statement.setString(i + 1, value); + } else + statement.setString(i + 1, value); + } + statement.addBatch(); + } + statement.executeBatch(); + connection.commit(); + statement.close(); + connection.setAutoCommit(true); + connection.clearWarnings(); + } catch (SQLException e) { + e.printStackTrace(); + if (e instanceof BatchUpdateException) { + System.err.println(((BatchUpdateException) e).getNextException().getMessage()); + } + } + } + + private static boolean isDate(String string) { + if (string != null && string.length() == 10 && string.charAt(4) == '-' && string.charAt(7) == '-') + try { + int year = Integer.parseInt(string.substring(0, 4)); + if (year < 1700 || year > 2200) + return false; + int month = Integer.parseInt(string.substring(5, 7)); + if (month < 1 || month > 12) + return false; + int day = Integer.parseInt(string.substring(8, 10)); + if (day < 1 || day > 31) + return false; + return true; + } catch (Exception e) { + return false; + } + return false; + } + + private Set createTable(String tableName, List rows) { + Set numericFields = new HashSet(); + Row firstRow = rows.get(0); + List fields = new ArrayList(rows.size()); + for (String field : firstRow.getFieldNames()) + fields.add(new FieldInfo(field)); + for (Row row : rows) { + for (FieldInfo fieldInfo : fields) { + String value = row.get(fieldInfo.name); + if (fieldInfo.isNumeric && !StringUtilities.isInteger(value)) + fieldInfo.isNumeric = false; + if (value.length() > fieldInfo.maxLength) + fieldInfo.maxLength = value.length(); + } + } + + StringBuilder sql = new StringBuilder(); + sql.append("CREATE TABLE " + tableName + " (\n"); + for (FieldInfo fieldInfo : fields) { + sql.append(" " + fieldInfo.toString() + ",\n"); + if (fieldInfo.isNumeric) + numericFields.add(fieldInfo.name); + } + sql.append(");"); + execute(sql.toString()); + return numericFields; + } + + private String columnNameToSqlName(String name) { + return name.replaceAll(" ", "_").replace("-", "_").replace(",", "_").replaceAll("_+", "_"); + } + + private class FieldInfo { + public String name; + public boolean isNumeric = true; + public int maxLength = 0; + + public FieldInfo(String name) { + this.name = name; + } + + public String toString() { + if (dbType == DbType.MYSQL) { + if (isNumeric) + return columnNameToSqlName(name) + " int(" + maxLength + ")"; + else if (maxLength > 255) + return columnNameToSqlName(name) + " text"; + else + return columnNameToSqlName(name) + " varchar(255)"; + } else if (dbType == DbType.MSSQL) { + if (isNumeric) { + if (maxLength < 10) + return columnNameToSqlName(name) + " int"; + else + return columnNameToSqlName(name) + " bigint"; + } else if (maxLength > 255) + return columnNameToSqlName(name) + " varchar(max)"; + else + return columnNameToSqlName(name) + " varchar(255)"; + } else + throw new RuntimeException("Create table syntax not specified for type " + dbType); + } + } + + public void copyTable(String sourceDatabase, String sourceTable, RichConnection targetConnection, String targetDatabase, String targetTable) { + StringBuilder sql = new StringBuilder(); + sql.append("CREATE TABLE "); + sql.append(targetDatabase); + if (targetConnection.dbType == DbType.MSSQL) + sql.append(".dbo."); + else + sql.append("."); + sql.append(targetTable); + sql.append("("); + boolean first = true; + String query; + if (dbType == DbType.ORACLE || dbType == DbType.MSSQL) + query = "SELECT COLUMN_NAME,DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG='" + sourceDatabase + "' AND TABLE_NAME='" + sourceTable + + "';"; + else + // mysql + query = "SELECT COLUMN_NAME,DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '" + sourceDatabase + "' AND TABLE_NAME = '" + + sourceTable + "';"; + + for (Row row : query(query)) { + if (first) + first = false; + else + sql.append(','); + sql.append(row.get("COLUMN_NAME")); + sql.append(' '); + if (targetConnection.dbType == DbType.ORACLE) { + if (row.get("DATA_TYPE").equals("bigint")) + sql.append("number"); + else + sql.append(row.get("DATA_TYPE")); + } else { + sql.append(row.get("DATA_TYPE")); + if (row.get("DATA_TYPE").equals("varchar")) + sql.append("(max)"); + } + } + sql.append(");"); + targetConnection.execute(sql.toString()); + targetConnection.use(targetDatabase); + targetConnection.insertIntoTable(query("SELECT * FROM " + sourceDatabase + ".dbo." + sourceTable).iterator(), targetTable, false); + } + + private class DBRowIterator implements Iterator { + + private ResultSet resultSet; + + private boolean hasNext; + + private Set columnNames = new HashSet(); + + public DBRowIterator(String sql) { + try { + sql.trim(); + if (sql.endsWith(";")) + sql = sql.substring(0, sql.length() - 1); + if (verbose) { + String abbrSQL = sql.replace('\n', ' ').replace('\t', ' ').trim(); + if (abbrSQL.length() > 100) + abbrSQL = abbrSQL.substring(0, 100).trim() + "..."; + System.out.println("Executing query: " + abbrSQL); + } + long start = System.currentTimeMillis(); + Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + resultSet = statement.executeQuery(sql.toString()); + hasNext = resultSet.next(); + if (verbose) + outputQueryStats(statement, System.currentTimeMillis() - start); + } catch (SQLException e) { + System.err.println(sql.toString()); + System.err.println(e.getMessage()); + throw new RuntimeException(e); + } + } + + public void close() { + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + resultSet = null; + hasNext = false; + } + } + + @Override + public boolean hasNext() { + return hasNext; + } + + @Override + public Row next() { + try { + Row row = new Row(); + ResultSetMetaData metaData; + metaData = resultSet.getMetaData(); + columnNames.clear(); + + for (int i = 1; i < metaData.getColumnCount() + 1; i++) { + String columnName = metaData.getColumnName(i); + if (columnNames.add(columnName)) { + String value = resultSet.getString(i); + if (value == null) + value = ""; + + row.add(columnName, value.replace(" 00:00:00", "")); + } + } + hasNext = resultSet.next(); + if (!hasNext) { + resultSet.close(); + resultSet = null; + } + return row; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + @Override + public void remove() { + } + } +} diff --git a/src/org/ohdsi/ooxml/CustomXWPFDocument.java b/src/org/ohdsi/ooxml/CustomXWPFDocument.java new file mode 100644 index 00000000..170937f9 --- /dev/null +++ b/src/org/ohdsi/ooxml/CustomXWPFDocument.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.ooxml; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.xwpf.usermodel.Document; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlToken; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; +import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline; + +/** + * This class offers workaround for bug in Apache POI, allowing images to be inserted + * + * @author MSCHUEMI + */ +public class CustomXWPFDocument extends XWPFDocument { + + public CustomXWPFDocument() { + super(); + } + + public CustomXWPFDocument(InputStream in) throws IOException { + super(in); + } + + public void addPicture(BufferedImage image, int width, int height) throws InvalidFormatException, FileNotFoundException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + ImageIO.write(image, "PNG", out); + } catch (IOException e) { + e.printStackTrace(); + } + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + addPicture(in, Document.PICTURE_TYPE_PNG, width, height); + } + + public void addPicture(String filename, int type, int width, int height) throws InvalidFormatException, FileNotFoundException { + addPicture(new FileInputStream(filename), type, width, height); + } + + public void addPicture(InputStream inputStream, int type, int width, int height) throws InvalidFormatException, FileNotFoundException { + String id = addPictureData(inputStream, type); + createPicture(id, getNextPicNameNumber(type), width, height); + } + + private void createPicture(String blipId, int id, int width, int height) { + final int EMU = 9525; + width *= EMU; + height *= EMU; + CTInline inline = createParagraph().createRun().getCTR().addNewDrawing().addNewInline(); + + String picXml = "" + "" + + " " + + " " + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + " " + " " + ""; + + XmlToken xmlToken = null; + try { + xmlToken = XmlToken.Factory.parse(picXml); + } catch (XmlException xe) { + xe.printStackTrace(); + } + inline.set(xmlToken); + + inline.setDistT(0); + inline.setDistB(0); + inline.setDistL(0); + inline.setDistR(0); + + CTPositiveSize2D extent = inline.addNewExtent(); + extent.setCx(width); + extent.setCy(height); + + CTNonVisualDrawingProps docPr = inline.addNewDocPr(); + docPr.setId(id); + docPr.setName("Picture " + id); + docPr.setDescr("Generated"); + } +} diff --git a/src/org/ohdsi/ooxml/ReadXlsxFileWithHeader.java b/src/org/ohdsi/ooxml/ReadXlsxFileWithHeader.java new file mode 100644 index 00000000..f85dcc57 --- /dev/null +++ b/src/org/ohdsi/ooxml/ReadXlsxFileWithHeader.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.ooxml; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.ohdsi.utilities.files.Row; + +public class ReadXlsxFileWithHeader implements Iterable { + private InputStream inputstream; + + public ReadXlsxFileWithHeader(String filename) { + try { + inputstream = new FileInputStream(filename); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + + public ReadXlsxFileWithHeader(InputStream inputstream) { + this.inputstream = inputstream; + } + + @Override + public Iterator iterator() { + return new RowIterator(); + } + + public class RowIterator implements Iterator { + + private Iterator iterator; + private Map fieldName2ColumnIndex; + private DecimalFormat myFormatter = new DecimalFormat("###############.################"); + + public RowIterator() { + try { + XSSFWorkbook workbook = new XSSFWorkbook(inputstream); + XSSFSheet sheet = workbook.getSheetAt(0); + iterator = sheet.iterator(); + fieldName2ColumnIndex = new HashMap(); + for (Cell header : iterator.next()) + fieldName2ColumnIndex.put(header.toString(), fieldName2ColumnIndex.size()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Row next() { + List cells = new ArrayList(fieldName2ColumnIndex.size()); + for (Cell cell : iterator.next()) { + String text; + if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) + text = myFormatter.format(cell.getNumericCellValue()); + else + text = cell.toString(); + cells.add(text); + } + for (int i = cells.size(); i < fieldName2ColumnIndex.size(); i++) + cells.add(""); + return new Row(cells, fieldName2ColumnIndex); + } + + @Override + public void remove() { + throw new RuntimeException("Remove not supported"); + } + + } +} diff --git a/src/org/ohdsi/utilities/DirectoryUtilities.java b/src/org/ohdsi/utilities/DirectoryUtilities.java new file mode 100644 index 00000000..ea89fbd0 --- /dev/null +++ b/src/org/ohdsi/utilities/DirectoryUtilities.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class DirectoryUtilities { + public static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + String[] children = dir.list(); + for (int i=0; i 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } + } + + public static List getFileListing(File dir) { + List result = new ArrayList(); + for(String filename: dir.list()) + result.add(new File(dir, filename)); + return result; + } + + private static List getPathList(File f) { + List l = new ArrayList(); + File r; + r = f.getAbsoluteFile(); + while(r != null) { + l.add(r.getName()); + r = r.getParentFile(); + } + return l; + } + + + private static String matchPathLists(List r,List f) { + int i; + int j; + String s; + // start at the beginning of the lists + // iterate while both lists are equal + s = ""; + i = r.size()-1; + j = f.size()-1; + + // first eliminate common root + while((i >= 0)&&(j >= 0)&&(r.get(i).equals(f.get(j)))) { + i--; + j--; + } + + // for each remaining level in the home path, add a .. + for(;i>=0;i--) { + s += ".." + File.separator; + } + + // for each level in the file path, add the path + for(;j>=1;j--) { + s += f.get(j) + File.separator; + } + + // file name + s += f.get(j); + return s; + } + + + public static String getRelativePath(File home,File f){ + return matchPathLists(getPathList(home),getPathList(f)); + } + + + +} diff --git a/src/org/ohdsi/utilities/RandomUtilities.java b/src/org/ohdsi/utilities/RandomUtilities.java new file mode 100644 index 00000000..16d03bfc --- /dev/null +++ b/src/org/ohdsi/utilities/RandomUtilities.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class RandomUtilities { + public static List sampleWithoutReplacement(List items, int sampleSize) { + if (sampleSize > items.size()) { + return items; + } + Random random = new Random(); + List sample = new ArrayList(); + for (int i = 0; i < sampleSize; i++) + sample.add(items.remove(random.nextInt(items.size()))); + return sample; + } + + public static int[] sampleWithoutReplacement(int minValue, int maxValue, int sampleSize) { + if (sampleSize > (maxValue - minValue + 1)) { + int[] sample = new int[maxValue - minValue + 1]; + for (int i = minValue; i <= maxValue; i++) + sample[i - minValue] = i; + return sample; + } else { + Random random = new Random(); + int[] sample = new int[sampleSize]; + for (int i = 0; i < sampleSize; i++) { + int number = random.nextInt(maxValue - minValue + 1); + while (contains(sample, number)) + number = random.nextInt(maxValue - minValue + 1); + sample[i] = number; + } + return sample; + } + + } + + private static boolean contains(int[] sample, int number) { + for (int i : sample) + if (i == number) + return true; + return false; + } + +} diff --git a/src/org/ohdsi/utilities/SimpleCounter.java b/src/org/ohdsi/utilities/SimpleCounter.java new file mode 100644 index 00000000..770c9184 --- /dev/null +++ b/src/org/ohdsi/utilities/SimpleCounter.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities; + +public class SimpleCounter { + private int reportN; + private long count; + private long lastTime; + private long lastCount; + private boolean reportRate = false; + + public SimpleCounter(int reportN) { + this.reportN = reportN; + count = 0; + lastCount = 0; + lastTime = System.currentTimeMillis(); + } + + public SimpleCounter(int reportN, boolean reportRate){ + this(reportN); + setReportRate(reportRate); + } + + public void count() { + count++; + if (count % reportN == 0) + report(); + } + + private void report() { + if (reportRate){ + long interval = System.currentTimeMillis() - lastTime; + long processed = count - lastCount; + System.out.println(count + " (time per unit = " + interval/(double)processed + "ms)"); + lastTime = System.currentTimeMillis(); + lastCount = count; + } else + System.out.println(count); + } + + public void finish() { + report(); + } + + public long getCount() { + return count; + } + + public boolean isReportRate() { + return reportRate; + } + + public void setReportRate(boolean value) { + this.reportRate = value; + } +} diff --git a/src/org/ohdsi/utilities/StringUtilities.java b/src/org/ohdsi/utilities/StringUtilities.java new file mode 100644 index 00000000..36f2651e --- /dev/null +++ b/src/org/ohdsi/utilities/StringUtilities.java @@ -0,0 +1,873 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Iterator; +import java.util.List; +import java.util.zip.DataFormatException; + +public class StringUtilities { + + public static long SECOND = 1000; + public static long MINUTE = 60 * SECOND; + public static long HOUR = 60 * MINUTE; + public static long DAY = 24 * HOUR; + public static long WEEK = 7 * DAY; + public static long YEAR = 365 * DAY; + public static long CENTURY = 100 * YEAR; + public static long MILLENIUM = 1000 * YEAR; + public static long MISSING_DATE = -999999; + + private static Calendar calendar = new GregorianCalendar(); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static String joinSorted(Collection s, String delimiter) { + List list = new ArrayList(s); + Collections.sort(list); + return join(list, delimiter); + } + + public static String join(Collection s, String delimiter) { + StringBuffer buffer = new StringBuffer(); + Iterator iter = s.iterator(); + if (iter.hasNext()) { + buffer.append(iter.next().toString()); + } + while (iter.hasNext()) { + buffer.append(delimiter); + buffer.append(iter.next().toString()); + } + return buffer.toString(); + } + + public static String join(Object[] objects, String delimiter) { + StringBuffer buffer = new StringBuffer(); + if (objects.length != 0) + buffer.append(objects[0].toString()); + for (int i = 1; i < objects.length; i++) { + buffer.append(delimiter); + buffer.append(objects[i].toString()); + } + return buffer.toString(); + } + + public static int twoHexDigitsToInt(String value, int index) { + return Integer.parseInt(value.substring(index, index + 2), 16); + } + + public static boolean isInteger(String string) { + try { + Integer.parseInt(string); + } catch (NumberFormatException e) { + return false; + } + return true; + } + + public static boolean isLong(String string) { + try { + Long.parseLong(string); + } catch (NumberFormatException e) { + return false; + } + return true; + } + + // private static Pattern numberPattern = Pattern.compile("^-?\\d[0-9]*(\\.[0-9]+)?((E|e)-?[0-9]*)?\\d$"); + + public static boolean isNumber(String string) { + try { + Double.parseDouble(string); + } catch (Exception e) { + return false; + } + return true; + // string.trim(); + // if (string.length() == 1) { + // return Character.isDigit(string.charAt(0)); + // } + // return numberPattern.matcher(string).matches(); + } + + public static boolean isRomanNumeral(String string) { + return (string.equals("I") || string.equals("II") || string.equals("III") || string.equals("IV") || string.equals("V") || string.equals("VI") + || string.equals("VII") || string.equals("VIII") || string.equals("IX") || string.equals("IX")); + } + + public static boolean isGreekLetter(String string) { + String lcstring = string.toLowerCase(); + return (lcstring.equals("alpha") || lcstring.equals("beta") || lcstring.equals("gamma") || lcstring.equals("delta") || lcstring.equals("epsilon") + || lcstring.equals("zeta") || lcstring.equals("eta") || lcstring.equals("theta") || lcstring.equals("iota") || lcstring.equals("kappa") + || lcstring.equals("lambda") || lcstring.equals("mu") || lcstring.equals("nu") || lcstring.equals("xi") || lcstring.equals("omicron") + || lcstring.equals("pi") || lcstring.equals("rho") || lcstring.equals("sigma") || lcstring.equals("tau") || lcstring.equals("upsilon") + || lcstring.equals("phi") || lcstring.equals("chi") || lcstring.equals("psi") || lcstring.equals("omega")); + } + + // Adds PSF file specific escape characters to string + // Author: Martijn + public static String escape(String string) { + StringBuffer result = new StringBuffer(); + for (int i = 0; i < string.length(); i++) { + char currentChar = string.charAt(i); + if (currentChar == '"' || currentChar == '?' || currentChar == ';' || currentChar == '\\' || currentChar == '|') { + result.append('\\'); + } + result.append(currentChar); + } + return result.toString(); + } + + // Removes any escape characters from string + // Author: Martijn + public static String unescape(String string) { + StringBuffer result = new StringBuffer(); + if (string.length() > 0) { + if (string.charAt(0) == '"' && string.charAt(string.length() - 1) == '"') { + result.append(string.substring(1, string.length() - 1)); + } else { + boolean escape = false; + char currentchar; + for (int i = 0; i < string.length(); i++) { + currentchar = string.charAt(i); + if (escape) { + escape = false; + result.append(currentchar); + } else { + if (currentchar == '\\') { + escape = true; + } else { + result.append(currentchar); + } + } + } + } + } + return result.toString(); + } + + // Safesplit works the same as default split, but takes escapes into account + // Author: Martijn + public static List safeSplit(String string, char delimiter) { + List result = new ArrayList(); + if (string.length() == 0) { + result.add(""); + return result; + } + boolean literal = false; + boolean escape = false; + int startpos = 0; + int i = 0; + char currentchar; + while (i < string.length()) { + currentchar = string.charAt(i); + if (currentchar == '"' && !escape) { + literal = !literal; + } + if (!literal && (currentchar == delimiter && !escape)) { + result.add(string.substring(startpos, i)); + startpos = i + 1; + } + if (currentchar == '\\') { + escape = !escape; + } else { + escape = false; + } + i++; + } + result.add(string.substring(startpos, i)); + return result; + } + + public static boolean containsNumber(String string) { + for (int i = 0; i < string.length(); i++) { + if ((int) string.charAt(i) < 58 && (int) string.charAt(i) > 47) { + return true; + } + } + return false; + } + + public static int countNumbers(String string) { + int total = 0; + for (int i = 0; i < string.length(); i++) { + if ((int) string.charAt(i) < 58 && (int) string.charAt(i) > 47) { + total++; + } + } + return total; + } + + public static boolean containsLetter(String string) { + for (int i = 0; i < string.length(); i++) { + if (Character.isLetter(string.charAt(i))) { + return true; + } + } + return false; + } + + public static int countLetters(String string) { + int total = 0; + for (int i = 0; i < string.length(); i++) { + if (Character.isLetter(string.charAt(i))) { + total++; + } + } + return total; + } + + public static boolean containsCurlyBracket(String string) { + for (int i = 0; i < string.length(); i++) { + if (isCurlyBracket(string.charAt(i))) { + return true; + } + } + return false; + } + + public static boolean containsParenthesis(String string) { + for (int i = 0; i < string.length(); i++) { + if (isParenthesis(string.charAt(i))) { + return true; + } + } + return false; + } + + public static boolean containsBracket(String string) { + for (int i = 0; i < string.length(); i++) { + if (isBracket(string.charAt(i))) { + return true; + } + } + return false; + } + + public static boolean containsArrow(String string) { + for (int i = 0; i < string.length(); i++) { + if (isArrow(string.charAt(i))) { + return true; + } + } + return false; + } + + public static boolean isParenthesis(char ch) { + return (ch == ('(') || ch == (')')); + } + + // Checks whether the word is a brackets + // Author: Kristina + public static boolean isBracket(char ch) { + return (ch == ('[') || ch == (']')); + } + + public static boolean isArrow(char ch) { + return (ch == ('<') || ch == ('>')); + } + + // Checks whether the word is a curly bracket + // Author: Kristina + public static boolean isCurlyBracket(char ch) { + return (ch == ('{') || ch == ('}')); + } + + // Converts a string to a list of words + // Author: Martijn + public static List mapToWords(String string) { + List result = new ArrayList(); + + int start = 0; + int i = 0; + for (; i < string.length(); i++) { + char ch = string.charAt(i); + if (!Character.isLetterOrDigit(ch) + && !(ch == '\'' && i > 0 && Character.isLetter(string.charAt(i - 1)) && string.length() - 1 > i && string.charAt(i + 1) == 's' && (string + .length() - 2 == i || !Character.isLetterOrDigit(string.charAt(i + 2))))) { // leaves ' in possesive pattern + if (start != i) { + result.add(string.substring(start, i)); + } + start = i + 1; + } + } + if (start != i) { + result.add(string.substring(start, i)); + } + return result; + } + + // Returns a string with the current time + // Author: Martijn + public static String now() { + Date d = new Date(); + DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); + return df.format(d); + } + + public static void outputWithTime(String message) { + System.out.println(now() + "\t" + message); + } + + // Checks whether the word is an abbreviation + // Author: Martijn + public static boolean isAbbr(String word) { + int lowercase = 0; + int uppercase = 0; + int charInt = 0; + for (int i = 0; i < word.length(); i++) { + charInt = (int) word.charAt(i); + if (charInt < 58) { + if (charInt > 47) { + }// its a number + } else if (charInt < 91) { + if (charInt > 64) { + uppercase++; + } + } else if (charInt < 123 && charInt > 96) { + lowercase++; + } + } + return (uppercase > 0 && lowercase < uppercase); + } + + /** + * If only the first letter of a word is a capital, the word is reduced to lowercase, else the original string is returned + * + * @param string + * @return + */ + public static String firstLetterToLowerCase(String string) { + boolean uppercase = false; + int charInt = 0; + for (int i = 1; i < string.length(); i++) { + charInt = (int) string.charAt(i); + if (charInt < 91) + if (charInt > 64) { + uppercase = true; + break; + } + } + if (!uppercase) + return string.toLowerCase(); + else + return string; + } + + public static int countsCharactersInUpperCase(String string) { + int uppercase = 0; + int charInt = 0; + for (int i = 0; i < string.length(); i++) { + charInt = (int) string.charAt(i); + if (charInt > 64 && charInt < 91) { + uppercase++; + } + } + return uppercase; + } + + public static int countsCharactersInLowerCase(String string) { + int lowercase = 0; + int charInt = 0; + for (int i = 0; i < string.length(); i++) { + charInt = (int) string.charAt(i); + if (charInt > 96 && charInt < 123) { + lowercase++; + } + } + return lowercase; + } + + // Converts a double to a formatted string. Examples of valid patterns are: + // "###,###.###" + // "###.##" + // "000000.000" + // "$###,###.###" + // "\u00a5###,###.###" + // # indicates optional number, 0 indicates forced number (will be printed as 0 when 0) + // Author: Martijn + public static String formatNumber(String pattern, double number) { + DecimalFormat myFormatter = new DecimalFormat(pattern); + return myFormatter.format(number); + } + + public static boolean isPlural(String string) { + if (string.length() > 1) + if (string.charAt(string.length() - 1) == 's') + if (Character.isLetter(string.charAt(string.length() - 2))) + return true; + return false; + } + + public static String findBetween(String source, String pre, String post) { + int start = source.indexOf(pre); + if (start == -1) + return ""; + int end = source.indexOf(post, start + pre.length()); + if (end == -1) + return ""; + return source.substring(start + pre.length(), end); + } + + public static List multiFindBetween(String source, String pre, String post) { + List result = new ArrayList(); + int start = 0; + int end = 0; + while (start != -1 && end != -1) { + start = source.indexOf(pre, end); + if (start != -1) { + end = source.indexOf(post, start + pre.length()); + if (end != -1) + result.add(source.substring(start + pre.length(), end)); + } + } + return result; + } + + /** + * Returns true if every parenthesis in the string is matched + * + * @param string + * @return + */ + public static boolean parenthesisMatch(String string) { + int count = 0; + for (int i = 0; i < string.length(); i++) { + char ch = string.charAt(i); + if (ch == '(') + count++; + else if (ch == ')') { + count--; + if (count == -1) + return false; + } + } + return (count == 0); + } + + public static int count(String s, char ch) { + int cnt = 0; + for (int i = 0; i < s.length(); i++) + if (s.charAt(i) == ch) + cnt++; + return cnt; + } + + /** + * Removes parenthesis and what is within the parenthesis from the string. For example: 'cold (disease)' -> 'cold ' + * + * @param string + * @return + */ + public static String removeParenthesisAndContent(String string) { + StringBuilder result = new StringBuilder(); + int count = 0; + for (int i = 0; i < string.length(); i++) { + char ch = string.charAt(i); + if (ch == '(') + count++; + else if (ch == ')') { + count--; + } else if (count == 0) + result.append(ch); + } + return result.toString(); + } + + public static String daysToSortableDateString(long days) { + long ms = days * DAY; + // Calendar calendar = new GregorianCalendar(); + ms -= calendar.getTimeZone().getOffset(ms); + calendar.setTimeInMillis(ms); + StringBuilder sb = new StringBuilder(); + sb.append(calendar.get(Calendar.YEAR)); + sb.append(StringUtilities.formatNumber("00", calendar.get(Calendar.MONTH) + 1)); + sb.append(StringUtilities.formatNumber("00", calendar.get(Calendar.DATE))); + return sb.toString(); + } + + public static String daysToDatabaseDateString(long days) { + if (days == MISSING_DATE) + return ""; + long ms = days * DAY; + ms -= calendar.getTimeZone().getOffset(ms); + calendar.setTimeInMillis(ms); + StringBuilder sb = new StringBuilder(); + sb.append(calendar.get(Calendar.YEAR)); + sb.append("-"); + sb.append(StringUtilities.formatNumber("00", calendar.get(Calendar.MONTH) + 1)); + sb.append("-"); + sb.append(StringUtilities.formatNumber("00", calendar.get(Calendar.DATE))); + return sb.toString(); + } + + public static String daysToCalendarYear(long days) { + long ms = days * DAY; + ms -= calendar.getTimeZone().getOffset(ms); + calendar.setTimeInMillis(ms); + return Integer.toString(calendar.get(Calendar.YEAR)); + } + + public static String dateToCalendarYear(Date date) { + calendar.setTime(date); + return Integer.toString(calendar.get(Calendar.YEAR)); + } + + public static String daysToCalendarMonth(long days) { + long ms = days * DAY; + ms -= calendar.getTimeZone().getOffset(ms); + calendar.setTimeInMillis(ms); + return Integer.toString(calendar.get(Calendar.MONTH) + 1); + } + + public static String daysToCalendarDayOfMonth(long days) { + long ms = days * DAY; + ms -= calendar.getTimeZone().getOffset(ms); + calendar.setTimeInMillis(ms); + return Integer.toString(calendar.get(Calendar.DATE) + 1); + } + + public static String daysToCalendarQuarterYear(long days) { + long ms = days * DAY; + ms -= calendar.getTimeZone().getOffset(ms); + calendar.setTimeInMillis(ms); + return Integer.toString(1 + (calendar.get(Calendar.MONTH) / 3)); + } + + public static String millisecondsToSortableTimeString(long ms) { + // Calendar calendar = new GregorianCalendar(); + ms -= calendar.getTimeZone().getOffset(ms + 2 * HOUR); + calendar.setTimeInMillis(ms); + StringBuilder sb = new StringBuilder(); + sb.append(calendar.get(Calendar.YEAR)); + sb.append(StringUtilities.formatNumber("00", calendar.get(Calendar.MONTH) + 1)); + sb.append(StringUtilities.formatNumber("00", calendar.get(Calendar.DATE))); + sb.append(StringUtilities.formatNumber("00", calendar.get(Calendar.HOUR))); + sb.append(StringUtilities.formatNumber("00", calendar.get(Calendar.MINUTE))); + sb.append(StringUtilities.formatNumber("00", calendar.get(Calendar.SECOND))); + return sb.toString(); + } + + public static long sortableTimeStringToDays(String string) throws DataFormatException { + // Calendar calendar = new GregorianCalendar(); + try { + int year = Integer.parseInt(string.substring(0, 4)); + int month = Integer.parseInt(string.substring(4, 6)) - 1; + int day = Integer.parseInt(string.substring(6, 8)); + calendar.set(year, month, day); + long time = calendar.getTimeInMillis(); + time += calendar.getTimeZone().getOffset(time); + + if (string.length() > 8) { + int hour = Integer.parseInt(string.substring(8, 10)); + time += hour * 60 * 60 * 1000; + if (string.length() > 8) { + int minute = Integer.parseInt(string.substring(10, 12)); + time += minute * 60 * 1000; + if (string.length() > 8) { + int second = Integer.parseInt(string.substring(12, 14)); + time += second * 1000; + } + } + } + // Millenium is added because for negative numbers, integer division truncates upwards! (-8/10 = 0) + return (((MILLENIUM + time) / DAY) - (1000 * 365)); + } catch (Exception e) { + throw new DataFormatException("Error parsing date: \"" + string + "\""); + } + } + + public static long databaseTimeStringToDays(String string) { + if (string.equals("")) + return MISSING_DATE; + int year = Integer.parseInt(string.substring(0, 4)); + int month = Integer.parseInt(string.substring(5, 7)) - 1; + int day = Integer.parseInt(string.substring(8, 10)); + calendar.set(year, month, day); + long time = calendar.getTimeInMillis(); + time += calendar.getTimeZone().getOffset(time); + // Millenium is added because for negative numbers, integer division truncates upwards! (-8/10 = 0) + return (((MILLENIUM + time) / DAY) - (1000 * 365)); + } + + public static long sortableTimeStringToMS(String string) throws DataFormatException { + // Calendar calendar = new GregorianCalendar(); + try { + int year = Integer.parseInt(string.substring(0, 4)); + int month = Integer.parseInt(string.substring(4, 6)) - 1; + int day = Integer.parseInt(string.substring(6, 8)); + calendar.set(year, month, day); + long time = calendar.getTimeInMillis(); + time += calendar.getTimeZone().getOffset(time); + + if (string.length() > 8) { + int hour = Integer.parseInt(string.substring(8, 10)); + time += hour * 60 * 60 * 1000; + if (string.length() > 8) { + int minute = Integer.parseInt(string.substring(10, 12)); + time += minute * 60 * 1000; + if (string.length() > 8) { + int second = Integer.parseInt(string.substring(12, 14)); + time += second * 1000; + } + } + } + // Millenium is added because for negative numbers, integer division truncates upwards! (-8/10 = 0) + return (time); + } catch (Exception e) { + throw new DataFormatException("Error parsing date: \"" + string + "\""); + } + } + + public static String replaceInternationalChars(String string) { + char result[] = string.toCharArray(); + for (int i = 0; i < result.length; i++) { + char ch = result[i]; + int charInt = (int) ch; + if (charInt == 216) + result[i] = 'O'; + else if (charInt == 248) + result[i] = 'o'; + else if (charInt == 246) + result[i] = 'o'; + else if (charInt == 244) + result[i] = 'o'; + else if (charInt == 245) + result[i] = 'o'; + else if (charInt == 242) + result[i] = 'o'; + else if (charInt == 243) + result[i] = 'o'; + else if (charInt == 237) + result[i] = 'i'; + else if (charInt == 238) + result[i] = 'i'; + else if (charInt == 239) + result[i] = 'i'; + else if (charInt == 232) + result[i] = 'e'; + else if (charInt == 233) + result[i] = 'e'; + else if (charInt == 234) + result[i] = 'e'; + else if (charInt == 235) + result[i] = 'e'; + else if (charInt == 231) + result[i] = 'c'; + else if (charInt == 224) + result[i] = 'a'; + else if (charInt == 225) + result[i] = 'a'; + else if (charInt == 226) + result[i] = 'a'; + else if (charInt == 227) + result[i] = 'a'; + else if (charInt == 228) + result[i] = 'a'; + else if (charInt == 229) + result[i] = 'a'; + else if (charInt == 252) + result[i] = 'u'; + else if (charInt == 250) + result[i] = 'u'; + else if (charInt == 253) + result[i] = 'y'; + else if (charInt == 241) + result[i] = 'n'; + } + return new String(result); + } + + public static int caseInsensitiveIndexOf(String value, List list) { + String queryLC = value.toLowerCase(); + for (int i = 0; i < list.size(); i++) { + String string = list.get(i); + if (string.toLowerCase().equals(queryLC)) + return i; + } + return -1; + } + + public static int levenshteinDistance(String s, String t) { + int d[][]; // matrix + int n; // length of s + int m; // length of t + int i; // iterates through s + int j; // iterates through t + char s_i; // ith character of s + char t_j; // jth character of t + int cost; // cost + n = s.length(); + m = t.length(); + if (n == 0) { + return m; + } + if (m == 0) { + return n; + } + d = new int[n + 1][m + 1]; + for (i = 0; i <= n; i++) { + d[i][0] = i; + } + for (j = 0; j <= m; j++) { + d[0][j] = j; + } + for (i = 1; i <= n; i++) { + s_i = s.charAt(i - 1); + for (j = 1; j <= m; j++) { + t_j = t.charAt(j - 1); + if (s_i == t_j) { + cost = 0; + } else { + cost = 1; + } + d[i][j] = Math.min(d[i - 1][j] + 1, Math.min(d[i][j - 1] + 1, d[i - 1][j - 1] + cost)); + } + } + return d[n][m]; + } + + /** + * Get hex string interpretation of the 16-byte MD5 hash for an input string Author: Kristina + */ + public static String getMD5Digest(String str) { + try { + byte[] buffer = str.getBytes(); + byte[] result = null; + StringBuffer buf = null; + MessageDigest md5 = MessageDigest.getInstance("MD5"); + // allocate room for the hash + result = new byte[md5.getDigestLength()]; + // calculate hash + md5.reset(); + md5.update(buffer); + + result = md5.digest(); + // System.out.println(result); + // create hex string from the 16-byte hash + buf = new StringBuffer(result.length * 2); + for (int i = 0; i < result.length; i++) { + int intVal = result[i] & 0xff; + if (intVal < 0x10) { + buf.append("0"); + } + buf.append(Integer.toHexString(intVal).toUpperCase()); + } + return buf.toString(); + } catch (NoSuchAlgorithmException e) { + System.err.println("Exception caught: " + e); + e.printStackTrace(); + + } + return null; + } + + /** + * Get hex string interpretation of the SHA-256 hash for an input string Author: Kristina + */ + public static String getSHA256Digest(String str) { + try { + byte[] buffer = str.getBytes(); + byte[] result = null; + StringBuffer buf = null; + MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); + // allocate room for the hash + result = new byte[sha256.getDigestLength()]; + // calculate hash + sha256.reset(); + sha256.update(buffer); + + result = sha256.digest(); + // System.out.println(result); + // create hex string from the 16-byte hash + buf = new StringBuffer(result.length * 2); + for (int i = 0; i < result.length; i++) { + int intVal = result[i] & 0xff; + if (intVal < 0x10) { + buf.append("0"); + } + buf.append(Integer.toHexString(intVal).toUpperCase()); + } + return buf.toString(); + } catch (NoSuchAlgorithmException e) { + System.err.println("Exception caught: " + e); + e.printStackTrace(); + + } + return null; + } + + public static String wordWrap(String text, int lineLength) { + text = text.trim(); + if (text.length() < lineLength) + return text; + if (text.substring(0, lineLength).contains("\n")) + return text.substring(0, text.indexOf("\n")).trim() + "\n\n" + wordWrap(text.substring(text.indexOf("\n") + 1), lineLength); + int place = Math.max(Math.max(text.lastIndexOf(" ", lineLength), text.lastIndexOf("\t", lineLength)), text.lastIndexOf("-", lineLength)); + return text.substring(0, place).trim() + "\n" + wordWrap(text.substring(place), lineLength); + } + + public static boolean isDate(String string) { + if (string.length() == 10) { + if ((string.charAt(4) == '-' || string.charAt(4) == '/') || (string.charAt(4) == string.charAt(7))) + try { + int year = Integer.parseInt(string.substring(0, 4)); + if (year < 1700 || year > 2200) + return false; + int month = Integer.parseInt(string.substring(5, 7)); + if (month < 1 || month > 12) + return false; + int day = Integer.parseInt(string.substring(8, 10)); + if (day < 1 || day > 31) + return false; + return true; + } catch (Exception e) { + return false; + } + } else if (string.length() == 8) { + if ((string.charAt(2) == '-' || string.charAt(5) == '/') || (string.charAt(2) == string.charAt(5))) + try { + Integer.parseInt(string.substring(6, 8)); + int month = Integer.parseInt(string.substring(0, 2)); + if (month < 1 || month > 12) + return false; + int day = Integer.parseInt(string.substring(3, 5)); + if (day < 1 || day > 31) + return false; + return true; + } catch (Exception e) { + return false; + } + + } + return false; + } + +} diff --git a/src/org/ohdsi/utilities/collections/CountingSet.java b/src/org/ohdsi/utilities/collections/CountingSet.java new file mode 100644 index 00000000..cb7cb3c1 --- /dev/null +++ b/src/org/ohdsi/utilities/collections/CountingSet.java @@ -0,0 +1,243 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.collections; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** + * Class for counting recurring objects. + * + * @author schuemie + * @param + */ +public class CountingSet implements Set { + + public Map key2count; + + public CountingSet() { + key2count = new HashMap(); + } + + public CountingSet(int capacity) { + key2count = new HashMap(capacity); + } + + public CountingSet(CountingSet set) { + key2count = new HashMap(set.key2count.size()); + for (Map.Entry entry : set.key2count.entrySet()) + key2count.put(entry.getKey(), new Count(entry.getValue().count)); + } + + public int getCount(T key) { + Count count = key2count.get(key); + if (count == null) + return 0; + else + return count.count; + } + + /** + * Computes the sum of the counts + * + * @return + */ + public int getSum() { + int sum = 0; + for (Count count : key2count.values()) + sum += count.count; + return sum; + } + + /** + * Returns the maximum count + * + * @return + */ + public int getMax() { + int max = 0; + for (Count count : key2count.values()) + if (count.count > max) + max = count.count; + return max; + } + + /** + * Computes the mean of the counts + * + * @return + */ + public double getMean() { + return (getSum() / (double) key2count.size()); + } + + /** + * Computes the standard deviations of the counts + * + * @return + */ + public double getSD() { + double mean = getMean(); + double sum = 0; + for (Count count : key2count.values()) + sum += sqr(count.count - mean); + return Math.sqrt(sum / (double) key2count.size()); + } + + private double sqr(double d) { + return d * d; + } + + public int size() { + return key2count.size(); + } + + public boolean isEmpty() { + return key2count.isEmpty(); + } + + public boolean contains(Object arg0) { + return key2count.containsKey(arg0); + } + + public Iterator iterator() { + return key2count.keySet().iterator(); + } + + public Object[] toArray() { + return key2count.keySet().toArray(); + } + + @SuppressWarnings("unchecked") + public Object[] toArray(Object[] arg0) { + return key2count.keySet().toArray(arg0); + } + + public boolean add(T arg0) { + Count count = key2count.get(arg0); + if (count == null) { + count = new Count(); + key2count.put(arg0, count); + return true; + } else { + count.count++; + return false; + } + } + + public boolean add(T arg0, int inc) { + Count count = key2count.get(arg0); + if (count == null) { + count = new Count(); + count.count = inc; + key2count.put(arg0, count); + return true; + } else { + count.count += inc; + return false; + } + } + + public boolean remove(Object arg0) { + + return (key2count.remove(arg0) != null); + } + + public boolean containsAll(Collection arg0) { + return key2count.keySet().containsAll(arg0); + } + + public boolean addAll(Collection arg0) { + boolean changed = false; + for (T object : arg0) { + if (add(object)) + changed = true; + } + return changed; + } + + public boolean retainAll(Collection arg0) { + return key2count.keySet().retainAll(arg0); + } + + public boolean removeAll(Collection arg0) { + return key2count.keySet().removeAll(arg0); + } + + public void clear() { + key2count.clear(); + } + + /** + * Keep the n most frequent values, remove the rest + * + * @param n + */ + public void keepTopN(int n) { + if (size() < n) + return; + List> list = new ArrayList>(key2count.entrySet()); + Collections.sort(list, new Comparator>() { + + @Override + public int compare(Entry arg0, Entry arg1) { + return IntegerComparator.compare(arg1.getValue().count, arg0.getValue().count); + } + }); + + Map newMap = new HashMap(n); + for (int i = 0; i < n; i++) + newMap.put(list.get(i).getKey(), list.get(i).getValue()); + + key2count = newMap; + } + + public static class Count { + public int count = 1; + + public Count() { + } + + public Count(int count) { + this.count = count; + } + + } + + public void printCounts() { + List> result = new ArrayList>(key2count.entrySet()); + Collections.sort(result, new Comparator>() { + public int compare(Entry o1, Entry o2) { + return IntegerComparator.compare(o2.getValue().count, o1.getValue().count); + } + }); + for (Map.Entry entry : result) + System.out.println(entry.getKey() + "\t" + entry.getValue().count); + } +} diff --git a/src/org/ohdsi/utilities/collections/IntegerComparator.java b/src/org/ohdsi/utilities/collections/IntegerComparator.java new file mode 100644 index 00000000..dcbd2dff --- /dev/null +++ b/src/org/ohdsi/utilities/collections/IntegerComparator.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.collections; + +import java.util.Comparator; + +public class IntegerComparator implements Comparator { + + @Override + public int compare(Integer arg0, Integer arg1) { + if (arg0 < arg1) + return -1; + else if (arg0 > arg1) + return 1; + else + return 0; + } + + public static int compare(int arg0, int arg1) { + if (arg0 < arg1) + return -1; + else if (arg0 > arg1) + return 1; + else + return 0; + } +} diff --git a/src/org/ohdsi/utilities/collections/LongComparator.java b/src/org/ohdsi/utilities/collections/LongComparator.java new file mode 100644 index 00000000..a9763496 --- /dev/null +++ b/src/org/ohdsi/utilities/collections/LongComparator.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.collections; + +import java.util.Comparator; + +public class LongComparator implements Comparator { + + @Override + public int compare(Long arg0, Long arg1) { + if (arg0 < arg1) + return -1; + else if (arg0 > arg1) + return 1; + else + return 0; + } + + public static int compare(long arg0, long arg1) { + if (arg0 < arg1) + return -1; + else if (arg0 > arg1) + return 1; + else + return 0; + } +} diff --git a/src/org/ohdsi/utilities/collections/OneToManyList.java b/src/org/ohdsi/utilities/collections/OneToManyList.java new file mode 100644 index 00000000..db8216da --- /dev/null +++ b/src/org/ohdsi/utilities/collections/OneToManyList.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.collections; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class OneToManyList { + private Map> map = new HashMap>(); + + public void put(K key, V value) { + List list = map.get(key); + if (list == null) { + list = new ArrayList(); + map.put(key, list); + } + list.add(value); + } + + public void putAll(OneToManyList other) { + for (Map.Entry> entry : other.map.entrySet()) + for (V value : entry.getValue()) + put(entry.getKey(), value); + } + + public void putAll(K key, Collection values) { + for (V value : values) + put(key, value); + } + + public List get(K key) { + List list = map.get(key); + if (list == null) + return Collections.emptyList(); + else + return list; + } + + public Set keySet() { + return map.keySet(); + } + + public Collection> values() { + return map.values(); + } + + public List remove(K key) { + return map.remove(key); + } + + public void clear() { + map.clear(); + } + + public int size() { + int size = 0; + for (List value : map.values()) + size += value.size(); + return size; + } + +} diff --git a/src/org/ohdsi/utilities/collections/OneToManySet.java b/src/org/ohdsi/utilities/collections/OneToManySet.java new file mode 100644 index 00000000..bf91989b --- /dev/null +++ b/src/org/ohdsi/utilities/collections/OneToManySet.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.collections; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class OneToManySet { + private Map> map = new HashMap>(); + + public boolean put(K key, V value){ + Set set = map.get(key); + if (set == null){ + set = new HashSet(); + map.put(key, set); + } + return set.add(value); + } + + public void set(K key, Set set){ + map.put(key, set); + } + + public Set get(K key){ + Set set = map.get(key); + if (set == null) + return Collections.emptySet(); + else + return set; + } + + public Set keySet(){ + return map.keySet(); + } + + public Collection> values(){ + return map.values(); + } + + public Set>> entrySet(){ + return map.entrySet(); + } + + public int size(){ + return map.size(); + } + + +} + diff --git a/src/org/ohdsi/utilities/collections/Pair.java b/src/org/ohdsi/utilities/collections/Pair.java new file mode 100644 index 00000000..b9457c28 --- /dev/null +++ b/src/org/ohdsi/utilities/collections/Pair.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.collections; + +import java.io.Serializable; + +public class Pair implements Serializable { + + private A object1; + private B object2; + private static final long serialVersionUID = 1784282381416947673L; + + public Pair(A item1, B item2) { + this.object1 = item1; + this.object2 = item2; + } + + public String toString() { + return "[[" + object1.toString() + "],[" + object2.toString() + "]]"; + } + + public int hashCode() { + return object1.hashCode() + object2.hashCode(); + } + + public A getItem1() { + return object1; + } + + public B getItem2() { + return object2; + } + + public void setItem1(A item1) { + object1 = item1; + } + + public void setItem2(B item2) { + object2 = item2; + } + + @SuppressWarnings("rawtypes") + public boolean equals(Object other) { + if (other instanceof Pair) + if (((Pair) other).object1.equals(object1)) + if (((Pair) other).object2.equals(object2)) + return true; + return false; + } +} diff --git a/src/org/ohdsi/utilities/files/FileSorter.java b/src/org/ohdsi/utilities/files/FileSorter.java new file mode 100644 index 00000000..3e54e0e4 --- /dev/null +++ b/src/org/ohdsi/utilities/files/FileSorter.java @@ -0,0 +1,325 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +/** + * Class for sorting (large) comma separated value text files. Assumes first row contains header + * + * @author schuemie + */ +public class FileSorter { + + /** + * Chunksize is the number of rows sorted in memory in one time. Higher chunk size leads to better performance but requires more memory. Set chunksize to -1 + * to let the system determine the largest chunk size based on available memory. + */ + public static int chunckSize = -1; + public static boolean verbose = false; + public static boolean caseSensitiveColumnNames = false; + public static int maxNumberOfTempFiles = 500; + public static double minFreeMemFraction = 0.25; + public static boolean checkIfAlreadySorted = false; + public static int maxCheckRows = 10000000; // Check only first 10000000 rows to see if already sorted + + public static void sort(String filename, String... columnNames) { + boolean[] sortNumeric = new boolean[columnNames.length]; + Arrays.fill(sortNumeric, false); + sort(filename, columnNames, sortNumeric); + } + + public static void sort(String filename, String[] columnnames, boolean[] sortNumeric) { + if (columnnames.length != sortNumeric.length) + throw new RuntimeException("Numeric sort array lenght does not equal sort column names"); + + System.gc(); + long availableMem = getFreeMem(); + long minFreeMem = Math.round(availableMem * minFreeMemFraction); + + if (verbose) { + System.out.println("Starting sort of " + filename); + if (chunckSize == -1) + System.out.println("Memory available for sorting: " + availableMem + " bytes. Min free = " + minFreeMem); + } + + Iterator> iterator = new ReadCSVFile(filename).iterator(); + + List header = iterator.next(); + + Comparator> comparator = buildComparator(columnnames, sortNumeric, header); + + if (checkIfAlreadySorted) { + if (isSorted(iterator, comparator)) + return; + else { + iterator = new ReadCSVFile(filename).iterator(); + iterator.next(); // skip header + } + } + + int nrOfFiles = 0; + int sorted = 0; + while (iterator.hasNext()) { + List> tempRows; + if (chunckSize == -1) + tempRows = readUntilMemFull(iterator, minFreeMem); + else + tempRows = readRows(iterator, chunckSize); + + // sort the rows + Collections.sort(tempRows, comparator); + + String tempFilename = generateFilename(filename, nrOfFiles++); + + // write temp file to disk + writeToDisk(header, tempRows, tempFilename); + + sorted += tempRows.size(); + if (verbose) + System.out.println("-Sorted " + sorted + " lines"); + } + mergeByBatches(nrOfFiles, filename, comparator); + } + + private static boolean isSorted(Iterator> iterator, Comparator> comparator) { + if (verbose) + System.out.println("Checking whether already sorted"); + List previous = null; + if (iterator.hasNext()) { + previous = iterator.next(); + } + int i = 0; + while (iterator.hasNext()) { + List row = iterator.next(); + if (comparator.compare(previous, row) > 0) { + if (verbose) + System.out.println("File not yet sorted"); + return false; + } + previous = row; + i++; + if (i > maxCheckRows) + break; + } + if (verbose) + System.out.println("File already sorted"); + return true; + } + + private static void mergeByBatches(int nrOfFiles, String source, Comparator> comparator) { + int level = 0; + String sourceBase = source; + String targetBase; + do { + if (verbose) + System.out.println("Merging " + nrOfFiles + " files"); + + int newNrOfFiles = 0; + int from = 0; + targetBase = source + "_" + level; + while (from < nrOfFiles) { + String targetFilename; + if (nrOfFiles <= maxNumberOfTempFiles) + targetFilename = source; + else + targetFilename = generateFilename(targetBase, newNrOfFiles++); + + int to = Math.min(from + maxNumberOfTempFiles, nrOfFiles); + mergeFiles(sourceBase, from, to, targetFilename, comparator); + deleteTempFiles(sourceBase, from, to); + from = to; + } + nrOfFiles = newNrOfFiles; + level++; + sourceBase = targetBase; + } while (nrOfFiles > 1); + } + + private static void writeToDisk(List header, List> rows, String filename) { + WriteCSVFile out = new WriteCSVFile(filename); + if (header != null) + out.write(header); + for (List row : rows) + out.write(row); + out.close(); + } + + private static List> readRows(Iterator> iterator, int nrOfRows) { + List> rows = new ArrayList>(); + int i = 0; + while (i++ < nrOfRows && iterator.hasNext()) + rows.add(iterator.next()); + return rows; + } + + private static List> readUntilMemFull(Iterator> iterator, long minFreeMem) { + List> rows = new ArrayList>(); + System.gc(); + if (verbose) + System.out.println("Loading next batch. Available memory: " + getFreeMem()); + long freeMem = Long.MAX_VALUE; + while (freeMem > minFreeMem && iterator.hasNext()) { + rows.add(iterator.next()); + freeMem = getFreeMem(); + } + return rows; + } + + private static long getFreeMem() { + return Runtime.getRuntime().freeMemory() + Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory(); + } + + private static Comparator> buildComparator(String[] columnnames, boolean[] sortNumeric, List header) { + int[] indexesToCompare = new int[columnnames.length]; + for (int i = 0; i < columnnames.length; i++) + indexesToCompare[i] = getIndexForColumn(header, new String(columnnames[i])); + + return new RowComparator(indexesToCompare, sortNumeric); + } + + private static class RowComparator implements Comparator> { + private int[] indexes; + private boolean[] sortNumeric; + + public RowComparator(int[] indexes, boolean[] sortNumeric) { + this.indexes = indexes; + this.sortNumeric = sortNumeric; + } + + public int compare(List o1, List o2) { + int result = 0; + int i = 0; + while (result == 0 && i < indexes.length) { + String value1 = o1.get(indexes[i]); + String value2 = o2.get(indexes[i]); + if (sortNumeric[i]) + result = efficientLongCompare(value1, value2); + else + result = value1.compareTo(value2); + i++; + } + return result; + } + + private int efficientLongCompare(String value1, String value2) { + if (value1.length() > value2.length()) + return 1; + else if (value1.length() < value2.length()) + return -1; + else + return value1.compareTo(value2); + } + + } + + private static void deleteTempFiles(String base, int start, int end) { + for (int i = start; i < end; i++) + (new File(generateFilename(base, i))).delete(); + } + + private static String generateFilename(String base, int number) { + return base + "_" + number + ".tmp"; + } + + private static void mergeFiles(String sourceBase, int start, int end, String target, Comparator> comparator) { + List>> tempFiles = new ArrayList>>(); + + List> filerows = new ArrayList>(); + List header = null; + boolean done = true; + for (int i = start; i < end; i++) { + ReadCSVFile tempFile = new ReadCSVFile(generateFilename(sourceBase, i)); + Iterator> iterator = tempFile.getIterator(); + if (iterator.hasNext()) { + if (tempFiles.size() == 0) // its the first one + header = iterator.next(); + else + iterator.next(); + } + tempFiles.add(iterator); + + // initialize + if (iterator.hasNext()) { + filerows.add(iterator.next()); + done = false; + } else + filerows.add(null); + } + WriteCSVFile out = new WriteCSVFile(target); + out.write(header); + while (!done) { + // Find best file to pick from: + List bestRow = null; + int bestFile = -1; + for (int i = 0; i < filerows.size(); i++) { + if (bestRow == null || (filerows.get(i) != null && comparator.compare(filerows.get(i), bestRow) < 0)) { + bestRow = filerows.get(i); + bestFile = i; + } + } + if (bestRow == null) + done = true; + else { + // write it to file: + out.write(bestRow); + + // get next from winning file: + List newRow; + Iterator> bestFileIterator = tempFiles.get(bestFile); + if (bestFileIterator.hasNext()) + newRow = bestFileIterator.next(); + else + newRow = null; + filerows.set(bestFile, newRow); + } + } + out.close(); + } + + private static int getIndexForColumn(List list, String value) throws RuntimeException { + int result; + if (caseSensitiveColumnNames) + result = list.indexOf(value); + else + result = caseInsensitiveIndexOf(value, list); + if (result == -1) + throw (new RuntimeException("File sorter could not find column \"" + value + "\"")); + return result; + } + + public static int caseInsensitiveIndexOf(String value, List list) { + String queryLC = value.toLowerCase(); + for (int i = 0; i < list.size(); i++) { + String string = list.get(i); + if (string.toLowerCase().equals(queryLC)) + return i; + } + return -1; + } + +} diff --git a/src/org/ohdsi/utilities/files/MultiRowIterator.java b/src/org/ohdsi/utilities/files/MultiRowIterator.java new file mode 100644 index 00000000..5f9e6c37 --- /dev/null +++ b/src/org/ohdsi/utilities/files/MultiRowIterator.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.ohdsi.utilities.files.MultiRowIterator.MultiRowSet; + +/** + * Allows iteration over multiple tables (as Iterator) simultaneously, synchronized by the value of the [linkingColumn]. Assumes all tables are sorted by + * the [linkingColumn]. + * + * @author MSCHUEMI + */ +public class MultiRowIterator implements Iterator { + + private Iterator[] iterators; + private String[] tableNames; + private Row[] nextRows; + private MultiRowSet buffer; + private String linkingColumn; + private boolean sortedNumerically; + + public MultiRowIterator(String linkingColumn, String[] tableNames, Iterator... tableIterators) { + this(linkingColumn, false, tableNames, tableIterators); + } + + public MultiRowIterator(String linkingColumn, boolean sortedNumerically, String[] tableNames, Iterator[] tableIterators) { + this.iterators = tableIterators; + this.linkingColumn = linkingColumn; + this.tableNames = tableNames; + this.sortedNumerically = sortedNumerically; + startRead(); + } + + private void startRead() { + nextRows = new Row[iterators.length]; + for (int i = 0; i < iterators.length; i++) + if (iterators[i].hasNext()) + nextRows[i] = iterators[i].next(); + else + nextRows[i] = null; + readNext(); + } + + @Override + public boolean hasNext() { + return (buffer != null); + } + + @Override + public MultiRowSet next() { + MultiRowSet result = buffer; + readNext(); + return result; + } + + private void readNext() { + String lowestLinkingColumn = findLowestLinkingColumn(nextRows); + if (lowestLinkingColumn == null) { + buffer = null; + return; + } + buffer = new MultiRowSet(tableNames); + buffer.linkingId = lowestLinkingColumn; + for (int i = 0; i < iterators.length; i++) { + Iterator iterator = iterators[i]; + while (nextRows[i] != null && nextRows[i].get(linkingColumn).equals(lowestLinkingColumn)) { + buffer.get(tableNames[i]).add(nextRows[i]); + if (iterator.hasNext()) + nextRows[i] = iterator.next(); + else + nextRows[i] = null; + } + } + } + + private String findLowestLinkingColumn(Row[] rows) { + String linkingId = null; + for (Row row : rows) + if (row != null && (linkingId == null || compare(row.get(linkingColumn), linkingId) < 0)) + linkingId = row.get(linkingColumn); + return linkingId; + } + + private int compare(String value1, String value2) { + if (sortedNumerically) + return efficientLongCompare(value1, value2); + else + return value1.compareTo(value2); + } + + private int efficientLongCompare(String value1, String value2) { + if (value1.length() > value2.length()) + return 1; + else if (value1.length() < value2.length()) + return -1; + else + return value1.compareTo(value2); + } + + @Override + public void remove() { + System.err.println("Calling unimplemented remove method in class " + this.getClass().getName()); + } + + public static class MultiRowSet extends HashMap> { + private static final long serialVersionUID = 1164317535150664720L; + + public String linkingId; + + public MultiRowSet(String[] tableNames) { + for (String tableName : tableNames) { + put(tableName, new ArrayList()); + } + } + + public List getNonEmptyTableNames() { + List result = new ArrayList(); + for (String tableName : keySet()) + if (get(tableName).size() != 0) + result.add(tableName); + return result; + } + + /** + * returns the total number of rows (summed across the tables) + * + * @return + */ + public int totalSize() { + int size = 0; + for (List rows : values()) + size += rows.size(); + return size; + } + + } + +} diff --git a/src/org/ohdsi/utilities/files/QuickAndDirtyXlsxReader.java b/src/org/ohdsi/utilities/files/QuickAndDirtyXlsxReader.java new file mode 100644 index 00000000..5f79e977 --- /dev/null +++ b/src/org/ohdsi/utilities/files/QuickAndDirtyXlsxReader.java @@ -0,0 +1,568 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.collections.IntegerComparator; +import org.ohdsi.utilities.files.QuickAndDirtyXlsxReader.Sheet; + +public class QuickAndDirtyXlsxReader extends ArrayList { + + private static final long serialVersionUID = 25124428448185386L; + + private List sharedStrings = new ArrayList(); + + private Map rIdToSheet = new HashMap(); + private Map filenameToSheet = new HashMap(); + + public static void main(String[] args) { + QuickAndDirtyXlsxReader reader = new QuickAndDirtyXlsxReader("S:/Data/THIN/ScanReport.xlsx"); + WriteCSVFile out = new WriteCSVFile("c:/temp/xlsxdump.csv"); + for (Sheet sheet : reader) { + List sheetHeader = new ArrayList(); + sheetHeader.add("*** " + sheet.name + " ***"); + out.write(sheetHeader); + for (Row row : sheet) + out.write(row); + + List sheetFooter = new ArrayList(); + sheetHeader.add(""); + out.write(sheetFooter); + } + out.close(); + + } + + public QuickAndDirtyXlsxReader(String filename) { + try { + // Step 1: load the shared strings (if any), and the rels + FileInputStream inputStream = new FileInputStream(filename); + loadSharedStringsAndRels(inputStream); + + // Step 2: load the data: + inputStream = new FileInputStream(filename); + readFromStream(inputStream); + + // Step 3: order the sheets: + Collections.sort(this, new Comparator() { + + @Override + public int compare(Sheet o1, Sheet o2) { + return IntegerComparator.compare(o1.order, o2.order); + } + }); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + } + + private void loadSharedStringsAndRels(FileInputStream inputStream) { + try { + int tasksComplete = 0; + ZipInputStream zipInputStream = new ZipInputStream(inputStream); + + ZipEntry zipEntry = null; + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + String filename = zipEntry.getName(); + if (filename.equals("xl/sharedStrings.xml")) { + processSharedStrings(zipInputStream); + tasksComplete++; + } else if (filename.equals("xl/_rels/workbook.xml.rels")) { + processRels(zipInputStream); + tasksComplete++; + } + + if (tasksComplete == 2) { + zipInputStream.close(); + break; + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void processRels(ZipInputStream inputStream) throws IOException { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String line = null; + while ((line = bufferedReader.readLine()) != null) + for (String tag : StringUtilities.multiFindBetween(line, "")) { + String rId = StringUtilities.findBetween(tag, "Id=\"", "\""); + String filename = "xl/" + StringUtilities.findBetween(tag, "Target=\"", "\""); + if (filename.contains("/sheet")) { + Sheet sheet = new Sheet(); + add(sheet); + rIdToSheet.put(rId, sheet); + filenameToSheet.put(filename, sheet); + } + } + } + + public QuickAndDirtyXlsxReader(InputStream stream) { + readFromStream(stream); + } + + private void readFromStream(InputStream inputStream) { + try { + ZipInputStream zipInputStream = new ZipInputStream(inputStream); + + ZipEntry zipEntry = null; + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + String filename = zipEntry.getName(); + if (filename.equals("xl/workbook.xml")) + processWorkBook(zipInputStream); + else if (filename.startsWith("xl/worksheets/sheet")) + processSheet(filename, zipInputStream); + } + } catch (IOException e) { + e.printStackTrace(); + } + + } + + private void processSharedStrings(ZipInputStream inputStream) throws IOException { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + StringBuilder fullFile = new StringBuilder(); + String line; + while ((line = bufferedReader.readLine()) != null) + fullFile.append(line); + + for (String string : StringUtilities.multiFindBetween(fullFile.toString(), "", "")) + if (string.trim().equals("")) // Empty string + sharedStrings.add(""); + else { + string = StringUtilities.findBetween(string, ">", "<"); + sharedStrings.add(string); + } + } + + private void processSheet(String filename, ZipInputStream inputStream) throws IOException { + Sheet sheet = filenameToSheet.get(filename); + //System.out.println(filename + "\t" + sheet.name); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String line; + StringBuilder fullSheet = new StringBuilder(); + while ((line = bufferedReader.readLine()) != null) + fullSheet.append(line); + + for (String rowLine : StringUtilities.multiFindBetween(fullSheet.toString(), "")) { + Row row = new Row(); + row.addAll(findCellValues(rowLine)); + if (row.size() != 0) + sheet.add(row); + } + + } + + public List findCellValues(String string) { + List result = new ArrayList(); + int tagStart = -1; + int stringStart = -1; + int column = -1; + boolean sharedString = false; + for (int i = 0; i < string.length(); i++) { + char ch = string.charAt(i); + if (ch == '<') + tagStart = i + 1; + else if (ch == '>') { + if (tagStart != -1 && i > tagStart) { + String tag = string.substring(tagStart, i); + if (tag.charAt(0) == 'c') { + sharedString = tag.contains("t=\"s\""); + column = parseColumn(StringUtilities.findBetween(tag, "r=\"", "\"")); + } else if (tag.startsWith("v") || tag.startsWith("t")) + stringStart = i + 1; + else if (tag.equals("/v") || tag.equals("/t")) { + if (stringStart != -1 && i > stringStart) { + for (int j = result.size(); j <= column; j++) + result.add(""); + if (sharedString) { + int index = Integer.parseInt(string.substring(stringStart, tagStart - 1)); + result.set(column, sharedStrings.get(index)); + } else + result.set(column, decode(string.substring(stringStart, tagStart - 1))); + } + stringStart = -1; + column = -1; + } + + } + } + + } + return result; + } + + private int parseColumn(String cellIdString) { + int column = 0; + for (int i = 0; i < cellIdString.length(); i++) { + char ch = cellIdString.charAt(i); + if (Character.isDigit(cellIdString.charAt(i))) { + return column - 1; + } else { + column *= 26; + column += (int) ch - 64; + } + } + return -1; + } + + private static HashMap htmlEntities = new HashMap(); + static { + htmlEntities.put("nbsp", new Integer(160)); + htmlEntities.put("iexcl", new Integer(161)); + htmlEntities.put("cent", new Integer(162)); + htmlEntities.put("pound", new Integer(163)); + htmlEntities.put("curren", new Integer(164)); + htmlEntities.put("yen", new Integer(165)); + htmlEntities.put("brvbar", new Integer(166)); + htmlEntities.put("sect", new Integer(167)); + htmlEntities.put("uml", new Integer(168)); + htmlEntities.put("copy", new Integer(169)); + htmlEntities.put("ordf", new Integer(170)); + htmlEntities.put("laquo", new Integer(171)); + htmlEntities.put("not", new Integer(172)); + htmlEntities.put("shy", new Integer(173)); + htmlEntities.put("reg", new Integer(174)); + htmlEntities.put("macr", new Integer(175)); + htmlEntities.put("deg", new Integer(176)); + htmlEntities.put("plusmn", new Integer(177)); + htmlEntities.put("sup2", new Integer(178)); + htmlEntities.put("sup3", new Integer(179)); + htmlEntities.put("acute", new Integer(180)); + htmlEntities.put("micro", new Integer(181)); + htmlEntities.put("para", new Integer(182)); + htmlEntities.put("middot", new Integer(183)); + htmlEntities.put("cedil", new Integer(184)); + htmlEntities.put("sup1", new Integer(185)); + htmlEntities.put("ordm", new Integer(186)); + htmlEntities.put("raquo", new Integer(187)); + htmlEntities.put("frac14", new Integer(188)); + htmlEntities.put("frac12", new Integer(189)); + htmlEntities.put("frac34", new Integer(190)); + htmlEntities.put("iquest", new Integer(191)); + htmlEntities.put("Agrave", new Integer(192)); + htmlEntities.put("Aacute", new Integer(193)); + htmlEntities.put("Acirc", new Integer(194)); + htmlEntities.put("Atilde", new Integer(195)); + htmlEntities.put("Auml", new Integer(196)); + htmlEntities.put("Aring", new Integer(197)); + htmlEntities.put("AElig", new Integer(198)); + htmlEntities.put("Ccedil", new Integer(199)); + htmlEntities.put("Egrave", new Integer(200)); + htmlEntities.put("Eacute", new Integer(201)); + htmlEntities.put("Ecirc", new Integer(202)); + htmlEntities.put("Euml", new Integer(203)); + htmlEntities.put("Igrave", new Integer(204)); + htmlEntities.put("Iacute", new Integer(205)); + htmlEntities.put("Icirc", new Integer(206)); + htmlEntities.put("Iuml", new Integer(207)); + htmlEntities.put("ETH", new Integer(208)); + htmlEntities.put("Ntilde", new Integer(209)); + htmlEntities.put("Ograve", new Integer(210)); + htmlEntities.put("Oacute", new Integer(211)); + htmlEntities.put("Ocirc", new Integer(212)); + htmlEntities.put("Otilde", new Integer(213)); + htmlEntities.put("Ouml", new Integer(214)); + htmlEntities.put("times", new Integer(215)); + htmlEntities.put("Oslash", new Integer(216)); + htmlEntities.put("Ugrave", new Integer(217)); + htmlEntities.put("Uacute", new Integer(218)); + htmlEntities.put("Ucirc", new Integer(219)); + htmlEntities.put("Uuml", new Integer(220)); + htmlEntities.put("Yacute", new Integer(221)); + htmlEntities.put("THORN", new Integer(222)); + htmlEntities.put("szlig", new Integer(223)); + htmlEntities.put("agrave", new Integer(224)); + htmlEntities.put("aacute", new Integer(225)); + htmlEntities.put("acirc", new Integer(226)); + htmlEntities.put("atilde", new Integer(227)); + htmlEntities.put("auml", new Integer(228)); + htmlEntities.put("aring", new Integer(229)); + htmlEntities.put("aelig", new Integer(230)); + htmlEntities.put("ccedil", new Integer(231)); + htmlEntities.put("egrave", new Integer(232)); + htmlEntities.put("eacute", new Integer(233)); + htmlEntities.put("ecirc", new Integer(234)); + htmlEntities.put("euml", new Integer(235)); + htmlEntities.put("igrave", new Integer(236)); + htmlEntities.put("iacute", new Integer(237)); + htmlEntities.put("icirc", new Integer(238)); + htmlEntities.put("iuml", new Integer(239)); + htmlEntities.put("eth", new Integer(240)); + htmlEntities.put("ntilde", new Integer(241)); + htmlEntities.put("ograve", new Integer(242)); + htmlEntities.put("oacute", new Integer(243)); + htmlEntities.put("ocirc", new Integer(244)); + htmlEntities.put("otilde", new Integer(245)); + htmlEntities.put("ouml", new Integer(246)); + htmlEntities.put("divide", new Integer(247)); + htmlEntities.put("oslash", new Integer(248)); + htmlEntities.put("ugrave", new Integer(249)); + htmlEntities.put("uacute", new Integer(250)); + htmlEntities.put("ucirc", new Integer(251)); + htmlEntities.put("uuml", new Integer(252)); + htmlEntities.put("yacute", new Integer(253)); + htmlEntities.put("thorn", new Integer(254)); + htmlEntities.put("yuml", new Integer(255)); + htmlEntities.put("fnof", new Integer(402)); + htmlEntities.put("Alpha", new Integer(913)); + htmlEntities.put("Beta", new Integer(914)); + htmlEntities.put("Gamma", new Integer(915)); + htmlEntities.put("Delta", new Integer(916)); + htmlEntities.put("Epsilon", new Integer(917)); + htmlEntities.put("Zeta", new Integer(918)); + htmlEntities.put("Eta", new Integer(919)); + htmlEntities.put("Theta", new Integer(920)); + htmlEntities.put("Iota", new Integer(921)); + htmlEntities.put("Kappa", new Integer(922)); + htmlEntities.put("Lambda", new Integer(923)); + htmlEntities.put("Mu", new Integer(924)); + htmlEntities.put("Nu", new Integer(925)); + htmlEntities.put("Xi", new Integer(926)); + htmlEntities.put("Omicron", new Integer(927)); + htmlEntities.put("Pi", new Integer(928)); + htmlEntities.put("Rho", new Integer(929)); + htmlEntities.put("Sigma", new Integer(931)); + htmlEntities.put("Tau", new Integer(932)); + htmlEntities.put("Upsilon", new Integer(933)); + htmlEntities.put("Phi", new Integer(934)); + htmlEntities.put("Chi", new Integer(935)); + htmlEntities.put("Psi", new Integer(936)); + htmlEntities.put("Omega", new Integer(937)); + htmlEntities.put("alpha", new Integer(945)); + htmlEntities.put("beta", new Integer(946)); + htmlEntities.put("gamma", new Integer(947)); + htmlEntities.put("delta", new Integer(948)); + htmlEntities.put("epsilon", new Integer(949)); + htmlEntities.put("zeta", new Integer(950)); + htmlEntities.put("eta", new Integer(951)); + htmlEntities.put("theta", new Integer(952)); + htmlEntities.put("iota", new Integer(953)); + htmlEntities.put("kappa", new Integer(954)); + htmlEntities.put("lambda", new Integer(955)); + htmlEntities.put("mu", new Integer(956)); + htmlEntities.put("nu", new Integer(957)); + htmlEntities.put("xi", new Integer(958)); + htmlEntities.put("omicron", new Integer(959)); + htmlEntities.put("pi", new Integer(960)); + htmlEntities.put("rho", new Integer(961)); + htmlEntities.put("sigmaf", new Integer(962)); + htmlEntities.put("sigma", new Integer(963)); + htmlEntities.put("tau", new Integer(964)); + htmlEntities.put("upsilon", new Integer(965)); + htmlEntities.put("phi", new Integer(966)); + htmlEntities.put("chi", new Integer(967)); + htmlEntities.put("psi", new Integer(968)); + htmlEntities.put("omega", new Integer(969)); + htmlEntities.put("thetasym", new Integer(977)); + htmlEntities.put("upsih", new Integer(978)); + htmlEntities.put("piv", new Integer(982)); + htmlEntities.put("bull", new Integer(8226)); + htmlEntities.put("hellip", new Integer(8230)); + htmlEntities.put("prime", new Integer(8242)); + htmlEntities.put("Prime", new Integer(8243)); + htmlEntities.put("oline", new Integer(8254)); + htmlEntities.put("frasl", new Integer(8260)); + htmlEntities.put("weierp", new Integer(8472)); + htmlEntities.put("image", new Integer(8465)); + htmlEntities.put("real", new Integer(8476)); + htmlEntities.put("trade", new Integer(8482)); + htmlEntities.put("alefsym", new Integer(8501)); + htmlEntities.put("larr", new Integer(8592)); + htmlEntities.put("uarr", new Integer(8593)); + htmlEntities.put("rarr", new Integer(8594)); + htmlEntities.put("darr", new Integer(8595)); + htmlEntities.put("harr", new Integer(8596)); + htmlEntities.put("crarr", new Integer(8629)); + htmlEntities.put("lArr", new Integer(8656)); + htmlEntities.put("uArr", new Integer(8657)); + htmlEntities.put("rArr", new Integer(8658)); + htmlEntities.put("dArr", new Integer(8659)); + htmlEntities.put("hArr", new Integer(8660)); + htmlEntities.put("forall", new Integer(8704)); + htmlEntities.put("part", new Integer(8706)); + htmlEntities.put("exist", new Integer(8707)); + htmlEntities.put("empty", new Integer(8709)); + htmlEntities.put("nabla", new Integer(8711)); + htmlEntities.put("isin", new Integer(8712)); + htmlEntities.put("notin", new Integer(8713)); + htmlEntities.put("ni", new Integer(8715)); + htmlEntities.put("prod", new Integer(8719)); + htmlEntities.put("sum", new Integer(8721)); + htmlEntities.put("minus", new Integer(8722)); + htmlEntities.put("lowast", new Integer(8727)); + htmlEntities.put("radic", new Integer(8730)); + htmlEntities.put("prop", new Integer(8733)); + htmlEntities.put("infin", new Integer(8734)); + htmlEntities.put("ang", new Integer(8736)); + htmlEntities.put("and", new Integer(8743)); + htmlEntities.put("or", new Integer(8744)); + htmlEntities.put("cap", new Integer(8745)); + htmlEntities.put("cup", new Integer(8746)); + htmlEntities.put("int", new Integer(8747)); + htmlEntities.put("there4", new Integer(8756)); + htmlEntities.put("sim", new Integer(8764)); + htmlEntities.put("cong", new Integer(8773)); + htmlEntities.put("asymp", new Integer(8776)); + htmlEntities.put("ne", new Integer(8800)); + htmlEntities.put("equiv", new Integer(8801)); + htmlEntities.put("le", new Integer(8804)); + htmlEntities.put("ge", new Integer(8805)); + htmlEntities.put("sub", new Integer(8834)); + htmlEntities.put("sup", new Integer(8835)); + htmlEntities.put("nsub", new Integer(8836)); + htmlEntities.put("sube", new Integer(8838)); + htmlEntities.put("supe", new Integer(8839)); + htmlEntities.put("oplus", new Integer(8853)); + htmlEntities.put("otimes", new Integer(8855)); + htmlEntities.put("perp", new Integer(8869)); + htmlEntities.put("sdot", new Integer(8901)); + htmlEntities.put("lceil", new Integer(8968)); + htmlEntities.put("rceil", new Integer(8969)); + htmlEntities.put("lfloor", new Integer(8970)); + htmlEntities.put("rfloor", new Integer(8971)); + htmlEntities.put("lang", new Integer(9001)); + htmlEntities.put("rang", new Integer(9002)); + htmlEntities.put("loz", new Integer(9674)); + htmlEntities.put("spades", new Integer(9824)); + htmlEntities.put("clubs", new Integer(9827)); + htmlEntities.put("hearts", new Integer(9829)); + htmlEntities.put("diams", new Integer(9830)); + htmlEntities.put("quot", new Integer(34)); + htmlEntities.put("amp", new Integer(38)); + htmlEntities.put("lt", new Integer(60)); + htmlEntities.put("gt", new Integer(62)); + htmlEntities.put("OElig", new Integer(338)); + htmlEntities.put("oelig", new Integer(339)); + htmlEntities.put("Scaron", new Integer(352)); + htmlEntities.put("scaron", new Integer(353)); + htmlEntities.put("Yuml", new Integer(376)); + htmlEntities.put("circ", new Integer(710)); + htmlEntities.put("tilde", new Integer(732)); + htmlEntities.put("ensp", new Integer(8194)); + htmlEntities.put("emsp", new Integer(8195)); + htmlEntities.put("thinsp", new Integer(8201)); + htmlEntities.put("zwnj", new Integer(8204)); + htmlEntities.put("zwj", new Integer(8205)); + htmlEntities.put("lrm", new Integer(8206)); + htmlEntities.put("rlm", new Integer(8207)); + htmlEntities.put("ndash", new Integer(8211)); + htmlEntities.put("mdash", new Integer(8212)); + htmlEntities.put("lsquo", new Integer(8216)); + htmlEntities.put("rsquo", new Integer(8217)); + htmlEntities.put("sbquo", new Integer(8218)); + htmlEntities.put("ldquo", new Integer(8220)); + htmlEntities.put("rdquo", new Integer(8221)); + htmlEntities.put("bdquo", new Integer(8222)); + htmlEntities.put("dagger", new Integer(8224)); + htmlEntities.put("Dagger", new Integer(8225)); + htmlEntities.put("permil", new Integer(8240)); + htmlEntities.put("lsaquo", new Integer(8249)); + htmlEntities.put("rsaquo", new Integer(8250)); + htmlEntities.put("euro", new Integer(8364)); + } + + public static String decode(String s) { + StringBuffer result = new StringBuffer(s.length()); + int ampInd = s.indexOf("&"); + int lastEnd = 0; + while (ampInd >= 0) { + int nextAmp = s.indexOf("&", ampInd + 1); + int nextSemi = s.indexOf(";", ampInd + 1); + if (nextSemi != -1 && (nextAmp == -1 || nextSemi < nextAmp)) { + int value = -1; + String escape = s.substring(ampInd + 1, nextSemi); + try { + if (escape.startsWith("#")) { + value = Integer.parseInt(escape.substring(1), 10); + } else { + if (htmlEntities.containsKey(escape)) { + value = ((Integer) (htmlEntities.get(escape))).intValue(); + } + } + } catch (NumberFormatException x) { + } + result.append(s.substring(lastEnd, ampInd)); + lastEnd = nextSemi + 1; + if (value >= 0 && value <= 0xffff) { + result.append((char) value); + } else { + result.append("&").append(escape).append(";"); + } + } + ampInd = nextAmp; + } + result.append(s.substring(lastEnd)); + return result.toString(); + } + + private void processWorkBook(InputStream inputStream) throws NumberFormatException, IOException { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String line = null; + while ((line = bufferedReader.readLine()) != null) { + for (String sheetTag : StringUtilities.multiFindBetween(line, "")) { + String name = StringUtilities.findBetween(sheetTag, "name=\"", "\""); + String order = StringUtilities.findBetween(sheetTag, "sheetId=\"", "\""); + String rId = StringUtilities.findBetween(sheetTag, "r:id=\"", "\""); + Sheet sheet = rIdToSheet.get(rId); + sheet.setName(name); + sheet.order = Integer.parseInt(order); + } + } + } + + public class Sheet extends ArrayList { + private static final long serialVersionUID = -8597151681911998153L; + private String name; + private int order; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public class Row extends ArrayList { + private static final long serialVersionUID = -6391290892840364766L; + + } +} diff --git a/src/org/ohdsi/utilities/files/ReadCSVFile.java b/src/org/ohdsi/utilities/files/ReadCSVFile.java new file mode 100644 index 00000000..2e6806d2 --- /dev/null +++ b/src/org/ohdsi/utilities/files/ReadCSVFile.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.Iterator; +import java.util.List; + +import org.ohdsi.utilities.StringUtilities; + +public class ReadCSVFile implements Iterable>{ + protected BufferedReader bufferedReader; + public boolean EOF = false; + private char delimiter = ','; + + public ReadCSVFile(String filename) { + try { + FileInputStream textFileStream = new FileInputStream(filename); + bufferedReader = new BufferedReader(new InputStreamReader(textFileStream, "UTF-8")); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + public ReadCSVFile(InputStream inputstream){ + try { + bufferedReader = new BufferedReader(new InputStreamReader(inputstream, "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + public Iterator> getIterator() { + return iterator(); + } + + private class CSVFileIterator implements Iterator> { + private String buffer; + + public CSVFileIterator() { + try { + buffer = bufferedReader.readLine(); + if (buffer == null){ + EOF = true; + bufferedReader.close(); + } + } + catch (IOException e) { + e.printStackTrace(); + } + + } + + public boolean hasNext() { + return !EOF; + } + + public List next() { + String result = buffer; + try { + buffer = bufferedReader.readLine(); + if (buffer == null){ + EOF = true; + bufferedReader.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + return line2columns(result); + } + + public void remove() { + System.err.println("Unimplemented method 'remove' called"); + } + } + + public Iterator> iterator() { + return new CSVFileIterator(); + } + + private List line2columns(String line){ + List columns = StringUtilities.safeSplit(line, delimiter); + for (int i = 0; i < columns.size(); i++){ + String column = columns.get(i); + if (column.startsWith("\"") && column.endsWith("\"") && column.length() > 1) + column = column.substring(1, column.length()-1); + column = column.replace("\\\"", "\""); + columns.set(i, column); + } + return columns; + } + + public void setDelimiter(char delimiter) { + this.delimiter = delimiter; + } + + public char getDelimiter() { + return delimiter; + } +} diff --git a/src/org/ohdsi/utilities/files/ReadCSVFileWithHeader.java b/src/org/ohdsi/utilities/files/ReadCSVFileWithHeader.java new file mode 100644 index 00000000..33cda1c2 --- /dev/null +++ b/src/org/ohdsi/utilities/files/ReadCSVFileWithHeader.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + + +public class ReadCSVFileWithHeader implements Iterable{ + private InputStream inputstream; + + public ReadCSVFileWithHeader(String filename) { + try { + inputstream = new FileInputStream(filename); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + + public ReadCSVFileWithHeader(InputStream inputstream){ + this.inputstream = inputstream; + } + + @Override + public Iterator iterator() { + return new RowIterator(); + } + + public class RowIterator implements Iterator{ + + private Iterator> iterator; + private Map fieldName2ColumnIndex; + + public RowIterator(){ + iterator = new ReadCSVFile(inputstream).iterator(); + fieldName2ColumnIndex = new HashMap(); + for (String header : iterator.next()) + fieldName2ColumnIndex.put(header, fieldName2ColumnIndex.size()); + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Row next() { + return new Row(iterator.next(),fieldName2ColumnIndex); + } + + @Override + public void remove() { + throw new RuntimeException("Remove not supported"); + } + + } +} diff --git a/src/org/ohdsi/utilities/files/ReadTextFile.java b/src/org/ohdsi/utilities/files/ReadTextFile.java new file mode 100644 index 00000000..54100320 --- /dev/null +++ b/src/org/ohdsi/utilities/files/ReadTextFile.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ReadTextFile implements Iterable{ + public String filename; + protected BufferedReader bufferedReader; + public boolean EOF = false; + + + public ReadTextFile(InputStream inputStream) { + try { + bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + } catch (UnsupportedEncodingException e) { + System.err.println("Computer does not support UTF-8 encoding"); + e.printStackTrace(); + } + + } + public ReadTextFile(String filename) { + this.filename = filename; + try { + FileInputStream inputStream = new FileInputStream(filename); + bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + System.err.println("Computer does not support UTF-8 encoding"); + e.printStackTrace(); + } + } + + + public Iterator getIterator() { + return iterator(); + } + + public List loadFromFileInBatches(Integer batchsize) { + List result = new ArrayList(); + if (!EOF) { + try { + int i = 0; + while (!EOF && i++ < batchsize) { + String nextLine = bufferedReader.readLine(); + if (nextLine == null) + EOF = true; + else + result.add(nextLine); + } + if (EOF) { + bufferedReader.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return result; + } + + private class TextFileIterator implements Iterator { + private String buffer; + + public TextFileIterator() { + try { + buffer = bufferedReader.readLine(); + if(buffer == null) { + EOF = true; + bufferedReader.close(); + } + } + catch (IOException e) { + e.printStackTrace(); + } + + } + + public boolean hasNext() { + return !EOF; + } + + public String next() { + String result = buffer; + try { + buffer = bufferedReader.readLine(); + if(buffer == null) { + EOF = true; + bufferedReader.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + return result; + } + + public void remove() { + // not implemented + } + + } + + public Iterator iterator() { + return new TextFileIterator(); + } +} diff --git a/src/org/ohdsi/utilities/files/Row.java b/src/org/ohdsi/utilities/files/Row.java new file mode 100644 index 00000000..7d3a0d81 --- /dev/null +++ b/src/org/ohdsi/utilities/files/Row.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.ohdsi.utilities.StringUtilities; + +public class Row { + private List cells; + private Map fieldName2ColumnIndex; + + public Row() { + fieldName2ColumnIndex = new HashMap(); + cells = new ArrayList(); + } + + public Row(List cells, Map fieldName2ColumnIndex) { + this.cells = cells; + this.fieldName2ColumnIndex = fieldName2ColumnIndex; + } + + public Row(Row row) { + cells = new ArrayList(row.cells); + fieldName2ColumnIndex = new HashMap(row.fieldName2ColumnIndex); + } + + public String get(String fieldName) { + int index; + try { + index = fieldName2ColumnIndex.get(fieldName); + } catch (NullPointerException e) { + throw new RuntimeException("Field \"" + fieldName + "\" not found"); + } + if (cells.size() <= index) + return null; + else + return cells.get(index); + } + + public List getFieldNames() { + List names = new ArrayList(fieldName2ColumnIndex.size()); + for (int i = 0; i < fieldName2ColumnIndex.size(); i++) + names.add(null); + for (Map.Entry entry : fieldName2ColumnIndex.entrySet()) + names.set(entry.getValue(), entry.getKey()); + return names; + } + + public int getInt(String fieldName) { + return Integer.parseInt(get(fieldName).trim()); + } + + public long getLong(String fieldName) { + return Long.parseLong(get(fieldName)); + } + + public double getDouble(String fieldName) { + return Double.parseDouble(get(fieldName)); + } + + public void add(String fieldName, String value) { + fieldName2ColumnIndex.put(fieldName, cells.size()); + cells.add(value); + } + + public void add(String fieldName, int value) { + add(fieldName, Integer.toString(value)); + } + + public void add(String fieldName, boolean value) { + add(fieldName, Boolean.toString(value)); + } + + public void add(String fieldName, double value) { + add(fieldName, Double.toString(value)); + } + + public void add(String fieldName, long value) { + add(fieldName, Long.toString(value)); + } + + public void set(String fieldName, String value) { + cells.set(fieldName2ColumnIndex.get(fieldName), value); + } + + public void set(String fieldName, int value) { + set(fieldName, Integer.toString(value)); + } + + public void set(String fieldName, long value) { + set(fieldName, Long.toString(value)); + } + + public void set(String fieldName, double value) { + set(fieldName, Double.toString(value)); + } + + public List getCells() { + return cells; + } + + protected Map getfieldName2ColumnIndex() { + return fieldName2ColumnIndex; + } + + public String toString() { + List data = new ArrayList(cells); + for (String fieldName : fieldName2ColumnIndex.keySet()) { + int index = fieldName2ColumnIndex.get(fieldName); + if (data.size() > index) + data.set(index, "[" + fieldName + ": " + data.get(index) + "]"); + } + return StringUtilities.join(data, ","); + } + + public void remove(String field) { + Integer index = fieldName2ColumnIndex.remove(field); + cells.remove(index); + Map tempMap = new HashMap(); + for (Map.Entry entry : fieldName2ColumnIndex.entrySet()) + if (entry.getValue() > index) + tempMap.put(entry.getKey(), entry.getValue() - 1); + else + tempMap.put(entry.getKey(), entry.getValue()); + } +} diff --git a/src/org/ohdsi/utilities/files/RowUtilities.java b/src/org/ohdsi/utilities/files/RowUtilities.java new file mode 100644 index 00000000..7bad6051 --- /dev/null +++ b/src/org/ohdsi/utilities/files/RowUtilities.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class RowUtilities { + public static void sort(List rows, String... fieldName) { + if (rows.size() < 2) + return; + int[] indexes = new int[fieldName.length]; + for (int i = 0; i < fieldName.length; i++) { + Integer index = rows.get(0).getfieldName2ColumnIndex().get(fieldName[i]); + if (index == null) + throw new RuntimeException("Column '" + fieldName[i] + "' not found"); + indexes[i] = index; + } + Collections.sort(rows, new RowComparator(indexes)); + } + + private static class RowComparator implements Comparator { + private int[] indexes; + private StringIdComparator stringIdComparator = new StringIdComparator(); + + public RowComparator(int[] indexes) { + this.indexes = indexes; + } + + public int compare(Row o1, Row o2) { + int result = 0; + int i = 0; + while (result == 0 && i < indexes.length) { + String value1 = o1.getCells().get(indexes[i]); + String value2 = o2.getCells().get(indexes[i]); + result = stringIdComparator.compare(value1, value2); + i++; + } + return result; + } + + } +} diff --git a/src/org/ohdsi/utilities/files/StringIdComparator.java b/src/org/ohdsi/utilities/files/StringIdComparator.java new file mode 100644 index 00000000..6e0a6e70 --- /dev/null +++ b/src/org/ohdsi/utilities/files/StringIdComparator.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.util.Comparator; + +/** + * Comparator for strings. If both strings are numbers, they are compared as numbers, else as strings + * @author MSCHUEMI + * + */ +public class StringIdComparator implements Comparator { + + @Override + public int compare(String value1, String value2) { + if (isNumber(value1)) { + if (isNumber(value2)) + return efficientLongCompare(value1, value2); + else + return 1; + } else { + if (isNumber(value2)) + return -1; + else + return value1.compareTo(value2); + } + } + + private int efficientLongCompare(String value1, String value2) { + if (value1.length() > value2.length()) + return 1; + else if (value1.length() < value2.length()) + return -1; + else + return value1.compareTo(value2); + } + + private boolean isNumber(String string) { + if (string.length() == 0) + return false; + for (int i = 0; i < string.length(); i++) + if (!Character.isDigit(string.charAt(i))) + return false; + return true; + } + +} diff --git a/src/org/ohdsi/utilities/files/WriteCSVFile.java b/src/org/ohdsi/utilities/files/WriteCSVFile.java new file mode 100644 index 00000000..081d2b0e --- /dev/null +++ b/src/org/ohdsi/utilities/files/WriteCSVFile.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.io.BufferedWriter; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.util.Iterator; +import java.util.List; + +public class WriteCSVFile { + + public WriteCSVFile(String filename, boolean append) { + FileOutputStream stream; + try { + stream = new FileOutputStream(filename, append); + bufferedWrite = new BufferedWriter(new OutputStreamWriter(stream, "UTF-8"), 10000); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + } + + public WriteCSVFile(String filename) { + this(filename, false); + } + + public void write(List string) { + try { + bufferedWrite.write(columns2line(string)); + bufferedWrite.newLine(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static String columns2line(List columns) { + StringBuilder sb = new StringBuilder(); + Iterator iterator = columns.iterator(); + while (iterator.hasNext()) { + String column = iterator.next(); + column = column.replaceAll("\"", "\\\""); + column = column.replaceAll("\n", "\\n"); + if (column.contains(",")) + column = "\"" + column + "\""; + sb.append(column); + if (iterator.hasNext()) + sb.append(","); + } + return sb.toString(); + } + + public void flush() { + try { + bufferedWrite.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void close() { + try { + bufferedWrite.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private BufferedWriter bufferedWrite; +} diff --git a/src/org/ohdsi/utilities/files/WriteCSVFileWithHeader.java b/src/org/ohdsi/utilities/files/WriteCSVFileWithHeader.java new file mode 100644 index 00000000..2f1bcf92 --- /dev/null +++ b/src/org/ohdsi/utilities/files/WriteCSVFileWithHeader.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.ReentrantLock; + +public class WriteCSVFileWithHeader { + + private WriteCSVFile out; + private boolean headerWritten; + private boolean threadSafe = false; + private ReentrantLock lock; + + public WriteCSVFileWithHeader(String filename) { + out = new WriteCSVFile(filename); + headerWritten = false; + } + + public WriteCSVFileWithHeader(String filename, boolean append) { + out = new WriteCSVFile(filename, append); + headerWritten = true; + } + + public void write(Row row) { + if (threadSafe) + lock.lock(); + if (!headerWritten) + writeHeader(row); + out.write(row.getCells()); + if (threadSafe) + lock.unlock(); + } + + public void close() { + out.close(); + } + + public void flush() { + if (threadSafe) + lock.lock(); + out.flush(); + if (threadSafe) + lock.unlock(); + } + + public void setThreadSafe(boolean value) { + threadSafe = value; + if (threadSafe) + lock = new ReentrantLock(); + } + + public boolean getThreadSafe() { + return threadSafe; + } + + private void writeHeader(Row row) { + headerWritten = true; + Map fieldName2ColumnIndex = row.getfieldName2ColumnIndex(); + int size = fieldName2ColumnIndex.size(); + List header = new ArrayList(size); + for (int i = 0; i < size; i++) + header.add(null); + for (Map.Entry entry : fieldName2ColumnIndex.entrySet()) + header.set(entry.getValue(), entry.getKey()); + out.write(header); + } +} diff --git a/src/org/ohdsi/utilities/files/WriteTextFile.java b/src/org/ohdsi/utilities/files/WriteTextFile.java new file mode 100644 index 00000000..fe2a1709 --- /dev/null +++ b/src/org/ohdsi/utilities/files/WriteTextFile.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.utilities.files; + +import java.io.BufferedWriter; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; + +public class WriteTextFile { + + public WriteTextFile(String filename){ + FileOutputStream stream; + try { + stream = new FileOutputStream(filename); + bufferedWrite = new BufferedWriter( new OutputStreamWriter(stream, "UTF-8"),10000); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + System.err.println("Computer does not support UTF-8 encoding"); + e.printStackTrace(); + } + } + + public void writeln(String string){ + try { + bufferedWrite.write(string); + bufferedWrite.newLine(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void writeln(int integer){ + writeln(Integer.toString(integer)); + } + + public void writeln(Object object){ + writeln(object.toString()); + } + + public void flush(){ + try { + bufferedWrite.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void close() { + try { + bufferedWrite.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private BufferedWriter bufferedWrite; +} diff --git a/src/org/ohdsi/whiteRabbit/Console.java b/src/org/ohdsi/whiteRabbit/Console.java new file mode 100644 index 00000000..75518bba --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/Console.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.swing.JTextArea; +import javax.swing.text.BadLocationException; + +import org.ohdsi.utilities.files.WriteTextFile; + +public class Console extends OutputStream { + + private StringBuffer buffer = new StringBuffer(); + private WriteTextFile debug = null; + private JTextArea textArea; + + public void println(String string) { + textArea.append(string + "\n"); + textArea.repaint(); + System.out.println(string); + } + + public void setTextArea(JTextArea textArea) { + this.textArea = textArea; + } + + public void setDebugFile(String filename) { + debug = new WriteTextFile(filename); + } + + public String getText() { + try { + return textArea.getDocument().getText(0, textArea.getDocument().getLength()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void write(int b) throws IOException { + buffer.append((char) b); + if ((char) b == '\n') { + if (textArea != null) { + textArea.append(buffer.toString()); + textArea.setCaretPosition(textArea.getDocument().getLength()); + } + if (debug != null) { + debug.writeln(buffer.toString()); + debug.flush(); + } + buffer = new StringBuffer(); + } + } + +} diff --git a/src/org/ohdsi/whiteRabbit/DbSettings.java b/src/org/ohdsi/whiteRabbit/DbSettings.java new file mode 100644 index 00000000..95113ab2 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/DbSettings.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit; + +import java.util.ArrayList; +import java.util.List; + +import org.ohdsi.databases.DbType; + +public class DbSettings { + public static int DATABASE = 1; + public static int CSVFILES = 2; + + public int dataType; + public List tables = new ArrayList(); + + // Database settings + public DbType dbType; + public String user; + public String password; + public String database; + public String server; + public String domain; + + // CSV file settings + public char delimiter = ','; +} diff --git a/src/org/ohdsi/whiteRabbit/ErrorReport.java b/src/org/ohdsi/whiteRabbit/ErrorReport.java new file mode 100644 index 00000000..f8004ad1 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/ErrorReport.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit; + +import java.io.File; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; + +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.files.WriteTextFile; + +public class ErrorReport { + public static String generate(String folder, Exception e) { + String filename = folder + "/Error.txt"; + int i = 1; + while (new File(filename).exists()) + filename = folder + "/Error" + (i++) + ".txt"; + DecimalFormat df = new DecimalFormat(); + DecimalFormatSymbols dfs = new DecimalFormatSymbols(); + dfs.setGroupingSeparator(','); + df.setDecimalFormatSymbols(dfs); + + WriteTextFile out = new WriteTextFile(filename); + + out.writeln("*** Generic error information ***"); + out.writeln("Message: " + e.getMessage()); + out.writeln("Time: " + StringUtilities.now()); + Runtime runTime = Runtime.getRuntime(); + out.writeln("Processor type: " + System.getProperty("sun.cpu.isalist")); + out.writeln("Available processors: " + runTime.availableProcessors()); + out.writeln("Maximum available memory: " + df.format(runTime.maxMemory()) + " bytes"); + out.writeln("Used memory: " + df.format(runTime.totalMemory() - runTime.freeMemory()) + " bytes"); + out.writeln("Java version: " + System.getProperty("java.version")); + out.writeln("Java vendor: " + System.getProperty("java.vendor")); + out.writeln("OS architecture: " + System.getProperty("os.arch")); + out.writeln("OS name: " + System.getProperty("os.name")); + out.writeln("OS version: " + System.getProperty("os.version")); + out.writeln("OS patch level: " + System.getProperty("sun.os.patch.level")); + out.writeln(""); + out.writeln("*** Stack trace ***"); + for (StackTraceElement element : e.getStackTrace()) + out.writeln(element.toString()); + out.writeln(""); + out.writeln("*** Console ***"); + out.writeln(ObjectExchange.console.getText()); + out.writeln(""); + out.writeln("*** Working folder contents ***"); + out.writeln("Directory of " + folder); + out.writeln(""); + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + File[] files = new File(folder).listFiles(); + Arrays.sort(files, new Comparator() { + @Override + public int compare(File o1, File o2) { + return Long.valueOf(o1.lastModified()).compareTo(o2.lastModified()); + } + }); + + for (File file : files) { + String name = file.getName(); + String length = df.format(file.length()); + String dir = file.isDirectory() ? "" : " "; + String modifiedDate = sdf.format(new Date(file.lastModified())); + StringBuilder filler = new StringBuilder(); + for (int x = 0; x < (80 - name.length() - length.length()); x++) + filler.append(' '); + out.writeln(name + filler.toString() + length + " " + dir + " " + modifiedDate); + } + out.writeln(""); + out.writeln("Available disc space: " + df.format(new File(folder).getFreeSpace()) + " bytes"); + out.close(); + return filename; + } +} diff --git a/src/org/ohdsi/whiteRabbit/EtlReport.java b/src/org/ohdsi/whiteRabbit/EtlReport.java new file mode 100644 index 00000000..e3ce076b --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/EtlReport.java @@ -0,0 +1,239 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.collections.CountingSet; +import org.ohdsi.utilities.collections.CountingSet.Count; +import org.ohdsi.utilities.collections.IntegerComparator; +import org.ohdsi.utilities.collections.OneToManyList; +import org.ohdsi.utilities.files.MultiRowIterator.MultiRowSet; +import org.ohdsi.whiteRabbit.utilities.CodeToConceptMap; +import org.ohdsi.whiteRabbit.utilities.CodeToConceptMap.CodeData; + +public class EtlReport { + + public static long MAX_REPORT_PROBLEM = 1000; + + private Map problems = new HashMap(); + private CountingSet incomingTableRowCounts = new CountingSet(); + private CountingSet outgoingTableRowCounts = new CountingSet(); + private String folder; + private long totalProblemCount = 0; + + public EtlReport(String folder) { + this.folder = folder; + } + + public void reportProblem(String table, String problemType, String personId) { + totalProblemCount++; + Problem problem = problems.get(table + "\t" + problemType); + if (problem == null) { + problem = new Problem(); + problem.problemType = problemType; + problem.table = table; + problems.put(table + "\t" + problemType, problem); + } + problem.count++; + if (problem.count < MAX_REPORT_PROBLEM) + problem.personId.add(personId); + if (problem.count == MAX_REPORT_PROBLEM) + System.out.println("Warning: encountered " + MAX_REPORT_PROBLEM + " problems of type '" + problemType + "' in table " + table); + } + + public long getTotalProblemCount() { + return totalProblemCount; + } + + public String generateProblemList() { + StringUtilities.outputWithTime("Generating ETL problem list"); + String filename = generateETLProblemListFilename(folder); + XSSFWorkbook workbook = new XSSFWorkbook(); + + XSSFSheet sheet = workbook.createSheet("Problems"); + addRow(sheet, "Table", "Problem", "Person_id"); + for (Problem problem : problems.values()) { + for (int i = 0; i < Math.min(MAX_REPORT_PROBLEM, problem.count); i++) + addRow(sheet, problem.table, problem.problemType, problem.personId.get(i)); + if (problem.count > MAX_REPORT_PROBLEM) + addRow(sheet, problem.table, problem.problemType, "in " + (problem.count - MAX_REPORT_PROBLEM) + " other persons"); + } + try { + FileOutputStream out = new FileOutputStream(new File(filename)); + workbook.write(out); + out.close(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + return filename; + } + + public String generate(CodeToConceptMap... codeToConceptMaps) { + StringUtilities.outputWithTime("Generating ETL report"); + String filename = generateFilename(folder); + XSSFWorkbook workbook = new XSSFWorkbook(); + + XSSFSheet sheet = workbook.createSheet("Overview"); + addRow(sheet, "Source tables"); + addRow(sheet, ""); + addRow(sheet, "Table name", "Number of records"); + for (String table : incomingTableRowCounts) + addRow(sheet, table, Integer.valueOf(incomingTableRowCounts.getCount(table))); + addRow(sheet, ""); + + addRow(sheet, "CDM tables"); + addRow(sheet, ""); + addRow(sheet, "Table name", "Number of records"); + for (String table : outgoingTableRowCounts) + addRow(sheet, table, Integer.valueOf(outgoingTableRowCounts.getCount(table))); + addRow(sheet, ""); + + addRow(sheet, "Number of problems encountered", Long.valueOf(totalProblemCount)); + addRow(sheet, ""); + addRow(sheet, "Mapping", "Mapped unique codes", "Unmapped unique codes", "Mapped total codes", "Unmapped total codes"); + for (CodeToConceptMap codeToConceptMap : codeToConceptMaps) { + int uniqueMapped = 0; + int uniqueUnmapped = 0; + long totalMapped = 0; + long totalUnmapped = 0; + CountingSet codeCounts = codeToConceptMap.getCodeCounts(); + for (String code : codeCounts) { + if (!codeToConceptMap.getConceptId(code).equals(0)) { + uniqueMapped++; + totalMapped += codeCounts.getCount(code); + } else { + uniqueUnmapped++; + totalUnmapped += codeCounts.getCount(code); + } + } + addRow(sheet, codeToConceptMap.getName(), Integer.valueOf(uniqueMapped), Integer.valueOf(uniqueUnmapped), Long.valueOf(totalMapped), + Long.valueOf(totalUnmapped)); + } + + sheet = workbook.createSheet("Problems"); + addRow(sheet, "Table", "Description", "Nr of rows"); + for (Problem problem : problems.values()) + addRow(sheet, problem.table, problem.problemType, Long.valueOf(problem.count)); + + for (CodeToConceptMap codeToConceptMap : codeToConceptMaps) { + sheet = workbook.createSheet(codeToConceptMap.getName()); + addRow(sheet, "Frequency", "Source code", "Source code description", "Target concept ID", "Target code", "Target concept description"); + CountingSet codeCounts = codeToConceptMap.getCodeCounts(); + List> codes = new ArrayList>(codeCounts.key2count.entrySet()); + reverseFrequencySort(codes); + for (Map.Entry code : codes) { + CodeData codeData = codeToConceptMap.getCodeData(code.getKey()); + if (codeData == null) + addRow(sheet, Integer.valueOf(code.getValue().count), code.getKey(), "", Integer.valueOf(0), "", ""); + else + for (int i = 0; i < codeData.targetConceptIds.length; i++) + addRow(sheet, Integer.valueOf(code.getValue().count), code.getKey(), codeData.description, + Integer.valueOf(codeData.targetConceptIds[i]), codeData.targetCodes[i], codeData.targetDescriptions[i]); + } + } + + try { + FileOutputStream out = new FileOutputStream(new File(filename)); + workbook.write(out); + out.close(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + + return filename; + } + + private void reverseFrequencySort(List> codes) { + Collections.sort(codes, new Comparator>() { + + @Override + public int compare(Entry o1, Entry o2) { + return -IntegerComparator.compare(o1.getValue().count, o2.getValue().count); + } + }); + + } + + private void addRow(XSSFSheet sheet, Object... values) { + Row row = sheet.createRow(sheet.getPhysicalNumberOfRows()); + for (Object value : values) { + Cell cell = row.createCell(row.getPhysicalNumberOfCells()); + + if (value instanceof Integer && value instanceof Long && value instanceof Double) + cell.setCellValue(Double.valueOf(value.toString())); + else + cell.setCellValue(value.toString()); + + } + } + + private String generateFilename(String folder) { + String filename = folder + "/ETLReport.xlsx"; + int i = 1; + while (new File(filename).exists()) + filename = folder + "/ETLReport" + (i++) + ".xlsx"; + return filename; + } + + private String generateETLProblemListFilename(String folder) { + String filename = folder + "/ETLProblems.xlsx"; + int i = 1; + while (new File(filename).exists()) + filename = folder + "/ETLPRoblems" + (i++) + ".xlsx"; + return filename; + } + + public void registerIncomingData(String table, org.ohdsi.utilities.files.Row row) { + incomingTableRowCounts.add(table, 1); + } + + public void registerIncomingData(MultiRowSet data) { + for (String table : data.keySet()) + incomingTableRowCounts.add(table, data.get(table).size()); + } + + public void registerOutgoingData(OneToManyList data) { + for (String table : data.keySet()) + outgoingTableRowCounts.add(table, data.get(table).size()); + } + + private class Problem { + public String table; + public String problemType; + public long count = 0; + public List personId = new ArrayList(); + } +} diff --git a/src/org/ohdsi/whiteRabbit/ObjectExchange.java b/src/org/ohdsi/whiteRabbit/ObjectExchange.java new file mode 100644 index 00000000..612d6e24 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/ObjectExchange.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit; + +import javax.swing.JFrame; + +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.ETL; + +public class ObjectExchange { + public static JFrame frame; + public static Console console; + public static ETL etl; +} diff --git a/src/org/ohdsi/whiteRabbit/WhiteRabbit.ico b/src/org/ohdsi/whiteRabbit/WhiteRabbit.ico new file mode 100644 index 00000000..fd0a1949 Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/WhiteRabbit.ico differ diff --git a/src/org/ohdsi/whiteRabbit/WhiteRabbit128.png b/src/org/ohdsi/whiteRabbit/WhiteRabbit128.png new file mode 100644 index 00000000..1c4b6fa5 Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/WhiteRabbit128.png differ diff --git a/src/org/ohdsi/whiteRabbit/WhiteRabbit16.png b/src/org/ohdsi/whiteRabbit/WhiteRabbit16.png new file mode 100644 index 00000000..60bb7cfc Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/WhiteRabbit16.png differ diff --git a/src/org/ohdsi/whiteRabbit/WhiteRabbit256.png b/src/org/ohdsi/whiteRabbit/WhiteRabbit256.png new file mode 100644 index 00000000..708e5d0a Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/WhiteRabbit256.png differ diff --git a/src/org/ohdsi/whiteRabbit/WhiteRabbit32.png b/src/org/ohdsi/whiteRabbit/WhiteRabbit32.png new file mode 100644 index 00000000..2c1e62f4 Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/WhiteRabbit32.png differ diff --git a/src/org/ohdsi/whiteRabbit/WhiteRabbit48.png b/src/org/ohdsi/whiteRabbit/WhiteRabbit48.png new file mode 100644 index 00000000..4329065d Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/WhiteRabbit48.png differ diff --git a/src/org/ohdsi/whiteRabbit/WhiteRabbit64.png b/src/org/ohdsi/whiteRabbit/WhiteRabbit64.png new file mode 100644 index 00000000..830d066e Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/WhiteRabbit64.png differ diff --git a/src/org/ohdsi/whiteRabbit/WhiteRabbitMain.java b/src/org/ohdsi/whiteRabbit/WhiteRabbitMain.java new file mode 100644 index 00000000..8b12c963 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/WhiteRabbitMain.java @@ -0,0 +1,955 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.MediaTracker; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileNameExtensionFilter; + +import org.ohdsi.databases.DbType; +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.DirectoryUtilities; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.whiteRabbit.etls.ars.ARSETL; +import org.ohdsi.whiteRabbit.etls.hcup.HCUPETL; +import org.ohdsi.whiteRabbit.scan.SourceDataScan; +import org.ohdsi.whiteRabbit.utilities.SqlDump; +import org.ohdsi.whiteRabbit.vocabulary.InsertVocabularyInServer; + +public class WhiteRabbitMain { + + private JFrame frame; + private JTextField folderField; + private JTextField vocabFileField; + + private JComboBox etlType; + private JComboBox sourceType; + private JComboBox targetType; + private JTextField targetUserField; + private JTextField targetPasswordField; + private JTextField targetServerField; + private JTextField targetDatabaseField; + private JTextField sourceDelimiterField; + private JTextField sourceServerField; + private JTextField sourceUserField; + private JTextField sourcePasswordField; + private JTextField sourceDatabaseField; + private JButton addAllButton; + private JList tableList; + private List tables = new ArrayList(); + private JTextArea sqlArea; + private JTextField sqlDumpFilenameField; + private JButton dumpButton; + private boolean sourceIsFiles = true; + + private List componentsToDisableWhenRunning = new ArrayList(); + + public static void main(String[] args) { + new WhiteRabbitMain(args); + } + + public WhiteRabbitMain(String[] args) { + frame = new JFrame("White Rabbit"); + + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + frame.setLayout(new BorderLayout()); + + JComponent tabsPanel = createTabsPanel(); + JComponent consolePanel = createConsolePanel(); + + frame.add(consolePanel, BorderLayout.CENTER); + frame.add(tabsPanel, BorderLayout.NORTH); + + loadIcons(frame); + frame.pack(); + frame.setVisible(true); + ObjectExchange.frame = frame; + executeParameters(args); + } + + private JComponent createTabsPanel() { + JTabbedPane tabbedPane = new JTabbedPane(); + + JPanel locationPanel = createLocationsPanel(); + tabbedPane.addTab("Locations", null, locationPanel, "Specify the location of the source data, the CDM, and the working folder"); + + JPanel dumpPanel = createSqlDumpPanel(); + tabbedPane.addTab("Bulk SQL dump", null, dumpPanel, "Write the results of a SQL query to a CSV file"); + + JPanel scanPanel = createScanPanel(); + tabbedPane.addTab("Scan", null, scanPanel, "Create a scan of the source data"); + + JPanel vocabPanel = createVocabPanel(); + tabbedPane.addTab("Vocabulary", null, vocabPanel, "Upload the vocabulary to the server"); + + JPanel etlPanel = createEtlPanel(); + tabbedPane.addTab("ETL", null, etlPanel, "Extract, Transform and Load the data into the OMOP CDM"); + + return tabbedPane; + } + + private JPanel createLocationsPanel() { + JPanel panel = new JPanel(); + + panel.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.weightx = 0.5; + + JPanel folderPanel = new JPanel(); + folderPanel.setLayout(new BoxLayout(folderPanel, BoxLayout.X_AXIS)); + folderPanel.setBorder(BorderFactory.createTitledBorder("Working folder")); + folderField = new JTextField(); + folderField.setText((new File("").getAbsolutePath())); + folderField.setToolTipText("The folder where all output will be written"); + folderPanel.add(folderField); + JButton pickButton = new JButton("Pick folder"); + pickButton.setToolTipText("Pick a different working folder"); + folderPanel.add(pickButton); + pickButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + pickFile(); + } + }); + componentsToDisableWhenRunning.add(pickButton); + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + panel.add(folderPanel, c); + + JPanel sourcePanel = new JPanel(); + sourcePanel.setLayout(new GridLayout(0, 2)); + sourcePanel.setBorder(BorderFactory.createTitledBorder("Source data location")); + sourcePanel.add(new JLabel("Data type")); + sourceType = new JComboBox(new String[] { "Delimited text files", "MySQL", "Oracle", "SQL Server", "PostgreSQL" }); + sourceType.setToolTipText("Select the type of source data available"); + sourceType.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent arg0) { + sourceIsFiles = arg0.getItem().toString().equals("Delimited text files"); + sourceServerField.setEnabled(!sourceIsFiles); + sourceUserField.setEnabled(!sourceIsFiles); + sourcePasswordField.setEnabled(!sourceIsFiles); + sourceDatabaseField.setEnabled(!sourceIsFiles); + sourceDelimiterField.setEnabled(sourceIsFiles); + addAllButton.setEnabled(!sourceIsFiles); + dumpButton.setEnabled(!sourceIsFiles); + + if (!sourceIsFiles && arg0.getItem().toString().equals("Oracle")) { + sourceServerField + .setToolTipText("For Oracle servers this field contains the SID, servicename, and optionally the port: '/', ':/', '/', or ':/'"); + sourceUserField.setToolTipText("For Oracle servers this field contains the name of the user used to log in"); + sourcePasswordField.setToolTipText("For Oracle servers this field contains the password corresponding to the user"); + sourceDatabaseField + .setToolTipText("For Oracle servers this field contains the schema (i.e. 'user' in Oracle terms) containing the source tables"); + } else if (!sourceIsFiles && arg0.getItem().toString().equals("PostgreSQL")) { + sourceServerField.setToolTipText("For PostgreSQL servers this field contains the host name and database name (/)"); + sourceUserField.setToolTipText("The user used to log in to the server"); + sourcePasswordField.setToolTipText("The password used to log in to the server"); + sourceDatabaseField.setToolTipText("For PostgreSQL servers this field contains the schema containing the source tables"); + } else if (!sourceIsFiles) { + sourceServerField.setToolTipText("This field contains the name or IP address of the database server"); + if (arg0.getItem().toString().equals("SQL Server")) + sourceUserField + .setToolTipText("The user used to log in to the server. Optionally, the domain can be specified as / (e.g. 'MyDomain/Joe')"); + else + sourceUserField.setToolTipText("The user used to log in to the server"); + sourcePasswordField.setToolTipText("The password used to log in to the server"); + sourceDatabaseField.setToolTipText("The name of the database containing the source tables"); + } + } + }); + sourcePanel.add(sourceType); + + sourcePanel.add(new JLabel("Server location")); + sourceServerField = new JTextField("127.0.0.1"); + sourceServerField.setEnabled(false); + sourcePanel.add(sourceServerField); + sourcePanel.add(new JLabel("User name")); + sourceUserField = new JTextField(""); + sourceUserField.setEnabled(false); + sourcePanel.add(sourceUserField); + sourcePanel.add(new JLabel("Password")); + sourcePasswordField = new JPasswordField(""); + sourcePasswordField.setEnabled(false); + sourcePanel.add(sourcePasswordField); + sourcePanel.add(new JLabel("Database name")); + sourceDatabaseField = new JTextField(""); + sourceDatabaseField.setEnabled(false); + sourcePanel.add(sourceDatabaseField); + + sourcePanel.add(new JLabel("Delimiter")); + sourceDelimiterField = new JTextField(","); + sourceDelimiterField.setToolTipText("The delimiter that separates values. Enter 'tab' for tab."); + sourcePanel.add(sourceDelimiterField); + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + panel.add(sourcePanel, c); + + JPanel targetPanel = new JPanel(); + targetPanel.setLayout(new GridLayout(0, 2)); + targetPanel.setBorder(BorderFactory.createTitledBorder("Target data location")); + targetPanel.add(new JLabel("Data type")); + targetType = new JComboBox(new String[] { "MySQL", "Oracle", "SQL Server", "PostgreSQL" }); + targetType.setToolTipText("Select the type of server where the CDM and vocabulary will be stored"); + targetPanel.add(targetType); + targetPanel.add(new JLabel("Server location")); + targetServerField = new JTextField("127.0.0.1"); + targetPanel.add(targetServerField); + targetPanel.add(new JLabel("User name")); + targetUserField = new JTextField("root"); + targetPanel.add(targetUserField); + targetPanel.add(new JLabel("Password")); + targetPasswordField = new JPasswordField(""); + targetPanel.add(targetPasswordField); + targetPanel.add(new JLabel("CDM database name")); + targetDatabaseField = new JTextField("CDM_v4"); + targetPanel.add(targetDatabaseField); + targetPanel.add(new JLabel("")); + targetPanel.add(new JLabel("")); + + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + panel.add(targetPanel, c); + + return panel; + } + + private JPanel createSqlDumpPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + + JPanel inputPanel = new JPanel(); + inputPanel.setLayout(new BorderLayout()); + + sqlArea = new JTextArea(); + sqlArea.setToolTipText("Enter the SQL statement to retrieve the date here"); + JScrollPane sqlPane = new JScrollPane(sqlArea); + sqlPane.setBorder(BorderFactory.createTitledBorder("SQL")); + sqlPane.setAutoscrolls(true); + inputPanel.add(sqlPane, BorderLayout.CENTER); + + sqlDumpFilenameField = new JTextField("Dump.csv"); + sqlDumpFilenameField.setBorder(BorderFactory.createTitledBorder("Output filename")); + sqlDumpFilenameField.setToolTipText("The name of the CSV file where the result of the SQL query will be written"); + inputPanel.add(sqlDumpFilenameField, BorderLayout.SOUTH); + + panel.add(inputPanel, BorderLayout.CENTER); + + JPanel dumpButtonPanel = new JPanel(); + dumpButtonPanel.setLayout(new BoxLayout(dumpButtonPanel, BoxLayout.X_AXIS)); + dumpButtonPanel.add(Box.createHorizontalGlue()); + + dumpButton = new JButton("Dump SQL results to file"); + dumpButton.setBackground(new Color(151, 220, 141)); + dumpButton.setToolTipText("Execute the SQL statement, and write the output to the file"); + dumpButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + sqlDumpRun(); + } + }); + dumpButton.setEnabled(false); + componentsToDisableWhenRunning.add(dumpButton); + dumpButtonPanel.add(dumpButton); + panel.add(dumpButtonPanel, BorderLayout.SOUTH); + + return panel; + } + + private JPanel createScanPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + + JPanel tablePanel = new JPanel(); + tablePanel.setLayout(new BorderLayout()); + tablePanel.setBorder(new TitledBorder("Tables")); + tableList = new JList(); + tableList.setToolTipText("Specify the tables (or CSV files) to be scanned here"); + tablePanel.add(new JScrollPane(tableList), BorderLayout.CENTER); + + JPanel tableButtonPanel = new JPanel(); + tableButtonPanel.setLayout(new GridLayout(3, 1)); + addAllButton = new JButton("Add all in DB"); + addAllButton.setToolTipText("Add all tables in the database"); + addAllButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + addAllTables(); + } + }); + addAllButton.setEnabled(false); + tableButtonPanel.add(addAllButton); + JButton addButton = new JButton("Add"); + addButton.setToolTipText("Add tables to list"); + addButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + pickTables(); + } + }); + tableButtonPanel.add(addButton); + JButton removeButton = new JButton("Remove"); + removeButton.setToolTipText("Remove tables from list"); + removeButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + removeTables(); + } + }); + tableButtonPanel.add(removeButton); + tablePanel.add(tableButtonPanel, BorderLayout.EAST); + + panel.add(tablePanel, BorderLayout.CENTER); + + JPanel scanButtonPanel = new JPanel(); + scanButtonPanel.setLayout(new BoxLayout(scanButtonPanel, BoxLayout.X_AXIS)); + scanButtonPanel.add(Box.createHorizontalGlue()); + + JButton scan100kButton = new JButton("Scan 100k rows per table"); + scan100kButton.setBackground(new Color(151, 220, 141)); + scan100kButton.setToolTipText("Perform the scan on a random sample of 100,000 rows per table"); + scan100kButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scanRun(100000); + } + }); + componentsToDisableWhenRunning.add(scan100kButton); + scanButtonPanel.add(scan100kButton); + + JButton scan1mButton = new JButton("Scan 1m rows per table"); + scan1mButton.setBackground(new Color(151, 220, 141)); + scan1mButton.setToolTipText("Perform the scan on a random sample of 1 million rows per table"); + scan1mButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scanRun(1000000); + } + }); + componentsToDisableWhenRunning.add(scan1mButton); + scanButtonPanel.add(scan1mButton); + + JButton scanButton = new JButton("Scan full tables"); + scanButton.setBackground(new Color(151, 220, 141)); + scanButton.setToolTipText("Perform the scan on the full tables"); + scanButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scanRun(-1); + } + }); + componentsToDisableWhenRunning.add(scanButton); + scanButtonPanel.add(scanButton); + panel.add(scanButtonPanel, BorderLayout.SOUTH); + + return panel; + } + + private JPanel createVocabPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + + JPanel vocabFilePanel = new JPanel(); + vocabFilePanel.setLayout(new BoxLayout(vocabFilePanel, BoxLayout.X_AXIS)); + vocabFilePanel.setBorder(BorderFactory.createTitledBorder("Vocabulary data file")); + + vocabFileField = new JTextField(); + vocabFileField.setText("Vocabulary.dat"); + vocabFileField.setToolTipText("Specify the name of the file containing the vocabulary here"); + vocabFilePanel.add(vocabFileField); + JButton pickButton = new JButton("Pick file"); + pickButton.setToolTipText("Select a different vocabulary file"); + vocabFilePanel.add(pickButton); + pickButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + pickVocabFile(); + } + }); + vocabFilePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, vocabFilePanel.getPreferredSize().height)); + panel.add(vocabFilePanel); + + panel.add(Box.createVerticalGlue()); + + JPanel vocabButtonPanel = new JPanel(); + vocabButtonPanel.setLayout(new BoxLayout(vocabButtonPanel, BoxLayout.X_AXIS)); + + vocabButtonPanel.add(Box.createHorizontalGlue()); + JButton vocabButton = new JButton("Insert vocabulary"); + vocabButton.setBackground(new Color(151, 220, 141)); + vocabButton.setToolTipText("Insert the vocabulary database into the server"); + vocabButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + vocabRun(); + } + }); + componentsToDisableWhenRunning.add(vocabButton); + vocabButtonPanel.add(vocabButton); + + panel.add(vocabButtonPanel); + + return panel; + } + + private JPanel createEtlPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + + JPanel etlTypePanel = new JPanel(); + etlTypePanel.setLayout(new BoxLayout(etlTypePanel, BoxLayout.X_AXIS)); + etlTypePanel.setBorder(BorderFactory.createTitledBorder("ETL type")); + etlType = new JComboBox(new String[] { "ARS -> OMOP CDM V4", "HCUP -> OMOP CDM V4" }); + etlType.setToolTipText("Select the appropriate ETL process"); + etlTypePanel.add(etlType); + etlTypePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, etlTypePanel.getPreferredSize().height)); + panel.add(etlTypePanel); + + panel.add(Box.createVerticalGlue()); + + JPanel etlButtonPanel = new JPanel(); + etlButtonPanel.setLayout(new BoxLayout(etlButtonPanel, BoxLayout.X_AXIS)); + etlButtonPanel.add(Box.createHorizontalGlue()); + + JButton etl10kButton = new JButton("Perform 10k persons ETL"); + etl10kButton.setBackground(new Color(151, 220, 141)); + etl10kButton.setToolTipText("Perform the ETL for the first 10,000 persons"); + etl10kButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + etlRun(10000); + } + }); + componentsToDisableWhenRunning.add(etl10kButton); + etlButtonPanel.add(etl10kButton); + + // etlButtonPanel.add(Box.createHorizontalStrut(10)); + + JButton etlButton = new JButton("Perform ETL"); + etlButton.setBackground(new Color(151, 220, 141)); + etlButton.setToolTipText("Extract, Transform and Load the data into the OMOP CDM"); + etlButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + etlRun(Integer.MAX_VALUE); + } + }); + componentsToDisableWhenRunning.add(etlButton); + etlButtonPanel.add(etlButton); + panel.add(etlButtonPanel); + + return panel; + } + + private JComponent createConsolePanel() { + JTextArea consoleArea = new JTextArea(); + consoleArea.setToolTipText("General progress information"); + consoleArea.setEditable(false); + Console console = new Console(); + console.setTextArea(consoleArea); + // console.setDebugFile("c:/temp/debug.txt"); + System.setOut(new PrintStream(console)); + System.setErr(new PrintStream(console)); + JScrollPane consoleScrollPane = new JScrollPane(consoleArea); + consoleScrollPane.setBorder(BorderFactory.createTitledBorder("Console")); + consoleScrollPane.setPreferredSize(new Dimension(800, 200)); + consoleScrollPane.setAutoscrolls(true); + ObjectExchange.console = console; + return consoleScrollPane; + } + + private void loadIcons(JFrame f) { + List icons = new ArrayList(); + icons.add(loadIcon("WhiteRabbit16.png", f)); + icons.add(loadIcon("WhiteRabbit32.png", f)); + icons.add(loadIcon("WhiteRabbit48.png", f)); + icons.add(loadIcon("WhiteRabbit64.png", f)); + icons.add(loadIcon("WhiteRabbit128.png", f)); + icons.add(loadIcon("WhiteRabbit256.png", f)); + f.setIconImages(icons); + } + + private Image loadIcon(String name, JFrame f) { + Image icon = Toolkit.getDefaultToolkit().getImage(WhiteRabbitMain.class.getResource(name)); + MediaTracker mediaTracker = new MediaTracker(f); + mediaTracker.addImage(icon, 0); + try { + mediaTracker.waitForID(0); + return icon; + } catch (Exception e1) { + e1.printStackTrace(); + } + return null; + } + + private void executeParameters(String[] args) { + String mode = null; + for (String arg : args) { + if (arg.startsWith("-")) { + mode = arg.toLowerCase(); + } else { + if (mode.equals("-folder")) + folderField.setText(arg); + if (mode.equals("-targetpassword")) + targetPasswordField.setText(arg); + if (mode.equals("-targetserver")) + targetServerField.setText(arg); + if (mode.equals("-targettype")) + targetType.setSelectedItem(arg); + if (mode.equals("-targetdatabase")) + targetDatabaseField.setText(arg); + if (mode.equals("-targetuser")) + targetUserField.setText(arg); + if (mode.equals("-sourceserver")) + sourceServerField.setText(arg); + if (mode.equals("-sourcetype")) + sourceType.setSelectedItem(arg); + if (mode.equals("-sourcedatabase")) + sourceDatabaseField.setText(arg); + if (mode.equals("-sourceuser")) + sourceUserField.setText(arg); + mode = null; + } + } + } + + private void pickFile() { + JFileChooser fileChooser = new JFileChooser(new File(folderField.getText())); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + int returnVal = fileChooser.showDialog(frame, "Select folder"); + if (returnVal == JFileChooser.APPROVE_OPTION) + folderField.setText(fileChooser.getSelectedFile().getAbsolutePath()); + } + + private void removeTables() { + for (Object item : tableList.getSelectedValues()) { + tables.remove(item); + tableList.setListData(tables.toArray()); + } + } + + private void addAllTables() { + DbSettings sourceDbSettings = getSourceDbSettings(); + if (sourceDbSettings != null) { + RichConnection connection = new RichConnection(sourceDbSettings.server, sourceDbSettings.domain, sourceDbSettings.user, sourceDbSettings.password, + sourceDbSettings.dbType); + for (String table : connection.getTableNames(sourceDbSettings.database)) { + if (!tables.contains(table)) + tables.add((String) table); + tableList.setListData(tables.toArray()); + } + connection.close(); + } + } + + private void pickTables() { + DbSettings sourceDbSettings = getSourceDbSettings(); + if (sourceDbSettings != null) { + if (sourceDbSettings.dataType == DbSettings.CSVFILES) { + JFileChooser fileChooser = new JFileChooser(new File(folderField.getText())); + fileChooser.setMultiSelectionEnabled(true); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + FileNameExtensionFilter filter = new FileNameExtensionFilter("Delimited text files", "csv", "txt"); + fileChooser.setFileFilter(filter); + + int returnVal = fileChooser.showDialog(frame, "Select tables"); + if (returnVal == JFileChooser.APPROVE_OPTION) { + for (File table : fileChooser.getSelectedFiles()) { + String tableName = DirectoryUtilities.getRelativePath(new File(folderField.getText()), table); + if (!tables.contains(tableName)) + tables.add(tableName); + tableList.setListData(tables.toArray()); + } + + } + } else if (sourceDbSettings.dataType == DbSettings.DATABASE) { + RichConnection connection = new RichConnection(sourceDbSettings.server, sourceDbSettings.domain, sourceDbSettings.user, + sourceDbSettings.password, sourceDbSettings.dbType); + String tableNames = StringUtilities.join(connection.getTableNames(sourceDbSettings.database), "\t"); + DBTableSelectionDialog selectionDialog = new DBTableSelectionDialog(frame, true, tableNames); + if (selectionDialog.getAnswer()) { + for (Object item : selectionDialog.getSelectedItems()) { + if (!tables.contains(item)) + tables.add((String) item); + tableList.setListData(tables.toArray()); + } + } + connection.close(); + } + } + } + + private void pickVocabFile() { + JFileChooser fileChooser = new JFileChooser(new File(folderField.getText())); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + int returnVal = fileChooser.showDialog(frame, "Select vocabulary file"); + if (returnVal == JFileChooser.APPROVE_OPTION) + vocabFileField.setText(DirectoryUtilities.getRelativePath(new File(folderField.getText()), fileChooser.getSelectedFile())); + } + + private DbSettings getSourceDbSettings() { + DbSettings dbSettings = new DbSettings(); + if (sourceType.getSelectedItem().equals("Delimited text files")) { + dbSettings.dataType = DbSettings.CSVFILES; + if (sourceDelimiterField.getText().length() == 0) { + JOptionPane.showMessageDialog(frame, "Delimiter field cannot be empty for source database", "Error connecting to server", + JOptionPane.ERROR_MESSAGE); + return null; + } + if (sourceDelimiterField.getText().toLowerCase().equals("tab")) + dbSettings.delimiter = '\t'; + else + dbSettings.delimiter = sourceDelimiterField.getText().charAt(0); + } else { + dbSettings.dataType = DbSettings.DATABASE; + dbSettings.user = sourceUserField.getText(); + dbSettings.password = sourcePasswordField.getText(); + dbSettings.server = sourceServerField.getText(); + dbSettings.database = sourceDatabaseField.getText().trim().length() == 0 ? null : sourceDatabaseField.getText(); + if (sourceType.getSelectedItem().toString().equals("MySQL")) + dbSettings.dbType = DbType.MYSQL; + else if (sourceType.getSelectedItem().toString().equals("Oracle")) + dbSettings.dbType = DbType.ORACLE; + else if (sourceType.getSelectedItem().toString().equals("PostgreSQL")) + dbSettings.dbType = DbType.POSTGRESQL; + else if (sourceType.getSelectedItem().toString().equals("SQL Server")) { + dbSettings.dbType = DbType.MSSQL; + if (sourceUserField.getText().length() != 0) { // Not using windows authentication + String[] parts = sourceUserField.getText().split("/"); + if (parts.length < 2) { + throw new RuntimeException("For SQL server you need to specify the domain in the user name field (e.g. Mydomain/Joe)"); + } else { + dbSettings.user = parts[1]; + dbSettings.domain = parts[0]; + } + } + + } + + if (dbSettings.database == null) { + String message = "Please specify a name for the source database"; + JOptionPane.showMessageDialog(frame, StringUtilities.wordWrap(message, 80), "Database error", JOptionPane.ERROR_MESSAGE); + return null; + } + + } + return dbSettings; + } + + private void testConnection(DbSettings dbSettings, boolean testConnectionToDb) { + RichConnection connection; + try { + connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + } catch (Exception e) { + String message = "Could not connect to source server: " + e.getMessage(); + JOptionPane.showMessageDialog(frame, StringUtilities.wordWrap(message, 80), "Error connecting to server", JOptionPane.ERROR_MESSAGE); + return; + } + + if (testConnectionToDb) + try { + connection.getTableNames(dbSettings.database); + } catch (Exception e) { + String message = "Could not connect to database: " + e.getMessage(); + JOptionPane.showMessageDialog(frame, StringUtilities.wordWrap(message, 80), "Error connecting to server", JOptionPane.ERROR_MESSAGE); + return; + } + + connection.close(); + } + + private DbSettings getTargetDbSettings() { + DbSettings dbSettings = new DbSettings(); + dbSettings.dataType = DbSettings.DATABASE; + dbSettings.user = targetUserField.getText(); + dbSettings.password = targetPasswordField.getText(); + dbSettings.server = targetServerField.getText(); + dbSettings.database = targetDatabaseField.getText(); + if (targetType.getSelectedItem().toString().equals("MySQL")) + dbSettings.dbType = DbType.MYSQL; + else if (targetType.getSelectedItem().toString().equals("Oracle")) + dbSettings.dbType = DbType.ORACLE; + else if (sourceType.getSelectedItem().toString().equals("PostgreSQL")) + dbSettings.dbType = DbType.POSTGRESQL; + else if (sourceType.getSelectedItem().toString().equals("SQL Server")) { + dbSettings.dbType = DbType.MSSQL; + if (sourceUserField.getText().length() != 0) { // Not using windows authentication + String[] parts = sourceUserField.getText().split("/"); + if (parts.length < 2) { + throw new RuntimeException("For SQL server you need to specify the domain in the user name field (e.g. Mydomain/Joe)"); + } else { + dbSettings.user = parts[1]; + dbSettings.domain = parts[0]; + } + } + } + + if (dbSettings.database.trim().length() == 0) { + String message = "Please specify a name for the target database"; + JOptionPane.showMessageDialog(frame, StringUtilities.wordWrap(message, 80), "Database error", JOptionPane.ERROR_MESSAGE); + return null; + } + + return dbSettings; + } + + private void etlRun(int maxPersons) { + EtlThread etlThread = new EtlThread(maxPersons); + etlThread.start(); + } + + private void scanRun(int maxRows) { + ScanThread scanThread = new ScanThread(maxRows); + scanThread.start(); + } + + private void sqlDumpRun() { + SqlDumpThread sqlDumpThread = new SqlDumpThread(); + sqlDumpThread.start(); + } + + private void vocabRun() { + VocabRunThread thread = new VocabRunThread(); + thread.start(); + } + + private class SqlDumpThread extends Thread { + + public void run() { + for (JComponent component : componentsToDisableWhenRunning) + component.setEnabled(false); + try { + DbSettings dbSettings = getSourceDbSettings(); + testConnection(dbSettings, true); + if (dbSettings != null) { + SqlDump sqlDump = new SqlDump(); + sqlDump.process(dbSettings, sqlArea.getText(), folderField.getText() + "/" + sqlDumpFilenameField.getText()); + } + + } catch (Exception e) { + handleError(e); + } finally { + for (JComponent component : componentsToDisableWhenRunning) + component.setEnabled(true); + dumpButton.setEnabled(!sourceIsFiles); + } + } + + } + + private class EtlThread extends Thread { + + private int maxPersons; + + public EtlThread(int maxPersons) { + this.maxPersons = maxPersons; + } + + public void run() { + for (JComponent component : componentsToDisableWhenRunning) + component.setEnabled(false); + + try { + if (etlType.getSelectedItem().equals("ARS -> OMOP CDM V4")) { + ARSETL etl = new ARSETL(); + DbSettings dbSettings = getTargetDbSettings(); + testConnection(dbSettings, false); + if (dbSettings != null) + etl.process(folderField.getText(), dbSettings, maxPersons); + } + if (etlType.getSelectedItem().equals("HCUP -> OMOP CDM V4")) { + HCUPETL etl = new HCUPETL(); + DbSettings sourceDbSettings = getSourceDbSettings(); + DbSettings targetDbSettings = getTargetDbSettings(); + if (sourceDbSettings != null && targetDbSettings != null) { + testConnection(sourceDbSettings, true); + testConnection(targetDbSettings, false); + etl.process(folderField.getText(), sourceDbSettings, targetDbSettings, maxPersons); + } + } + + } catch (Exception e) { + handleError(e); + } finally { + for (JComponent component : componentsToDisableWhenRunning) + component.setEnabled(true); + dumpButton.setEnabled(!sourceIsFiles); + } + } + + } + + private class ScanThread extends Thread { + + private int maxRows; + + public ScanThread(int maxRows) { + this.maxRows = maxRows; + } + + public void run() { + for (JComponent component : componentsToDisableWhenRunning) + component.setEnabled(false); + try { + SourceDataScan sourceDataScan = new SourceDataScan(); + DbSettings dbSettings = getSourceDbSettings(); + if (dbSettings != null) { + for (String table : tables) { + if (dbSettings.dataType == DbSettings.CSVFILES) + table = folderField.getText() + "/" + table; + dbSettings.tables.add(table); + } + sourceDataScan.process(dbSettings, maxRows, folderField.getText() + "/ScanReport.xlsx"); + } + } catch (Exception e) { + handleError(e); + } finally { + for (JComponent component : componentsToDisableWhenRunning) + component.setEnabled(true); + dumpButton.setEnabled(!sourceIsFiles); + } + } + + } + + private class VocabRunThread extends Thread { + + public void run() { + for (JComponent component : componentsToDisableWhenRunning) + component.setEnabled(false); + try { + InsertVocabularyInServer process = new InsertVocabularyInServer(); + DbSettings dbSettings = getTargetDbSettings(); + if (dbSettings != null) + process.process(folderField.getText() + "/" + vocabFileField.getText(), dbSettings); + } catch (Exception e) { + handleError(e); + } finally { + for (JComponent component : componentsToDisableWhenRunning) + component.setEnabled(true); + dumpButton.setEnabled(!sourceIsFiles); + } + + } + } + + private class DBTableSelectionDialog extends JDialog implements ActionListener { + private static final long serialVersionUID = 4527207331482143091L; + private JButton yesButton = null; + private JButton noButton = null; + private boolean answer = false; + private JList list; + + public boolean getAnswer() { + return answer; + } + + public DBTableSelectionDialog(JFrame frame, boolean modal, String tableNames) { + super(frame, modal); + + setTitle("Select tables"); + JPanel panel = new JPanel(); + panel.setPreferredSize(new Dimension(800, 500)); + getContentPane().add(panel); + panel.setLayout(new BorderLayout()); + + JLabel message = new JLabel("Select tables"); + panel.add(message, BorderLayout.NORTH); + + list = new JList(tableNames.split("\t")); + JScrollPane scrollPane = new JScrollPane(list); + panel.add(scrollPane, BorderLayout.CENTER); + + JPanel buttonPanel = new JPanel(); + yesButton = new JButton("Select tables"); + yesButton.addActionListener(this); + buttonPanel.add(yesButton); + noButton = new JButton("Cancel"); + noButton.addActionListener(this); + buttonPanel.add(noButton); + panel.add(buttonPanel, BorderLayout.SOUTH); + + pack(); + setLocationRelativeTo(frame); + setVisible(true); + } + + public void actionPerformed(ActionEvent e) { + if (yesButton == e.getSource()) { + answer = true; + setVisible(false); + } else if (noButton == e.getSource()) { + answer = false; + setVisible(false); + } + } + + public Object[] getSelectedItems() { + return list.getSelectedValues(); + } + + } + + private void handleError(Exception e) { + System.err.println("Error: " + e.getMessage()); + String errorReportFilename = ErrorReport.generate(folderField.getText(), e); + String message = "Error: " + e.getLocalizedMessage(); + message += "\nAn error report has been generated:\n" + errorReportFilename; + System.out.println(message); + JOptionPane.showMessageDialog(frame, StringUtilities.wordWrap(message, 80), "Error", JOptionPane.ERROR_MESSAGE); + } + +} diff --git a/src/org/ohdsi/whiteRabbit/WhiteRabbitProcess.java b/src/org/ohdsi/whiteRabbit/WhiteRabbitProcess.java new file mode 100644 index 00000000..627f6f27 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/WhiteRabbitProcess.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit; + +public class WhiteRabbitProcess { + public void process(String folder) { + if (!folder.endsWith("/")) + folder = folder + "/"; + + + + } +} diff --git a/src/org/ohdsi/whiteRabbit/cdm/CDMV4NullableChecker.java b/src/org/ohdsi/whiteRabbit/cdm/CDMV4NullableChecker.java new file mode 100644 index 00000000..788db98c --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/cdm/CDMV4NullableChecker.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.cdm; + +import org.ohdsi.utilities.collections.OneToManySet; +import org.ohdsi.utilities.files.ReadCSVFileWithHeader; +import org.ohdsi.utilities.files.Row; + +public class CDMV4NullableChecker { + + private OneToManySet tableToNotNullableFields; + + public CDMV4NullableChecker() { + tableToNotNullableFields = new OneToManySet(); + for (Row row : new ReadCSVFileWithHeader(this.getClass().getResourceAsStream("NotNullableV4.csv"))) { + if (row.get("IS_NULLABLE").equals("NO")) + tableToNotNullableFields.put(row.get("TABLE_NAME").toLowerCase(), row.get("COLUMN_NAME").toLowerCase()); + } + } + + public String findNonAllowedNull(String tableName, Row row) { + for (String notNullableField : tableToNotNullableFields.get(tableName)) + try { + if (row.get(notNullableField).length() == 0) + return notNullableField; + } catch (Exception e) { + return notNullableField; + } + return null; + } +} diff --git a/src/org/ohdsi/whiteRabbit/cdm/CdmV4.java b/src/org/ohdsi/whiteRabbit/cdm/CdmV4.java new file mode 100644 index 00000000..f048bcdd --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/cdm/CdmV4.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.cdm; + +import org.ohdsi.databases.DbType; +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.whiteRabbit.DbSettings; + +public class CdmV4 { + + public static void createStructure(DbSettings dbSettings) { + RichConnection connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + connection.setContext(CdmV4.class); + connection.setVerbose(false); + + StringUtilities.outputWithTime("Creating CDM V4 data structure"); + if (dbSettings.dbType == DbType.MYSQL) { + connection.execute("CREATE DATABASE IF NOT EXISTS `" + dbSettings.database + "`"); + connection.use(dbSettings.database); + connection.executeResource("CreateCDMStructureMySQL.sql"); + } else if (dbSettings.dbType == DbType.MSSQL) { + //connection.execute("CREATE DATABASE IF NOT EXISTS \"" + dbSettings.database + "\""); + connection.use(dbSettings.database); + connection.executeResource("CreateCDMStructureSQLServer.sql"); + } + + } + + public static void createIndices(DbSettings dbSettings) { + RichConnection connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + connection.setContext(CdmV4.class); + connection.setVerbose(false); + + StringUtilities.outputWithTime("Creating CDM V4 indices"); + connection.use(dbSettings.database); + connection.executeResource("CreateCDMIndices.sql"); + } +} diff --git a/src/org/ohdsi/whiteRabbit/cdm/CreateCDMIndices.sql b/src/org/ohdsi/whiteRabbit/cdm/CreateCDMIndices.sql new file mode 100644 index 00000000..3b608210 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/cdm/CreateCDMIndices.sql @@ -0,0 +1,61 @@ +CREATE INDEX INDEX_VISIT_OCCURRENCE_PLACE_OF_SERVICE_CONCEPT_ID ON VISIT_OCCURRENCE (PLACE_OF_SERVICE_CONCEPT_ID ASC); +CREATE INDEX INDEX_VISIT_PLACE_OF_SERVICE_SOURCE_VALUE ON VISIT_OCCURRENCE (PLACE_OF_SERVICE_SOURCE_VALUE ASC); +CREATE INDEX INDEX_VISIT_VISIT_START_DATE ON VISIT_OCCURRENCE (VISIT_START_DATE ASC); +CREATE INDEX INDEX_VISIT_VISIT_END_DATE ON VISIT_OCCURRENCE (VISIT_END_DATE ASC); +CREATE INDEX INDEX_VISIT_OCCURRENCE_PERSON_ID ON VISIT_OCCURRENCE (PERSON_ID ASC); + +CREATE INDEX INDEX_COHORT_COHORT_CONCEPT_ID ON COHORT (COHORT_CONCEPT_ID ASC); +CREATE INDEX INDEX_COHORT_COHORT_START_DATE ON COHORT (COHORT_START_DATE ASC); +CREATE INDEX INDEX_COHORT_COHORT_END_DATE ON COHORT (COHORT_END_DATE ASC); +CREATE INDEX INDEX_COHORT_SUBJECT_ID ON COHORT (SUBJECT_ID ASC); + +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PROCEDURE_OCCURRENCE_ID ON PROCEDURE_OCCURRENCE (PROCEDURE_OCCURRENCE_ID ASC); +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PROCEDURE_TYPE_CONCEPT_ID ON PROCEDURE_OCCURRENCE (PROCEDURE_TYPE_CONCEPT_ID ASC); +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PROCEDURE_SOURCE_VALUE ON PROCEDURE_OCCURRENCE (PROCEDURE_SOURCE_VALUE ASC); +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PROCEDURE_DATE ON PROCEDURE_OCCURRENCE (PROCEDURE_DATE ASC); +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PERSON_ID ON PROCEDURE_OCCURRENCE (PERSON_ID ASC); + +CREATE INDEX INDEX_PROCEDURE_COST_PROCEDURE_OCCURRENCE_ID ON PROCEDURE_COST (PROCEDURE_OCCURRENCE_ID ASC); +CREATE INDEX INDEX_PROCEDURE_COST_DISEASE_CLASS_CONCEPT_ID ON PROCEDURE_COST (DISEASE_CLASS_CONCEPT_ID ASC); +CREATE INDEX INDEX_PROCEDURE_COST_DISEASE_CLASS_SOURCE_VALUE ON PROCEDURE_COST (DISEASE_CLASS_SOURCE_VALUE ASC); + +CREATE INDEX INDEX_PROVIDER_PROVIDER_ID ON PROVIDER (PROVIDER_ID ASC); +CREATE INDEX INDEX_PROVIDER_SPECIALTY_CONCEPT_ID ON PROVIDER (SPECIALTY_CONCEPT_ID ASC); +CREATE INDEX INDEX_PROVIDER_SPECIALTY_SOURCE_VALUE ON PROVIDER (SPECIALTY_SOURCE_VALUE ASC); + +CREATE INDEX INDEX_PERSON_PERSON_ID ON PERSON (PERSON_ID ASC); + +CREATE INDEX INDEX_OBSERVATION_OBSERVATION_PERIOD_START_DATE ON OBSERVATION_PERIOD (OBSERVATION_PERIOD_START_DATE ASC); +CREATE INDEX INDEX_OBSERVATION_OBSERVATION_PERIOD_END_DATE ON OBSERVATION_PERIOD (OBSERVATION_PERIOD_END_DATE ASC); +CREATE INDEX INDEX_OBSERVATION_PERIOD_PERSON_ID ON OBSERVATION_PERIOD (PERSON_ID ASC); + +CREATE INDEX INDEX_OBSERVATION_OBSERVATION_CONCEPT_ID ON OBSERVATION (OBSERVATION_CONCEPT_ID ASC); +CREATE INDEX INDEX_OBSERVATION_OBSERVATION_DATE ON OBSERVATION (OBSERVATION_DATE ASC); +CREATE INDEX INDEX_OBSERVATION_PERSON_ID ON OBSERVATION (PERSON_ID ASC); + +CREATE INDEX INDEX_DRUG_ERA_DRUG_CONCEPT_ID ON DRUG_ERA (DRUG_CONCEPT_ID ASC); +CREATE INDEX INDEX_DRUG_ERA_DRUG_ERA_START_DATE ON DRUG_ERA (DRUG_ERA_START_DATE ASC); +CREATE INDEX INDEX_DRUG_ERA_DRUG_ERA_END_DATE ON DRUG_ERA (DRUG_ERA_END_DATE ASC); +CREATE INDEX INDEX_DRUG_ERA_PERSON_ID ON DRUG_ERA (PERSON_ID ASC); + +CREATE INDEX INDEX_DRUG_EXPOSURE_DRUG_CONCEPT_ID ON DRUG_EXPOSURE (DRUG_CONCEPT_ID ASC); +CREATE INDEX INDEX_DRUG_EXPOSURE_DRUG_SOURCE_VALUE ON DRUG_EXPOSURE (DRUG_SOURCE_VALUE ASC); +CREATE INDEX INDEX_DRUG_EXPOSURE_DRUG_EXPOSURE_START_DATE ON DRUG_EXPOSURE (DRUG_EXPOSURE_START_DATE ASC); +CREATE INDEX INDEX_DRUG_EXPOSURE_DRUG_EXPOSURE_END_DATE ON DRUG_EXPOSURE (DRUG_EXPOSURE_END_DATE ASC); +CREATE INDEX INDEX_DRUG_EXPOSURE_PERSON_ID ON DRUG_EXPOSURE (PERSON_ID ASC); + +CREATE INDEX INDEX_DEATH_DEATH_DATE ON DEATH (DEATH_DATE ASC); +CREATE INDEX INDEX_DEATH_PERSON_ID ON DEATH (PERSON_ID ASC); + +CREATE INDEX INDEX_CONDITION_ERA_CONDITION_CONCEPT_ID ON CONDITION_ERA (CONDITION_CONCEPT_ID ASC); +CREATE INDEX INDEX_CONDITION_ERA_CONDITION_ERA_START_DATE ON CONDITION_ERA (CONDITION_ERA_START_DATE ASC); +CREATE INDEX INDEX_CONDITION_ERA_CONDITION_ERA_END_DATE ON CONDITION_ERA (CONDITION_ERA_END_DATE ASC); +CREATE INDEX INDEX_CONDITION_ERA_PERSON_ID ON CONDITION_ERA (PERSON_ID ASC); + +CREATE INDEX INDEX_CONDITION_OCCURRENCE_CONDITION_CONCEPT_ID ON CONDITION_OCCURRENCE (CONDITION_CONCEPT_ID ASC); +CREATE INDEX INDEX_CONDITION_OCCURRENCE_CONDITION_SOURCE_VALUE ON CONDITION_OCCURRENCE (CONDITION_SOURCE_VALUE ASC); +CREATE INDEX INDEX_CONDITION_OCCURRENCE_CONDITION_START_DATE ON CONDITION_OCCURRENCE (CONDITION_START_DATE ASC); +CREATE INDEX INDEX_CONDITION_OCCURRENCE_CONDITION_END_DATE ON CONDITION_OCCURRENCE (CONDITION_END_DATE ASC); +CREATE INDEX INDEX_CONDITION_OCCURRENCE_PERSON_ID ON CONDITION_OCCURRENCE (PERSON_ID ASC); + + diff --git a/src/org/ohdsi/whiteRabbit/cdm/CreateCDMIndicesSQLServer.sql b/src/org/ohdsi/whiteRabbit/cdm/CreateCDMIndicesSQLServer.sql new file mode 100644 index 00000000..3b608210 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/cdm/CreateCDMIndicesSQLServer.sql @@ -0,0 +1,61 @@ +CREATE INDEX INDEX_VISIT_OCCURRENCE_PLACE_OF_SERVICE_CONCEPT_ID ON VISIT_OCCURRENCE (PLACE_OF_SERVICE_CONCEPT_ID ASC); +CREATE INDEX INDEX_VISIT_PLACE_OF_SERVICE_SOURCE_VALUE ON VISIT_OCCURRENCE (PLACE_OF_SERVICE_SOURCE_VALUE ASC); +CREATE INDEX INDEX_VISIT_VISIT_START_DATE ON VISIT_OCCURRENCE (VISIT_START_DATE ASC); +CREATE INDEX INDEX_VISIT_VISIT_END_DATE ON VISIT_OCCURRENCE (VISIT_END_DATE ASC); +CREATE INDEX INDEX_VISIT_OCCURRENCE_PERSON_ID ON VISIT_OCCURRENCE (PERSON_ID ASC); + +CREATE INDEX INDEX_COHORT_COHORT_CONCEPT_ID ON COHORT (COHORT_CONCEPT_ID ASC); +CREATE INDEX INDEX_COHORT_COHORT_START_DATE ON COHORT (COHORT_START_DATE ASC); +CREATE INDEX INDEX_COHORT_COHORT_END_DATE ON COHORT (COHORT_END_DATE ASC); +CREATE INDEX INDEX_COHORT_SUBJECT_ID ON COHORT (SUBJECT_ID ASC); + +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PROCEDURE_OCCURRENCE_ID ON PROCEDURE_OCCURRENCE (PROCEDURE_OCCURRENCE_ID ASC); +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PROCEDURE_TYPE_CONCEPT_ID ON PROCEDURE_OCCURRENCE (PROCEDURE_TYPE_CONCEPT_ID ASC); +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PROCEDURE_SOURCE_VALUE ON PROCEDURE_OCCURRENCE (PROCEDURE_SOURCE_VALUE ASC); +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PROCEDURE_DATE ON PROCEDURE_OCCURRENCE (PROCEDURE_DATE ASC); +CREATE INDEX INDEX_PROCEDURE_OCCURRENCE_PERSON_ID ON PROCEDURE_OCCURRENCE (PERSON_ID ASC); + +CREATE INDEX INDEX_PROCEDURE_COST_PROCEDURE_OCCURRENCE_ID ON PROCEDURE_COST (PROCEDURE_OCCURRENCE_ID ASC); +CREATE INDEX INDEX_PROCEDURE_COST_DISEASE_CLASS_CONCEPT_ID ON PROCEDURE_COST (DISEASE_CLASS_CONCEPT_ID ASC); +CREATE INDEX INDEX_PROCEDURE_COST_DISEASE_CLASS_SOURCE_VALUE ON PROCEDURE_COST (DISEASE_CLASS_SOURCE_VALUE ASC); + +CREATE INDEX INDEX_PROVIDER_PROVIDER_ID ON PROVIDER (PROVIDER_ID ASC); +CREATE INDEX INDEX_PROVIDER_SPECIALTY_CONCEPT_ID ON PROVIDER (SPECIALTY_CONCEPT_ID ASC); +CREATE INDEX INDEX_PROVIDER_SPECIALTY_SOURCE_VALUE ON PROVIDER (SPECIALTY_SOURCE_VALUE ASC); + +CREATE INDEX INDEX_PERSON_PERSON_ID ON PERSON (PERSON_ID ASC); + +CREATE INDEX INDEX_OBSERVATION_OBSERVATION_PERIOD_START_DATE ON OBSERVATION_PERIOD (OBSERVATION_PERIOD_START_DATE ASC); +CREATE INDEX INDEX_OBSERVATION_OBSERVATION_PERIOD_END_DATE ON OBSERVATION_PERIOD (OBSERVATION_PERIOD_END_DATE ASC); +CREATE INDEX INDEX_OBSERVATION_PERIOD_PERSON_ID ON OBSERVATION_PERIOD (PERSON_ID ASC); + +CREATE INDEX INDEX_OBSERVATION_OBSERVATION_CONCEPT_ID ON OBSERVATION (OBSERVATION_CONCEPT_ID ASC); +CREATE INDEX INDEX_OBSERVATION_OBSERVATION_DATE ON OBSERVATION (OBSERVATION_DATE ASC); +CREATE INDEX INDEX_OBSERVATION_PERSON_ID ON OBSERVATION (PERSON_ID ASC); + +CREATE INDEX INDEX_DRUG_ERA_DRUG_CONCEPT_ID ON DRUG_ERA (DRUG_CONCEPT_ID ASC); +CREATE INDEX INDEX_DRUG_ERA_DRUG_ERA_START_DATE ON DRUG_ERA (DRUG_ERA_START_DATE ASC); +CREATE INDEX INDEX_DRUG_ERA_DRUG_ERA_END_DATE ON DRUG_ERA (DRUG_ERA_END_DATE ASC); +CREATE INDEX INDEX_DRUG_ERA_PERSON_ID ON DRUG_ERA (PERSON_ID ASC); + +CREATE INDEX INDEX_DRUG_EXPOSURE_DRUG_CONCEPT_ID ON DRUG_EXPOSURE (DRUG_CONCEPT_ID ASC); +CREATE INDEX INDEX_DRUG_EXPOSURE_DRUG_SOURCE_VALUE ON DRUG_EXPOSURE (DRUG_SOURCE_VALUE ASC); +CREATE INDEX INDEX_DRUG_EXPOSURE_DRUG_EXPOSURE_START_DATE ON DRUG_EXPOSURE (DRUG_EXPOSURE_START_DATE ASC); +CREATE INDEX INDEX_DRUG_EXPOSURE_DRUG_EXPOSURE_END_DATE ON DRUG_EXPOSURE (DRUG_EXPOSURE_END_DATE ASC); +CREATE INDEX INDEX_DRUG_EXPOSURE_PERSON_ID ON DRUG_EXPOSURE (PERSON_ID ASC); + +CREATE INDEX INDEX_DEATH_DEATH_DATE ON DEATH (DEATH_DATE ASC); +CREATE INDEX INDEX_DEATH_PERSON_ID ON DEATH (PERSON_ID ASC); + +CREATE INDEX INDEX_CONDITION_ERA_CONDITION_CONCEPT_ID ON CONDITION_ERA (CONDITION_CONCEPT_ID ASC); +CREATE INDEX INDEX_CONDITION_ERA_CONDITION_ERA_START_DATE ON CONDITION_ERA (CONDITION_ERA_START_DATE ASC); +CREATE INDEX INDEX_CONDITION_ERA_CONDITION_ERA_END_DATE ON CONDITION_ERA (CONDITION_ERA_END_DATE ASC); +CREATE INDEX INDEX_CONDITION_ERA_PERSON_ID ON CONDITION_ERA (PERSON_ID ASC); + +CREATE INDEX INDEX_CONDITION_OCCURRENCE_CONDITION_CONCEPT_ID ON CONDITION_OCCURRENCE (CONDITION_CONCEPT_ID ASC); +CREATE INDEX INDEX_CONDITION_OCCURRENCE_CONDITION_SOURCE_VALUE ON CONDITION_OCCURRENCE (CONDITION_SOURCE_VALUE ASC); +CREATE INDEX INDEX_CONDITION_OCCURRENCE_CONDITION_START_DATE ON CONDITION_OCCURRENCE (CONDITION_START_DATE ASC); +CREATE INDEX INDEX_CONDITION_OCCURRENCE_CONDITION_END_DATE ON CONDITION_OCCURRENCE (CONDITION_END_DATE ASC); +CREATE INDEX INDEX_CONDITION_OCCURRENCE_PERSON_ID ON CONDITION_OCCURRENCE (PERSON_ID ASC); + + diff --git a/src/org/ohdsi/whiteRabbit/cdm/CreateCDMStructureMySQL.sql b/src/org/ohdsi/whiteRabbit/cdm/CreateCDMStructureMySQL.sql new file mode 100644 index 00000000..f83c64b2 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/cdm/CreateCDMStructureMySQL.sql @@ -0,0 +1,214 @@ +CREATE TABLE IF NOT EXISTS `CARE_SITE` ( + `CARE_SITE_ID` INT NOT NULL, + `LOCATION_ID` INT NULL, + `ORGANIZATION_ID` INT NULL, + `PLACE_OF_SERVICE_CONCEPT_ID` INT NULL, + `CARE_SITE_SOURCE_VALUE` VARCHAR(50) NULL, + `PLACE_OF_SERVICE_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `COHORT` ( + `COHORT_ID` INT AUTO_INCREMENT PRIMARY KEY, + `COHORT_CONCEPT_ID` INT NOT NULL, + `COHORT_START_DATE` DATE NOT NULL, + `COHORT_END_DATE` DATE NULL, + `SUBJECT_ID` BIGINT NOT NULL, + `STOP_REASON` VARCHAR(20) NULL +); + +CREATE TABLE IF NOT EXISTS `CONDITION_ERA` ( + `CONDITION_ERA_ID` BIGINT NOT NULL, + `PERSON_ID` BIGINT NOT NULL, + `CONDITION_CONCEPT_ID` INT NOT NULL, + `CONDITION_ERA_START_DATE` DATE NOT NULL, + `CONDITION_ERA_END_DATE` DATE NOT NULL, + `CONDITION_TYPE_CONCEPT_ID` INT NOT NULL, + `CONDITION_OCCURRENCE_COUNT` INT NULL +); + +CREATE TABLE IF NOT EXISTS `CONDITION_OCCURRENCE` ( + `CONDITION_OCCURRENCE_ID` BIGINT NOT NULL, + `PERSON_ID` BIGINT NOT NULL, + `CONDITION_CONCEPT_ID` INT NOT NULL, + `CONDITION_START_DATE` DATE NOT NULL, + `CONDITION_END_DATE` DATE NULL, + `CONDITION_TYPE_CONCEPT_ID` INT NOT NULL, + `STOP_REASON` VARCHAR(20) NULL, + `ASSOCIATED_PROVIDER_ID` INT NULL, + `VISIT_OCCURRENCE_ID` BIGINT NULL, + `CONDITION_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `DEATH` ( + `PERSON_ID` BIGINT NOT NULL, + `DEATH_DATE` DATE NOT NULL, + `DEATH_TYPE_CONCEPT_ID` INT NOT NULL, + `CAUSE_OF_DEATH_CONCEPT_ID` INT NULL, + `CAUSE_OF_DEATH_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `DRUG_COST` ( + `DRUG_COST_ID` BIGINT NOT NULL, + `DRUG_EXPOSURE_ID` BIGINT NOT NULL, + `PAID_COPAY` NUMERIC NULL, + `PAID_COINSURANCE` NUMERIC NULL, + `PAID_TOWARD_DEDUCTIBLE` NUMERIC NULL, + `PAID_BY_PAYER` NUMERIC NULL, + `PAID_BY_COORDINATION_BENEFITS` NUMERIC NULL, + `TOTAL_OUT_OF_POCKET` NUMERIC NULL, + `TOTAL_PAID` NUMERIC NULL, + `INGREDIENT_COST` NUMERIC NULL, + `DISPENSING_FEE` NUMERIC NULL, + `AVERAGE_WHOLESALE_PRICE` NUMERIC NULL, + `PAYER_PLAN_PERIOD_ID` INT NULL +); + +CREATE TABLE IF NOT EXISTS `DRUG_ERA` ( + `DRUG_ERA_ID` BIGINT NOT NULL, + `PERSON_ID` BIGINT NOT NULL, + `DRUG_ERA_START_DATE` DATE NOT NULL, + `DRUG_ERA_END_DATE` DATE NOT NULL, + `DRUG_TYPE_CONCEPT_ID` INT NOT NULL, + `DRUG_CONCEPT_ID` INT NULL, + `DRUG_EXPOSURE_COUNT` INT NOT NULL +); + +CREATE TABLE IF NOT EXISTS `DRUG_EXPOSURE` ( + `DRUG_EXPOSURE_ID` BIGINT NOT NULL, + `PERSON_ID` BIGINT NOT NULL, + `DRUG_CONCEPT_ID` INT NOT NULL, + `DRUG_EXPOSURE_START_DATE` DATE NOT NULL, + `DRUG_EXPOSURE_END_DATE` DATE NULL, + `DRUG_TYPE_CONCEPT_ID` INT NOT NULL, + `STOP_REASON` VARCHAR(20) NULL, + `REFILLS` INT NULL, + `QUANTITY` INT NULL, + `DAYS_SUPPLY` INT NULL, + `SIG` VARCHAR(500) NULL, + `PRESCRIBING_PROVIDER_ID` INT NULL, + `VISIT_OCCURRENCE_ID` BIGINT NULL, + `RELEVANT_CONDITION_CONCEPT_ID` INT NULL, + `DRUG_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `LOCATION` ( + `LOCATION_ID` INT NOT NULL, + `ADDRESS_1` VARCHAR(50) NULL, + `ADDRESS_2` VARCHAR(50) NULL, + `CITY` VARCHAR(50) NULL, + `STATE` CHAR(2) NULL, + `ZIP` VARCHAR(9) NULL, + `COUNTY` VARCHAR(20) NULL, + `LOCATION_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `OBSERVATION` ( + `OBSERVATION_ID` BIGINT NOT NULL, + `PERSON_ID` BIGINT NOT NULL, + `OBSERVATION_CONCEPT_ID` BIGINT NOT NULL, + `OBSERVATION_TYPE_CONCEPT_ID` INT NOT NULL, + `OBSERVATION_DATE` DATE NOT NULL, + `OBSERVATION_TIME` TIME NULL, + `VALUE_AS_NUMBER` NUMERIC NULL, + `VALUE_AS_STRING` VARCHAR(256) NULL, + `VALUE_AS_CONCEPT_ID` INT NULL, + `UNIT_CONCEPT_ID` BIGINT NULL, + `RANGE_LOW` FLOAT NULL, + `RANGE_HIGH` FLOAT NULL, + `ASSOCIATED_PROVIDER_ID` INT NULL, + `VISIT_OCCURRENCE_ID` BIGINT NULL, + `OBSERVATION_SOURCE_VALUE` VARCHAR(256) NULL, + `UNIT_SOURCE_VALUE` VARCHAR(256) NULL, + `RELEVANT_CONDITION_CONCEPT_ID` INT NULL +); + +CREATE TABLE IF NOT EXISTS `OBSERVATION_PERIOD` ( + `OBSERVATION_PERIOD_ID` BIGINT NOT NULL, + `PERSON_ID` BIGINT NOT NULL, + `OBSERVATION_PERIOD_START_DATE` DATE NOT NULL, + `OBSERVATION_PERIOD_END_DATE` DATE NOT NULL +); + +CREATE TABLE IF NOT EXISTS `ORGANIZATION` ( + `ORGANIZATION_ID` INT NOT NULL, + `PLACE_OF_SERVICE_CONCEPT_ID` INT NULL, + `LOCATION_ID` INT NULL, + `ORGANIZATION_SOURCE_VALUE` VARCHAR(50) NULL, + `PLACE_OF_SERVICE_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `PAYER_PLAN_PERIOD` ( + `PAYER_PLAN_PERIOD_ID` BIGINT NOT NULL, + `PERSON_ID` BIGINT NOT NULL, + `PAYER_PLAN_PERIOD_START_DATE` DATE NOT NULL, + `PAYER_PLAN_PERIOD_END_DATE` DATE NOT NULL, + `PAYER_SOURCE_VALUE` VARCHAR(50) NULL, + `PLAN_SOURCE_VALUE` VARCHAR(50) NULL, + `FAMILY_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `PERSON` ( + `PERSON_ID` BIGINT NOT NULL, + `GENDER_CONCEPT_ID` INT NOT NULL, + `YEAR_OF_BIRTH` INT NOT NULL, + `MONTH_OF_BIRTH` INT NULL, + `DAY_OF_BIRTH` INT NULL, + `RACE_CONCEPT_ID` INT NULL, + `ETHNICITY_CONCEPT_ID` INT NULL, + `LOCATION_ID` INT NULL, + `PROVIDER_ID` INT NULL, + `CARE_SITE_ID` INT NULL, + `PERSON_SOURCE_VALUE` VARCHAR(50) NULL, + `GENDER_SOURCE_VALUE` VARCHAR(50) NULL, + `RACE_SOURCE_VALUE` VARCHAR(50) NULL, + `ETHNICITY_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `PROCEDURE_COST` ( + `PROCEDURE_COST_ID` BIGINT NOT NULL, + `PROCEDURE_OCCURRENCE_ID` BIGINT NOT NULL, + `PAID_COPAY` NUMERIC NULL, + `PAID_COINSURANCE` NUMERIC NULL, + `PAID_TOWARD_DEDUCTIBLE` NUMERIC NULL, + `PAID_BY_PAYER` NUMERIC NULL, + `PAID_BY_COORDINATION_BENEFITS` NUMERIC NULL, + `TOTAL_OUT_OF_POCKET` NUMERIC NULL, + `TOTAL_PAID` NUMERIC NULL, + `DISEASE_CLASS_CONCEPT_ID` INT NULL, + `REVENUE_CODE_CONCEPT_ID` INT NULL, + `PAYER_PLAN_PERIOD_ID` BIGINT NULL, + `DISEASE_CLASS_SOURCE_VALUE` VARCHAR(50) NULL, + `REVENUE_CODE_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `PROCEDURE_OCCURRENCE` ( + `PROCEDURE_OCCURRENCE_ID` BIGINT NOT NULL, + `PERSON_ID` BIGINT NOT NULL, + `PROCEDURE_TYPE_CONCEPT_ID` INT NOT NULL, + `PROCEDURE_DATE` DATE NOT NULL, + `PROCEDURE_CONCEPT_ID` BIGINT NOT NULL, + `ASSOCIATED_PROVIDER_ID` INT NULL, + `PROCEDURE_SOURCE_VALUE` VARCHAR(50) NULL, + `VISIT_OCCURRENCE_ID` BIGINT NULL, + `RELEVANT_CONDITION_CONCEPT_ID` INT NULL +); + +CREATE TABLE IF NOT EXISTS `PROVIDER` ( + `PROVIDER_ID` BIGINT NOT NULL, + `NPI` VARCHAR(20) NULL, + `DEA` VARCHAR(20) NULL, + `SPECIALTY_CONCEPT_ID` INT NULL, + `CARE_SITE_ID` INT NULL, + `PROVIDER_SOURCE_VALUE` VARCHAR(50) NULL, + `SPECIALTY_SOURCE_VALUE` VARCHAR(50) NULL +); + +CREATE TABLE IF NOT EXISTS `VISIT_OCCURRENCE` ( + `VISIT_OCCURRENCE_ID` BIGINT NOT NULL, + `PERSON_ID` BIGINT NOT NULL, + `PLACE_OF_SERVICE_CONCEPT_ID` INT NOT NULL, + `VISIT_START_DATE` DATE NOT NULL, + `VISIT_END_DATE` DATE NOT NULL, + `PLACE_OF_SERVICE_SOURCE_VALUE` VARCHAR(50) NULL, + `CARE_SITE_ID` INT NULL +); diff --git a/src/org/ohdsi/whiteRabbit/cdm/CreateCDMStructureSQLServer.sql b/src/org/ohdsi/whiteRabbit/cdm/CreateCDMStructureSQLServer.sql new file mode 100644 index 00000000..c975938c --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/cdm/CreateCDMStructureSQLServer.sql @@ -0,0 +1,272 @@ + +CREATE TABLE "CARE_SITE" ( + "CARE_SITE_ID" INT NOT NULL, + "LOCATION_ID" INT NULL, + "ORGANIZATION_ID" INT NULL, + "PLACE_OF_SERVICE_CONCEPT_ID" INT NULL, + "CARE_SITE_SOURCE_VALUE" VARCHAR(50) NULL, + "PLACE_OF_SERVICE_SOURCE_VALUE" VARCHAR(50) NULL, + PRIMARY KEY ("CARE_SITE_ID") +); + +CREATE TABLE "COHORT" ( + "COHORT_ID" INT NOT NULL, + "COHORT_CONCEPT_ID" INT NOT NULL, + "COHORT_START_DATE" DATE NOT NULL, + "COHORT_END_DATE" DATE NULL, + "SUBJECT_ID" BIGINT NOT NULL, + "STOP_REASON" VARCHAR(20) NULL +); + +CREATE TABLE "CONCEPT" ( + "CONCEPT_ID" INT NOT NULL, + "CONCEPT_NAME" VARCHAR(256) NOT NULL, + "CONCEPT_LEVEL" INT NULL, + "CONCEPT_CLASS" VARCHAR(60) NOT NULL, + "VOCABULARY_ID" INT NOT NULL, + "CONCEPT_CODE" VARCHAR(40) NOT NULL, + "VALID_START_DATE" DATE NOT NULL, + "VALID_END_DATE" DATE NOT NULL, + "INVALID_REASON" CHAR(1) NULL, + PRIMARY KEY ("CONCEPT_ID") +); + +CREATE TABLE "CONCEPT_ANCESTOR" ( + "ANCESTOR_CONCEPT_ID" INT NOT NULL, + "DESCENDANT_CONCEPT_ID" INT NOT NULL, + "MIN_LEVELS_OF_SEPARATION" INT NULL, + "MAX_LEVELS_OF_SEPARATION" INT NULL, + PRIMARY KEY ("ANCESTOR_CONCEPT_ID","DESCENDANT_CONCEPT_ID") +); + +CREATE TABLE "CONCEPT_RELATIONSHIP" ( + "CONCEPT_ID_1" INT NOT NULL, + "CONCEPT_ID_2" INT NOT NULL, + "RELATIONSHIP_ID" INT NOT NULL, + "VALID_START_DATE" DATE NOT NULL, + "VALID_END_DATE" DATE NOT NULL, + "INVALID_REASON" CHAR(1) NULL, + PRIMARY KEY ("CONCEPT_ID_1","CONCEPT_ID_2","RELATIONSHIP_ID") +); + +CREATE TABLE "CONCEPT_SYNONYM" ( + "CONCEPT_SYNONYM_ID" INT NOT NULL, + "CONCEPT_ID" INT NOT NULL, + "CONCEPT_SYNONYM_NAME" VARCHAR(1000) NOT NULL, + PRIMARY KEY ("CONCEPT_SYNONYM_ID") +); + +CREATE TABLE "CONDITION_ERA" ( + "CONDITION_ERA_ID" BIGINT NOT NULL, + "PERSON_ID" BIGINT NOT NULL, + "CONDITION_CONCEPT_ID" INT NOT NULL, + "CONDITION_ERA_START_DATE" DATE NOT NULL, + "CONDITION_ERA_END_DATE" DATE NOT NULL, + "CONDITION_TYPE_CONCEPT_ID" INT NOT NULL, + "CONDITION_OCCURRENCE_COUNT" INT NULL +); + +CREATE TABLE "CONDITION_OCCURRENCE" ( + "CONDITION_OCCURRENCE_ID" BIGINT NOT NULL, + "PERSON_ID" BIGINT NOT NULL, + "CONDITION_CONCEPT_ID" INT NOT NULL, + "CONDITION_START_DATE" DATE NOT NULL, + "CONDITION_END_DATE" DATE NULL, + "CONDITION_TYPE_CONCEPT_ID" INT NOT NULL, + "STOP_REASON" VARCHAR(20) NULL, + "ASSOCIATED_PROVIDER_ID" INT NULL, + "VISIT_OCCURRENCE_ID" BIGINT NULL, + "CONDITION_SOURCE_VALUE" VARCHAR(50) NULL +); + +-- Data exporting was unselected. + + +-- Dumping structure for table CDM_Truven_MDCR.DEATH +CREATE TABLE "DEATH" ( + "PERSON_ID" BIGINT NOT NULL, + "DEATH_DATE" DATE NOT NULL, + "DEATH_TYPE_CONCEPT_ID" INT NOT NULL, + "CAUSE_OF_DEATH_CONCEPT_ID" INT NULL, + "CAUSE_OF_DEATH_SOURCE_VALUE" VARCHAR(50) NULL +); + +CREATE TABLE "DRG_MAP" ( + "SOURCE_CODE" VARCHAR(40) NOT NULL, + "TARGET_CONCEPT_ID" INT NOT NULL, + "VALID_START_DATE" DATE NOT NULL, + "VALID_END_DATE" DATE NOT NULL +); + +CREATE TABLE "DRUG_COST" ( + "DRUG_COST_ID" BIGINT NOT NULL, + "DRUG_EXPOSURE_ID" BIGINT NOT NULL, + "PAID_COPAY" NUMERIC NULL, + "PAID_COINSURANCE" NUMERIC NULL, + "PAID_TOWARD_DEDUCTIBLE" NUMERIC NULL, + "PAID_BY_PAYER" NUMERIC NULL, + "PAID_BY_COORDINATION_BENEFITS" NUMERIC NULL, + "TOTAL_OUT_OF_POCKET" NUMERIC NULL, + "TOTAL_PAID" NUMERIC NULL, + "INGREDIENT_COST" NUMERIC NULL, + "DISPENSING_FEE" NUMERIC NULL, + "AVERAGE_WHOLESALE_PRICE" NUMERIC NULL, + "PAYER_PLAN_PERIOD_ID" INT NULL, + PRIMARY KEY ("DRUG_EXPOSURE_ID") +); + +CREATE TABLE "DRUG_ERA" ( + "DRUG_ERA_ID" BIGINT NOT NULL, + "PERSON_ID" BIGINT NOT NULL, + "DRUG_ERA_START_DATE" DATE NOT NULL, + "DRUG_ERA_END_DATE" DATE NOT NULL, + "DRUG_TYPE_CONCEPT_ID" INT NOT NULL, + "DRUG_CONCEPT_ID" INT NULL, + "DRUG_EXPOSURE_COUNT" INT NOT NULL +); + +CREATE TABLE "DRUG_EXPOSURE" ( + "DRUG_EXPOSURE_ID" BIGINT NOT NULL, + "PERSON_ID" BIGINT NOT NULL, + "DRUG_CONCEPT_ID" INT NOT NULL, + "DRUG_EXPOSURE_START_DATE" DATE NOT NULL, + "DRUG_EXPOSURE_END_DATE" DATE NULL, + "DRUG_TYPE_CONCEPT_ID" INT NOT NULL, + "STOP_REASON" VARCHAR(20) NULL, + "REFILLS" INT NULL, + "QUANTITY" INT NULL, + "DAYS_SUPPLY" INT NULL, + "SIG" VARCHAR(500) NULL, + "PRESCRIBING_PROVIDER_ID" INT NULL, + "VISIT_OCCURRENCE_ID" BIGINT NULL, + "RELEVANT_CONDITION_CONCEPT_ID" INT NULL, + "DRUG_SOURCE_VALUE" VARCHAR(50) NULL, + PRIMARY KEY ("DRUG_EXPOSURE_ID") +); + +CREATE TABLE "LOCATION" ( + "LOCATION_ID" INT NOT NULL, + "ADDRESS_1" VARCHAR(50) NULL, + "ADDRESS_2" VARCHAR(50) NULL, + "CITY" VARCHAR(50) NULL, + "STATE" CHAR(2) NULL, + "ZIP" VARCHAR(9) NULL, + "COUNTY" VARCHAR(20) NULL, + "LOCATION_SOURCE_VALUE" VARCHAR(50) NULL, + PRIMARY KEY ("LOCATION_ID") +); + +CREATE TABLE "OBSERVATION" ( + "OBSERVATION_ID" BIGINT NOT NULL, + "PERSON_ID" BIGINT NOT NULL, + "OBSERVATION_CONCEPT_ID" BIGINT NOT NULL, + "OBSERVATION_TYPE_CONCEPT_ID" INT NOT NULL, + "OBSERVATION_DATE" DATE NOT NULL, + "OBSERVATION_TIME" TIME NULL, + "VALUE_AS_NUMBER" NUMERIC NULL, + "VALUE_AS_STRING" VARCHAR(256) NULL, + "VALUE_AS_CONCEPT_ID" INT NULL, + "UNIT_CONCEPT_ID" BIGINT NULL, + "RANGE_LOW" FLOAT NULL, + "RANGE_HIGH" FLOAT NULL, + "ASSOCIATED_PROVIDER_ID" INT NULL, + "VISIT_OCCURRENCE_ID" BIGINT NULL, + "OBSERVATION_SOURCE_VALUE" VARCHAR(256) NULL, + "UNIT_SOURCE_VALUE" VARCHAR(256) NULL, + "RELEVANT_CONDITION_CONCEPT_ID" INT NULL +); + +CREATE TABLE "OBSERVATION_PERIOD" ( + "OBSERVATION_PERIOD_ID" BIGINT NOT NULL, + "PERSON_ID" BIGINT NOT NULL, + "OBSERVATION_PERIOD_START_DATE" DATE NOT NULL, + "OBSERVATION_PERIOD_END_DATE" DATE NOT NULL +); + + +CREATE TABLE "ORGANIZATION" ( + "ORGANIZATION_ID" INT NOT NULL, + "PLACE_OF_SERVICE_CONCEPT_ID" INT NULL, + "LOCATION_ID" INT NULL, + "ORGANIZATION_SOURCE_VALUE" VARCHAR(50) NULL, + "PLACE_OF_SERVICE_SOURCE_VALUE" VARCHAR(50) NULL, + PRIMARY KEY ("ORGANIZATION_ID") +); + +CREATE TABLE "PAYER_PLAN_PERIOD" ( + "PAYER_PLAN_PERIOD_ID" BIGINT NOT NULL, + "PERSON_ID" BIGINT NOT NULL, + "PAYER_PLAN_PERIOD_START_DATE" DATE NOT NULL, + "PAYER_PLAN_PERIOD_END_DATE" DATE NOT NULL, + "PAYER_SOURCE_VALUE" VARCHAR(50) NULL, + "PLAN_SOURCE_VALUE" VARCHAR(50) NULL, + "FAMILY_SOURCE_VALUE" VARCHAR(50) NULL +); + +CREATE TABLE "PERSON" ( + "PERSON_ID" BIGINT NOT NULL, + "GENDER_CONCEPT_ID" INT NOT NULL, + "YEAR_OF_BIRTH" INT NOT NULL, + "MONTH_OF_BIRTH" INT NULL, + "DAY_OF_BIRTH" INT NULL, + "RACE_CONCEPT_ID" INT NULL, + "ETHNICITY_CONCEPT_ID" INT NULL, + "LOCATION_ID" INT NULL, + "PROVIDER_ID" INT NULL, + "CARE_SITE_ID" INT NULL, + "PERSON_SOURCE_VALUE" VARCHAR(50) NULL, + "GENDER_SOURCE_VALUE" VARCHAR(50) NULL, + "RACE_SOURCE_VALUE" VARCHAR(50) NULL, + "ETHNICITY_SOURCE_VALUE" VARCHAR(50) NULL, + PRIMARY KEY ("PERSON_ID") +); + +CREATE TABLE "PROCEDURE_COST" ( + "PROCEDURE_COST_ID" BIGINT NOT NULL, + "PROCEDURE_OCCURRENCE_ID" BIGINT NOT NULL, + "PAID_COPAY" NUMERIC NULL, + "PAID_COINSURANCE" NUMERIC NULL, + "PAID_TOWARD_DEDUCTIBLE" NUMERIC NULL, + "PAID_BY_PAYER" NUMERIC NULL, + "PAID_BY_COORDINATION_BENEFITS" NUMERIC NULL, + "TOTAL_OUT_OF_POCKET" NUMERIC NULL, + "TOTAL_PAID" NUMERIC NULL, + "DISEASE_CLASS_CONCEPT_ID" INT NULL, + "REVENUE_CODE_CONCEPT_ID" INT NULL, + "PAYER_PLAN_PERIOD_ID" BIGINT NULL, + "DISEASE_CLASS_SOURCE_VALUE" VARCHAR(50) NULL, + "REVENUE_CODE_SOURCE_VALUE" VARCHAR(50) NULL +); + +CREATE TABLE "PROCEDURE_OCCURRENCE" ( + "PROCEDURE_OCCURRENCE_ID" BIGINT NOT NULL, + "PERSON_ID" BIGINT NOT NULL, + "PROCEDURE_TYPE_CONCEPT_ID" INT NOT NULL, + "PROCEDURE_DATE" DATE NOT NULL, + "PROCEDURE_CONCEPT_ID" BIGINT NOT NULL, + "ASSOCIATED_PROVIDER_ID" INT NULL, + "PROCEDURE_SOURCE_VALUE" VARCHAR(50) NULL, + "VISIT_OCCURRENCE_ID" BIGINT NULL, + "RELEVANT_CONDITION_CONCEPT_ID" INT NULL, + PRIMARY KEY ("PROCEDURE_OCCURRENCE_ID") +); + +CREATE TABLE "PROVIDER" ( + "PROVIDER_ID" BIGINT NOT NULL, + "NPI" VARCHAR(20) NULL, + "DEA" VARCHAR(20) NULL, + "SPECIALTY_CONCEPT_ID" INT NULL, + "CARE_SITE_ID" INT NULL, + "PROVIDER_SOURCE_VALUE" VARCHAR(50) NULL, + "SPECIALTY_SOURCE_VALUE" VARCHAR(50) NULL, + PRIMARY KEY ("PROVIDER_ID") +); +CREATE TABLE "VISIT_OCCURRENCE" ( + "VISIT_OCCURRENCE_ID" BIGINT NOT NULL, + "PERSON_ID" BIGINT NOT NULL, + "PLACE_OF_SERVICE_CONCEPT_ID" INT NOT NULL, + "VISIT_START_DATE" DATE NOT NULL, + "VISIT_END_DATE" DATE NOT NULL, + "PLACE_OF_SERVICE_SOURCE_VALUE" VARCHAR(50) NULL, + "CARE_SITE_ID" INT NULL +); diff --git a/src/org/ohdsi/whiteRabbit/cdm/FetchNullableFromServer.java b/src/org/ohdsi/whiteRabbit/cdm/FetchNullableFromServer.java new file mode 100644 index 00000000..7b0b6a0c --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/cdm/FetchNullableFromServer.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.cdm; + +import org.ohdsi.databases.DbType; +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.utilities.files.WriteCSVFileWithHeader; + +public class FetchNullableFromServer { + + public static void main(String[] args) { + RichConnection connection = new RichConnection("127.0.0.1", null, "root", "F1r3starter", DbType.MYSQL); + connection.use("cdm_v4"); + + WriteCSVFileWithHeader out = new WriteCSVFileWithHeader("c:/temp/NotNullableV4.csv"); + String query = "SELECT table_name,column_name,is_nullable FROM information_schema.columns WHERE table_schema = 'cdm_v4';"; + for (Row row : connection.query(query)) + out.write(row); + out.close(); + + } + +} diff --git a/src/org/ohdsi/whiteRabbit/cdm/NotNullableV4.csv b/src/org/ohdsi/whiteRabbit/cdm/NotNullableV4.csv new file mode 100644 index 00000000..03b87b17 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/cdm/NotNullableV4.csv @@ -0,0 +1,162 @@ +TABLE_NAME,COLUMN_NAME,IS_NULLABLE +care_site,CARE_SITE_ID,NO +care_site,LOCATION_ID,YES +care_site,ORGANIZATION_ID,YES +care_site,PLACE_OF_SERVICE_CONCEPT_ID,YES +care_site,CARE_SITE_SOURCE_VALUE,YES +care_site,PLACE_OF_SERVICE_SOURCE_VALUE,YES +cohort,COHORT_ID,NO +cohort,COHORT_CONCEPT_ID,NO +cohort,COHORT_START_DATE,NO +cohort,COHORT_END_DATE,YES +cohort,SUBJECT_ID,NO +cohort,STOP_REASON,YES +condition_era,CONDITION_ERA_ID,NO +condition_era,PERSON_ID,NO +condition_era,CONDITION_CONCEPT_ID,NO +condition_era,CONDITION_ERA_START_DATE,NO +condition_era,CONDITION_ERA_END_DATE,NO +condition_era,CONDITION_TYPE_CONCEPT_ID,NO +condition_era,CONDITION_OCCURRENCE_COUNT,YES +condition_occurrence,CONDITION_OCCURRENCE_ID,NO +condition_occurrence,PERSON_ID,NO +condition_occurrence,CONDITION_CONCEPT_ID,NO +condition_occurrence,CONDITION_START_DATE,NO +condition_occurrence,CONDITION_END_DATE,YES +condition_occurrence,CONDITION_TYPE_CONCEPT_ID,NO +condition_occurrence,STOP_REASON,YES +condition_occurrence,ASSOCIATED_PROVIDER_ID,YES +condition_occurrence,VISIT_OCCURRENCE_ID,YES +condition_occurrence,CONDITION_SOURCE_VALUE,YES +death,PERSON_ID,NO +death,DEATH_DATE,NO +death,DEATH_TYPE_CONCEPT_ID,NO +death,CAUSE_OF_DEATH_CONCEPT_ID,YES +death,CAUSE_OF_DEATH_SOURCE_VALUE,YES +drug_cost,DRUG_COST_ID,NO +drug_cost,DRUG_EXPOSURE_ID,NO +drug_cost,PAID_COPAY,YES +drug_cost,PAID_COINSURANCE,YES +drug_cost,PAID_TOWARD_DEDUCTIBLE,YES +drug_cost,PAID_BY_PAYER,YES +drug_cost,PAID_BY_COORDINATION_BENEFITS,YES +drug_cost,TOTAL_OUT_OF_POCKET,YES +drug_cost,TOTAL_PAID,YES +drug_cost,INGREDIENT_COST,YES +drug_cost,DISPENSING_FEE,YES +drug_cost,AVERAGE_WHOLESALE_PRICE,YES +drug_cost,PAYER_PLAN_PERIOD_ID,YES +drug_era,DRUG_ERA_ID,NO +drug_era,PERSON_ID,NO +drug_era,DRUG_ERA_START_DATE,NO +drug_era,DRUG_ERA_END_DATE,NO +drug_era,DRUG_TYPE_CONCEPT_ID,NO +drug_era,DRUG_CONCEPT_ID,YES +drug_era,DRUG_EXPOSURE_COUNT,NO +drug_exposure,DRUG_EXPOSURE_ID,NO +drug_exposure,PERSON_ID,NO +drug_exposure,DRUG_CONCEPT_ID,NO +drug_exposure,DRUG_EXPOSURE_START_DATE,NO +drug_exposure,DRUG_EXPOSURE_END_DATE,YES +drug_exposure,DRUG_TYPE_CONCEPT_ID,NO +drug_exposure,STOP_REASON,YES +drug_exposure,REFILLS,YES +drug_exposure,QUANTITY,YES +drug_exposure,DAYS_SUPPLY,YES +drug_exposure,SIG,YES +drug_exposure,PRESCRIBING_PROVIDER_ID,YES +drug_exposure,VISIT_OCCURRENCE_ID,YES +drug_exposure,RELEVANT_CONDITION_CONCEPT_ID,YES +drug_exposure,DRUG_SOURCE_VALUE,YES +location,LOCATION_ID,NO +location,ADDRESS_1,YES +location,ADDRESS_2,YES +location,CITY,YES +location,STATE,YES +location,ZIP,YES +location,COUNTY,YES +location,LOCATION_SOURCE_VALUE,YES +observation,OBSERVATION_ID,NO +observation,PERSON_ID,NO +observation,OBSERVATION_CONCEPT_ID,NO +observation,OBSERVATION_TYPE_CONCEPT_ID,NO +observation,OBSERVATION_DATE,NO +observation,OBSERVATION_TIME,YES +observation,VALUE_AS_NUMBER,YES +observation,VALUE_AS_STRING,YES +observation,VALUE_AS_CONCEPT_ID,YES +observation,UNIT_CONCEPT_ID,YES +observation,RANGE_LOW,YES +observation,RANGE_HIGH,YES +observation,ASSOCIATED_PROVIDER_ID,YES +observation,VISIT_OCCURRENCE_ID,YES +observation,OBSERVATION_SOURCE_VALUE,YES +observation,UNIT_SOURCE_VALUE,YES +observation,RELEVANT_CONDITION_CONCEPT_ID,YES +observation_period,OBSERVATION_PERIOD_ID,NO +observation_period,PERSON_ID,NO +observation_period,OBSERVATION_PERIOD_START_DATE,NO +observation_period,OBSERVATION_PERIOD_END_DATE,NO +organization,ORGANIZATION_ID,NO +organization,PLACE_OF_SERVICE_CONCEPT_ID,YES +organization,LOCATION_ID,YES +organization,ORGANIZATION_SOURCE_VALUE,YES +organization,PLACE_OF_SERVICE_SOURCE_VALUE,YES +payer_plan_period,PAYER_PLAN_PERIOD_ID,NO +payer_plan_period,PERSON_ID,NO +payer_plan_period,PAYER_PLAN_PERIOD_START_DATE,NO +payer_plan_period,PAYER_PLAN_PERIOD_END_DATE,NO +payer_plan_period,PAYER_SOURCE_VALUE,YES +payer_plan_period,PLAN_SOURCE_VALUE,YES +payer_plan_period,FAMILY_SOURCE_VALUE,YES +person,PERSON_ID,NO +person,GENDER_CONCEPT_ID,NO +person,YEAR_OF_BIRTH,NO +person,MONTH_OF_BIRTH,YES +person,DAY_OF_BIRTH,YES +person,RACE_CONCEPT_ID,YES +person,ETHNICITY_CONCEPT_ID,YES +person,LOCATION_ID,YES +person,PROVIDER_ID,YES +person,CARE_SITE_ID,YES +person,PERSON_SOURCE_VALUE,YES +person,GENDER_SOURCE_VALUE,YES +person,RACE_SOURCE_VALUE,YES +person,ETHNICITY_SOURCE_VALUE,YES +procedure_cost,PROCEDURE_COST_ID,NO +procedure_cost,PROCEDURE_OCCURRENCE_ID,NO +procedure_cost,PAID_COPAY,YES +procedure_cost,PAID_COINSURANCE,YES +procedure_cost,PAID_TOWARD_DEDUCTIBLE,YES +procedure_cost,PAID_BY_PAYER,YES +procedure_cost,PAID_BY_COORDINATION_BENEFITS,YES +procedure_cost,TOTAL_OUT_OF_POCKET,YES +procedure_cost,TOTAL_PAID,YES +procedure_cost,DISEASE_CLASS_CONCEPT_ID,YES +procedure_cost,REVENUE_CODE_CONCEPT_ID,YES +procedure_cost,PAYER_PLAN_PERIOD_ID,YES +procedure_cost,DISEASE_CLASS_SOURCE_VALUE,YES +procedure_cost,REVENUE_CODE_SOURCE_VALUE,YES +procedure_occurrence,PROCEDURE_OCCURRENCE_ID,NO +procedure_occurrence,PERSON_ID,NO +procedure_occurrence,PROCEDURE_TYPE_CONCEPT_ID,NO +procedure_occurrence,PROCEDURE_DATE,NO +procedure_occurrence,PROCEDURE_CONCEPT_ID,NO +procedure_occurrence,ASSOCIATED_PROVIDER_ID,YES +procedure_occurrence,PROCEDURE_SOURCE_VALUE,YES +procedure_occurrence,VISIT_OCCURRENCE_ID,YES +procedure_occurrence,RELEVANT_CONDITION_CONCEPT_ID,YES +provider,PROVIDER_ID,NO +provider,NPI,YES +provider,DEA,YES +provider,SPECIALTY_CONCEPT_ID,YES +provider,CARE_SITE_ID,YES +provider,PROVIDER_SOURCE_VALUE,YES +provider,SPECIALTY_SOURCE_VALUE,YES +visit_occurrence,VISIT_OCCURRENCE_ID,NO +visit_occurrence,PERSON_ID,NO +visit_occurrence,PLACE_OF_SERVICE_CONCEPT_ID,NO +visit_occurrence,VISIT_START_DATE,NO +visit_occurrence,VISIT_END_DATE,NO +visit_occurrence,PLACE_OF_SERVICE_SOURCE_VALUE,YES +visit_occurrence,CARE_SITE_ID,YES diff --git a/src/org/ohdsi/whiteRabbit/etls/ars/ARSETL.java b/src/org/ohdsi/whiteRabbit/etls/ars/ARSETL.java new file mode 100644 index 00000000..085a79ff --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/etls/ars/ARSETL.java @@ -0,0 +1,661 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.etls.ars; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.ohdsi.databases.RichConnection; +import org.ohdsi.ooxml.ReadXlsxFileWithHeader; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.collections.OneToManyList; +import org.ohdsi.utilities.files.FileSorter; +import org.ohdsi.utilities.files.MultiRowIterator; +import org.ohdsi.utilities.files.MultiRowIterator.MultiRowSet; +import org.ohdsi.utilities.files.ReadCSVFileWithHeader; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.utilities.files.RowUtilities; +import org.ohdsi.whiteRabbit.DbSettings; +import org.ohdsi.whiteRabbit.EtlReport; +import org.ohdsi.whiteRabbit.ObjectExchange; +import org.ohdsi.whiteRabbit.cdm.CDMV4NullableChecker; +import org.ohdsi.whiteRabbit.cdm.CdmV4; +import org.ohdsi.whiteRabbit.utilities.CSVFileChecker; +import org.ohdsi.whiteRabbit.utilities.CodeToConceptMap; +import org.ohdsi.whiteRabbit.utilities.ConditionEraGenerator; +import org.ohdsi.whiteRabbit.utilities.DrugEraGenerator; +import org.ohdsi.whiteRabbit.utilities.ETLUtils; +import org.ohdsi.whiteRabbit.utilities.QCSampleConstructor; + +public class ARSETL { + + public static String EXTRACTION_DATE = "2012-12-31"; + public static String MIN_OBSERVATION_DATE = "2003-01-01"; + public static int MAX_ROWS_PER_PERSON = 100000; + public static String[] TABLES = new String[] { "DDRUG", "DRUGS", "EXE", "HOSP", "OUTPAT", "PERSON" }; + public static int BATCH_SIZE = 100; + + private int personCount; + private String folder; + private RichConnection connection; + private long personId; + private long observationPeriodId; + private long drugExposureId; + private long conditionOccurrenceId; + private long visitOccurrenceId; + private long procedureOccurrenceId; + private long procedureCostId; + private long extractionDate; + private long minObservationDate; + private OneToManyList tableToRows; + private CodeToConceptMap atcToConcept; + private CodeToConceptMap atcToRxNormConcepts; + private Map procToType; + private CodeToConceptMap icd9ToConcept; + private CodeToConceptMap icd9ProcToConcept; + private CodeToConceptMap specialtyToConcept; + private Map hospRowToVisitOccurrenceId = new HashMap(); + private Map outpatRowToVisitOccurrenceId = new HashMap(); + private Map hospRowToProcedureOccurrenceId = new HashMap(); + private Set providerIds; + private QCSampleConstructor qcSampleConstructor; + private EtlReport etlReport; + private CDMV4NullableChecker cdmv4NullableChecker = new CDMV4NullableChecker(); + + public void process(String folder, DbSettings dbSettings, int maxPersons) { + this.folder = folder; + extractionDate = StringUtilities.databaseTimeStringToDays(EXTRACTION_DATE); + minObservationDate = StringUtilities.databaseTimeStringToDays(MIN_OBSERVATION_DATE); + System.out.println("Extraction date is set at " + EXTRACTION_DATE); + System.out.println("Minimum observation date is set at " + MIN_OBSERVATION_DATE); + + if (ETLUtils.databaseAlreadyExists(dbSettings)) + return; + // checkTablesForFormattingErrors(); + // sortTables(); + CdmV4.createStructure(dbSettings); + connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + connection.setContext(this.getClass()); + connection.use(dbSettings.database); + loadMappings(dbSettings); + + personCount = 0; + personId = 0; + observationPeriodId = 0; + drugExposureId = 0; + conditionOccurrenceId = 0; + visitOccurrenceId = 0; + procedureOccurrenceId = 0; + procedureCostId = 0; + providerIds = new HashSet(); + qcSampleConstructor = new QCSampleConstructor(folder + "/sample"); + tableToRows = new OneToManyList(); + etlReport = new EtlReport(folder); + + StringUtilities.outputWithTime("Processing persons"); + MultiRowIterator iterator = constructMultiRowIterator(); + while (iterator.hasNext()) { + processPerson(iterator.next()); + + if (personCount == maxPersons) { + System.out.println("Reached limit of " + maxPersons + " persons, terminating"); + break; + } + if (personCount % BATCH_SIZE == 0) { + insertBatch(); + System.out.println("Processed " + personCount + " persons"); + } + } + insertBatch(); + System.out.println("Processed " + personCount + " persons"); + CdmV4.createIndices(dbSettings); + qcSampleConstructor.addCdmData(dbSettings, dbSettings); + String etlReportName = etlReport.generate(atcToConcept, icd9ProcToConcept, icd9ToConcept, atcToRxNormConcepts, specialtyToConcept); + System.out.println("An ETL report was generated and written to :" + etlReportName); + if (etlReport.getTotalProblemCount() > 0) { + String etlProblemListname = etlReport.generateProblemList(); + System.out.println("An ETL problem list was generated and written to :" + etlProblemListname); + } + StringUtilities.outputWithTime("Finished ETL"); + } + + private void checkTablesForFormattingErrors() { + StringUtilities.outputWithTime("Checking tables for formatting errors"); + + // for (String table : TABLES) { + // StringUtilities.outputWithTime("- Checking " + table); + CSVFileChecker checker = new CSVFileChecker(); + checker.setFrame(ObjectExchange.frame); + // checker.checkFile(folder + "/" + table + ".csv"); + checker.checkSpecifiedFields(folder, new ReadXlsxFileWithHeader(this.getClass().getResourceAsStream("Fields.xlsx")).iterator()); + // } + StringUtilities.outputWithTime("Finished checking tables"); + } + + private void sortTables() { + StringUtilities.outputWithTime("Sorting tables"); + for (String table : TABLES) { + StringUtilities.outputWithTime("- Sorting " + table); + FileSorter.sort(folder + "/" + table + ".csv", "PERSON_ID"); + } + StringUtilities.outputWithTime("Finished sorting"); + } + + private void loadMappings(DbSettings dbSettings) { + StringUtilities.outputWithTime("Loading mappings from server"); + RichConnection connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + + connection.use("vocabulary"); + + System.out.println("- Loading ATC to concept_id mapping"); + atcToConcept = new CodeToConceptMap("ATC to concept_id mapping"); + String query = "SELECT concept_id,concept_name,concept_code FROM concept WHERE VOCABULARY_ID = 21"; + for (Row row : connection.query(query)) + atcToConcept.add(row.get("CONCEPT_CODE"), row.get("CONCEPT_NAME"), row.getInt("CONCEPT_ID"), row.get("CONCEPT_CODE"), row.get("CONCEPT_NAME")); + + System.out.println("- Loading ICD-9 to concept_id mapping"); + icd9ToConcept = new CodeToConceptMap("ICD-9 to concept_id mapping"); + query = "SELECT source_code,source_code_description,target_concept_id,concept_code,concept_name FROM source_to_concept_map INNER JOIN concept ON target_concept_id = concept_id WHERE source_vocabulary_id = 2 AND target_vocabulary_id = 1"; + for (Row row : connection.query(query)) { + icd9ToConcept.add(row.get("SOURCE_CODE"), row.get("SOURCE_CODE_DESCRIPTION"), row.getInt("TARGET_CONCEPT_ID"), row.get("CONCEPT_CODE"), + row.get("CONCEPT_NAME")); + icd9ToConcept.add(row.get("SOURCE_CODE").replace(".", ""), row.get("SOURCE_CODE_DESCRIPTION"), row.getInt("TARGET_CONCEPT_ID"), + row.get("CONCEPT_CODE"), row.get("CONCEPT_NAME")); + } + + System.out.println("- Loading ICD-9 Procedure to concept_id mapping"); + icd9ProcToConcept = new CodeToConceptMap("ICD-9 Procedure to concept_id mapping"); + query = "SELECT concept_id,concept_name,concept_code FROM concept WHERE VOCABULARY_ID = 3"; + for (Row row : connection.query(query)) { + icd9ProcToConcept.add(row.get("CONCEPT_CODE"), row.get("CONCEPT_NAME"), row.getInt("CONCEPT_ID"), row.get("CONCEPT_CODE"), row.get("CONCEPT_NAME")); + icd9ProcToConcept.add(row.get("CONCEPT_CODE").replace(".", ""), row.get("CONCEPT_NAME"), row.getInt("CONCEPT_ID"), row.get("CONCEPT_CODE"), + row.get("CONCEPT_NAME")); + } + + System.out.println("- Loading ATC to RxNorm concept_id mapping"); + atcToRxNormConcepts = new CodeToConceptMap("ATC to RxNorm ingredient mapping"); + for (Row row : new ReadCSVFileWithHeader(this.getClass().getResourceAsStream("AtcToRxNormIngredient.csv"))) + atcToRxNormConcepts.add(row.get("atc"), row.get("atc_name"), row.getInt("rxnorm_concept_id"), row.get("rxnorm_code"), + row.get("rxnorm_concept name")); + + System.out.println("- Loading specialty to concept mapping"); + specialtyToConcept = new CodeToConceptMap("Specialty to concept mapping"); + for (Row row : new ReadCSVFileWithHeader(this.getClass().getResourceAsStream("specialty_italian.csv"))) + specialtyToConcept.add(removeLeadingZeroes(row.get("COD")), row.get("DESCRIZIONE"), row.getInt("CONCEPT_ID"), row.get("CONCEPT_CODE"), + row.get("CONCEPT_NAME")); + + System.out.println("- Loading proc_cod to type_outpat mapping"); + procToType = new HashMap(); + for (Row row : new ReadCSVFileWithHeader(this.getClass().getResourceAsStream("proc_OUTPAT.csv"))) + procToType.put(row.get("PROC_COD"), row.get("TYPE_OUTPAT")); + + StringUtilities.outputWithTime("Finished loading mappings"); + } + + private MultiRowIterator constructMultiRowIterator() { + @SuppressWarnings("unchecked") + Iterator[] iterators = new Iterator[TABLES.length]; + for (int i = 0; i < TABLES.length; i++) + iterators[i] = new ReadCSVFileWithHeader(folder + "/" + TABLES[i] + ".csv").iterator(); + return new MultiRowIterator("PERSON_ID", TABLES, iterators); + } + + private void processPerson(MultiRowSet personData) { + etlReport.registerIncomingData(personData); + + if (personData.linkingId.trim().length() == 0) { + for (String table : personData.keySet()) + if (personData.get(table).size() > 0) + etlReport.reportProblem(table, "Missing person_id in " + personData.get(table).size() + " rows in table " + table, ""); + return; + } + + if (personData.totalSize() > MAX_ROWS_PER_PERSON) { + etlReport.reportProblem("", "Person has too many rows (" + personData.totalSize() + "). Skipping person", personData.linkingId); + return; + } + + personCount++; + personId++; + + qcSampleConstructor.registerPersonData(personData, personId); + fixDateProblem(personData); + + hospRowToVisitOccurrenceId.clear(); + outpatRowToVisitOccurrenceId.clear(); + hospRowToProcedureOccurrenceId.clear(); + addToProvider(personData); + addToPerson(personData); + addToObservationPeriod(personData); + addToDeath(personData); + addToVisitOccurrence(personData); + addToDrugExposure(personData); + addToConditionOccurrence(personData); + addToProcedureOccurrence(personData); + addToProcedureCost(personData); + } + + private void fixDateProblem(MultiRowSet personData) { + for (List rows : personData.values()) + if (rows.size() != 0) { + List dateFields = new ArrayList(); + for (String fieldName : rows.get(0).getFieldNames()) + if (fieldName.toLowerCase().startsWith("date") || fieldName.toLowerCase().endsWith("date")) + dateFields.add(fieldName); + for (Row row : rows) + for (String fieldName : dateFields) { + String value = row.get(fieldName); + if (CSVFileChecker.isDateFormat1(value)) + row.set(fieldName, value.substring(0, 10)); + } + } + } + + private void insertBatch() { + addToDrugEra(); + addToConditionEra(); + removeRowsWithNonNullableNulls(); + + etlReport.registerOutgoingData(tableToRows); + for (String table : tableToRows.keySet()) + connection.insertIntoTable(tableToRows.get(table).iterator(), table, false); + tableToRows.clear(); + } + + private void removeRowsWithNonNullableNulls() { + for (String table : tableToRows.keySet()) { + Iterator iterator = tableToRows.get(table).iterator(); + while (iterator.hasNext()) { + Row row = iterator.next(); + String nonAllowedNullField = cdmv4NullableChecker.findNonAllowedNull(table, row); + if (nonAllowedNullField != null) { + if (row.getFieldNames().contains("person_id")) + etlReport.reportProblem(table, "Column " + nonAllowedNullField + " is null, could not create row", row.get("person_id")); + else + etlReport.reportProblem(table, "Column " + nonAllowedNullField + " is null, could not create row", ""); + iterator.remove(); + } + } + } + } + + private void addToProvider(MultiRowSet personData) { + for (Row row : personData.get("OUTPAT")) { + if (row.get("GROUP_CODE").length() > 0) { + int providerId = row.getInt("GROUP_CODE"); // Provider ID for outpatient providers is + if (providerIds.add(providerId)) { // Did not encounter this group code before + int specialtyConceptId = specialtyToConcept.getConceptId(removeLeadingZeroes(row.get("GROUP_CODE"))); + + Row provider = new Row(); + provider.add("provider_id", providerId); + provider.add("specialty_concept_id", specialtyConceptId); + provider.add("specialty_source_value", row.get("GROUP_CODE")); + provider.add("provider_source_value", ""); + tableToRows.put("provider", provider); + } + } + } + + for (Row row : personData.get("HOSP")) { + if (row.get("WARD_DISCHARGE").length() > 0) { + int providerId = row.getInt("WARD_DISCHARGE") + 1000; // Provider ID for hosp providers is + 1000; + if (providerIds.add(providerId)) { // Did not encounter this specialty code before + String specialtyCode = row.get("WARD_DISCHARGE").substring(0, 2); + int specialtyConceptId = specialtyToConcept.getConceptId(removeLeadingZeroes(specialtyCode)); + + Row provider = new Row(); + provider.add("provider_id", providerId); + provider.add("specialty_concept_id", specialtyConceptId); + provider.add("specialty_source_value", specialtyCode); + provider.add("provider_source_value", row.get("WARD_DISCHARGE")); + tableToRows.put("provider", provider); + } + } + } + + for (Row row : personData.get("PERSON")) { + if (row.get("GP_ID").length() != 0) { + int providerId = row.getInt("GP_ID") + 100000; // Provider ID for gp providers is + 100000; + if (providerIds.add(providerId)) { // Did not encounter this gp_id before + Row provider = new Row(); + provider.add("provider_id", providerId); + provider.add("specialty_concept_id", 38004446); // General Practice + provider.add("specialty_source_value", ""); + provider.add("provider_source_value", row.get("GP_ID")); + tableToRows.put("provider", provider); + } + } + } + } + + private void addToProcedureOccurrence(MultiRowSet personData) { + for (Row row : personData.get("HOSP")) { + String startDate = row.get("START_DATE"); + String mainProcDate = row.get("DATE_MAIN_PROC"); + String providerId = ""; + if (row.get("WARD_DISCHARGE").length() != 0) + providerId = Integer.toString(row.getInt("WARD_DISCHARGE") + 1000); // Provider ID for hosp providers is + 1000; + if (mainProcDate.length() == 0) + mainProcDate = startDate; + Long visitId = hospRowToVisitOccurrenceId.get(row.toString()); + hospRowToProcedureOccurrenceId.put(row.toString(), procedureOccurrenceId); + addHospProcedure(row.get("MAIN_PROC"), mainProcDate, visitId, providerId, 38000248); + addHospProcedure(row.get("SECONDARY_PROC_1"), startDate, visitId, providerId, 38000249); + addHospProcedure(row.get("SECONDARY_PROC_2"), startDate, visitId, providerId, 38000249); + addHospProcedure(row.get("SECONDARY_PROC_3"), startDate, visitId, providerId, 38000249); + addHospProcedure(row.get("SECONDARY_PROC_4"), startDate, visitId, providerId, 38000249); + addHospProcedure(row.get("SECONDARY_PROC_5"), startDate, visitId, providerId, 38000249); + } + + for (Row row : personData.get("OUTPAT")) { + String procDate = row.get("PROC_START_DATE"); + if (procDate.length() == 0) + procDate = row.get("PROC_DATE"); + if (procDate.length() != 0) { // Currently suppressing problems due to missing dates + Row procedureOccurrence = new Row(); + procedureOccurrence.add("procedure_occurrence_id", procedureOccurrenceId++); + procedureOccurrence.add("person_id", personId); + procedureOccurrence.add("procedure_concept_id", 0); + procedureOccurrence.add("procedure_date", procDate); + procedureOccurrence.add("procedure_type_concept_id", 38000266); + Long visitId = outpatRowToVisitOccurrenceId.get(row.toString()); + procedureOccurrence.add("visit_occurrence_id", (visitId == null ? "" : visitId.toString())); + procedureOccurrence.add("procedure_source_value", row.get("PROC_COD")); + procedureOccurrence.add("associated_provider_id", row.get("GROUP_CODE")); // Provider ID for outpatient providers is + tableToRows.put("procedure_occurrence", procedureOccurrence); + } + } + } + + private void addToProcedureCost(MultiRowSet personData) { + for (Row row : personData.get("HOSP")) + if (row.get("DRG").length() != 0) { + Row procedureCost = new Row(); + procedureCost.add("procedure_cost_id", procedureCostId++); + Long procedureOccurrenceId = hospRowToProcedureOccurrenceId.get(row.toString()); + procedureCost.add("procedure_occurrence_id", (procedureOccurrenceId == null ? "" : procedureOccurrenceId.toString())); + procedureCost.add("disease_class_source_value", row.get("DRG")); + tableToRows.put("procedure_cost", procedureCost); + } + } + + private void addHospProcedure(String proc, String date, Long visitId, String providerId, int procedureTypeConceptId) { + proc = proc.trim(); + if (proc.length() != 0) { + Row procedureOccurrence = new Row(); + procedureOccurrence.add("procedure_occurrence_id", procedureOccurrenceId++); + procedureOccurrence.add("person_id", personId); + procedureOccurrence.add("procedure_concept_id", icd9ProcToConcept.getConceptId(proc)); + procedureOccurrence.add("procedure_date", date); + procedureOccurrence.add("procedure_type_concept_id", procedureTypeConceptId); + procedureOccurrence.add("visit_occurrence_id", visitId); + procedureOccurrence.add("procedure_source_value", proc); + procedureOccurrence.add("associated_provider_id", providerId); + tableToRows.put("procedure_occurrence", procedureOccurrence); + } + } + + private void addToVisitOccurrence(MultiRowSet personData) { + for (Row row : personData.get("HOSP")) { + hospRowToVisitOccurrenceId.put(row.toString(), visitOccurrenceId); + + Row visitOccurrence = new Row(); + visitOccurrence.add("visit_occurrence_id", visitOccurrenceId++); + visitOccurrence.add("person_id", personId); + visitOccurrence.add("visit_start_date", row.get("START_DATE")); + if (row.get("END_DATE").length() == 0) + visitOccurrence.add("visit_end_date", row.get("START_DATE")); + else + visitOccurrence.add("visit_end_date", row.get("END_DATE")); + visitOccurrence.add("place_of_service_concept_id", 9201); // Inpatient visit + tableToRows.put("visit_occurrence", visitOccurrence); + } + + for (Row row : personData.get("OUTPAT")) { + String type = procToType.get(row.get("PROC_COD")); + if (type != null && type.equals("CLIN")) { + outpatRowToVisitOccurrenceId.put(row.toString(), visitOccurrenceId); + + Row visitOccurrence = new Row(); + visitOccurrence.add("visit_occurrence_id", visitOccurrenceId++); + visitOccurrence.add("person_id", personId); + visitOccurrence.add("visit_start_date", row.get("PROC_START_DATE")); + if (row.get("PROC_END_DATE").length() == 0) + visitOccurrence.add("visit_end_date", row.get("PROC_START_DATE")); + else + visitOccurrence.add("visit_end_date", row.get("PROC_END_DATE")); + visitOccurrence.add("place_of_service_concept_id", 9202); // Outpatient visit + tableToRows.put("visit_occurrence", visitOccurrence); + } + } + } + + private void addToConditionOccurrence(MultiRowSet personData) { + for (Row row : personData.get("HOSP")) { + String startDate = row.get("START_DATE"); + Long visitId = hospRowToVisitOccurrenceId.get(row.toString()); + String providerId = ""; + if (row.get("WARD_DISCHARGE").length() != 0) + providerId = Integer.toString(row.getInt("WARD_DISCHARGE") + 1000); // Provider ID for hosp providers is + 1000; + addHospCondition(startDate, row.get("MAIN_DIAGNOSIS"), visitId, providerId, 38000183); // Inpatient detail, primary + addHospCondition(startDate, row.get("SECONDARY_DIAGNOSIS_1"), visitId, providerId, 38000184); // Inpatient detail - 1st position + addHospCondition(startDate, row.get("SECONDARY_DIAGNOSIS_2"), visitId, providerId, 38000185); // Inpatient detail - 2st position + addHospCondition(startDate, row.get("SECONDARY_DIAGNOSIS_3"), visitId, providerId, 38000186); // Inpatient detail - 3st position + addHospCondition(startDate, row.get("SECONDARY_DIAGNOSIS_4"), visitId, providerId, 38000187); // Inpatient detail - 4st position + addHospCondition(startDate, row.get("SECONDARY_DIAGNOSIS_5"), visitId, providerId, 38000188); // Inpatient detail - 5st position + } + + for (Row row : personData.get("EXE")) { + Row conditionOccurrence = new Row(); + conditionOccurrence.add("condition_occurrence_id", conditionOccurrenceId++); + conditionOccurrence.add("person_id", personId); + conditionOccurrence.add("condition_concept_id", icd9ToConcept.getConceptId(row.get("EXEMPTION_CODE"))); + conditionOccurrence.add("condition_start_date", row.get("EXE_START_DATE")); + conditionOccurrence.add("condition_type_concept_id", 38000245); + conditionOccurrence.add("visit_occurrence_id", ""); + conditionOccurrence.add("condition_source_value", row.get("EXEMPTION_CODE")); + conditionOccurrence.add("associated_provider_id", ""); + tableToRows.put("condition_occurrence", conditionOccurrence); + } + } + + private void addToConditionEra() { + ConditionEraGenerator conditionEraGenerator = new ConditionEraGenerator(); + for (Row row : tableToRows.get("condition_occurrence")) { + int personId = row.getInt("person_id"); + long startDate = StringUtilities.databaseTimeStringToDays(row.get("condition_start_date")); + long endDate = StringUtilities.MISSING_DATE; + int conceptId = row.getInt("condition_concept_id"); + conditionEraGenerator.addCondition(personId, startDate, endDate, conceptId); + } + + tableToRows.putAll("condition_era", conditionEraGenerator.generateRows()); + } + + private void addHospCondition(String startDate, String diagnose, Long visitId, String providerId, int typeConceptId) { + diagnose = diagnose.trim(); + if (diagnose.length() != 0) { + Row conditionOccurrence = new Row(); + conditionOccurrence.add("condition_occurrence_id", conditionOccurrenceId++); + conditionOccurrence.add("person_id", personId); + conditionOccurrence.add("condition_concept_id", icd9ToConcept.getConceptId(diagnose)); + conditionOccurrence.add("condition_start_date", startDate); + conditionOccurrence.add("condition_type_concept_id", typeConceptId); + conditionOccurrence.add("visit_occurrence_id", visitId); + conditionOccurrence.add("condition_source_value", diagnose); + conditionOccurrence.add("associated_provider_id", providerId); + tableToRows.put("condition_occurrence", conditionOccurrence); + } + } + + private void addToDrugExposure(MultiRowSet personData) { + for (Row row : personData.get("DRUGS")) { + Row drugExposure = new Row(); + drugExposure.add("drug_exposure_id", drugExposureId++); + drugExposure.add("person_id", personId); + drugExposure.add("drug_concept_id", atcToConcept.getConceptId(row.get("ATC"))); + drugExposure.add("drug_exposure_start_date", row.get("DRUG_DISPENSING_DATE")); + drugExposure.add("days_supply", row.get("DURATION")); + drugExposure.add("drug_type_concept_id", 38000175); + drugExposure.add("drug_source_value", row.get("PRODUCT_CODE")); + drugExposure.add("atc", row.get("ATC")); // Store temporarily for drug era + tableToRows.put("drug_exposure", drugExposure); + } + + for (Row row : personData.get("DDRUG")) { + Row drugExposure = new Row(); + drugExposure.add("drug_exposure_id", drugExposureId++); + drugExposure.add("person_id", personId); + drugExposure.add("drug_concept_id", atcToConcept.getConceptId(row.get("ATC"))); + drugExposure.add("drug_exposure_start_date", row.get("DRUG_DISPENSING_DATE")); + drugExposure.add("days_supply", row.get("DURATION")); + drugExposure.add("drug_type_concept_id", 38000175); + drugExposure.add("drug_source_value", row.get("PRODUCT_CODE")); + drugExposure.add("atc", row.get("ATC")); // Store temporarily for drug era + tableToRows.put("drug_exposure", drugExposure); + } + } + + private void addToDrugEra() { + DrugEraGenerator drugEraGenerator = new DrugEraGenerator(); + for (Row row : tableToRows.get("drug_exposure")) { + int personId = row.getInt("person_id"); + long startDate = StringUtilities.databaseTimeStringToDays(row.get("drug_exposure_start_date")); + long endDate = startDate + Math.round(parseZeroIfEmpty(row.get("days_supply"))); + for (int conceptId : atcToRxNormConcepts.getConceptIds(row.get("atc"))) + drugEraGenerator.addExposure(personId, startDate, endDate, conceptId); + row.remove("atc"); + } + + tableToRows.putAll("drug_era", drugEraGenerator.generateRows()); + } + + private void addToDeath(MultiRowSet personData) { + for (Row row : personData.get("PERSON")) { + if (row.get("DATE_OF_DEATH").trim().length() != 0) { + Row death = new Row(); + death.add("person_id", personId); + death.add("death_type_concept_id", 38003565); + death.add("death_date", row.get("DATE_OF_DEATH")); + tableToRows.put("death", death); + } + } + } + + private void addToObservationPeriod(MultiRowSet personData) { + List rows = personData.get("PERSON"); + if (rows.size() == 0) + return; + + RowUtilities.sort(rows, "STARTDATE"); + long observationPeriodStartDate = Long.MIN_VALUE; + long observationPeriodEndDate = Long.MIN_VALUE; + for (Row row : rows) { + if (row.get("STARTDATE").length() == 0) { + etlReport.reportProblem("PERSON", "No person startdate, could not create observation period", row.get("PERSON_ID")); + continue; + } + long startDate = StringUtilities.databaseTimeStringToDays(row.get("STARTDATE")); + startDate = Math.max(startDate, minObservationDate); + long endDate = StringUtilities.databaseTimeStringToDays(row.get("ENDDATE")); + endDate = endDate == StringUtilities.MISSING_DATE ? extractionDate : Math.min(endDate, extractionDate); + if (observationPeriodEndDate == startDate - 1) { + observationPeriodEndDate = endDate; + } else { + if (observationPeriodStartDate != Long.MIN_VALUE && observationPeriodStartDate < observationPeriodEndDate) { + Row observationPeriod = new Row(); + observationPeriod.add("observation_period_id", observationPeriodId++); + observationPeriod.add("person_id", personId); + observationPeriod.add("observation_period_start_date", StringUtilities.daysToDatabaseDateString(observationPeriodStartDate)); + observationPeriod.add("observation_period_end_date", StringUtilities.daysToDatabaseDateString(observationPeriodEndDate)); + tableToRows.put("observation_period", observationPeriod); + } + observationPeriodStartDate = startDate; + observationPeriodEndDate = endDate; + + } + } + if (observationPeriodStartDate != Long.MIN_VALUE && observationPeriodStartDate < observationPeriodEndDate) { + Row observationPeriod = new Row(); + observationPeriod.add("observation_period_id", observationPeriodId++); + observationPeriod.add("person_id", personId); + observationPeriod.add("observation_period_start_date", StringUtilities.daysToDatabaseDateString(observationPeriodStartDate)); + observationPeriod.add("observation_period_end_date", StringUtilities.daysToDatabaseDateString(observationPeriodEndDate)); + tableToRows.put("observation_period", observationPeriod); + } + } + + private void addToPerson(MultiRowSet personData) { + List rows = personData.get("PERSON"); + if (rows.size() == 0) + return; + + Row row = rows.get(0); + if (rows.size() > 1) { // Multiple rows: find the one with the latest startdate: + RowUtilities.sort(rows, "STARTDATE"); + row = rows.get(rows.size() - 1); + } + + Row person = new Row(); + person.add("person_id", personId); + person.add("person_source_value", row.get("PERSON_ID")); + String gender = row.get("GENDER_CONCEPT_ID"); + person.add("gender_source_value", gender); + person.add("gender_concept_id", gender.toLowerCase().equals("m") || gender.toLowerCase().equals("1") ? "8507" : gender.toLowerCase().equals("f") + || gender.toLowerCase().equals("2") ? "8532" : "8521"); + String dateOfBirth = row.get("DATE_OF_BIRTH"); + + if (dateOfBirth.length() < 10) { + person.add("year_of_birth", ""); + person.add("month_of_birth", ""); + person.add("day_of_birth", ""); + } else { + person.add("year_of_birth", dateOfBirth.substring(0, 4)); + person.add("month_of_birth", dateOfBirth.substring(5, 7)); + person.add("day_of_birth", dateOfBirth.substring(8, 10)); + } + if (row.get("GP_ID").length() != 0) + person.add("provider_id", row.getInt("GP_ID") + 100000);// Provider ID for gp providers is + 100000; + else + person.add("provider_id", ""); + person.add("location_id", row.get("LOCATION_CONCEPT_ID")); + tableToRows.put("person", person); + } + + private double parseZeroIfEmpty(String number) { + if (number.length() == 0) + return 0; + else + return Double.parseDouble(number); + } + + private String removeLeadingZeroes(String string) { + for (int i = 0; i < string.length(); i++) + if (string.charAt(i) != '0') + return string.substring(i); + return string; + } +} diff --git a/src/org/ohdsi/whiteRabbit/etls/ars/AddExtraInfoToAtcToRxNormMap.java b/src/org/ohdsi/whiteRabbit/etls/ars/AddExtraInfoToAtcToRxNormMap.java new file mode 100644 index 00000000..faae0984 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/etls/ars/AddExtraInfoToAtcToRxNormMap.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.etls.ars; + +import java.util.HashMap; +import java.util.Map; + +import org.ohdsi.databases.DbType; +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.files.ReadCSVFileWithHeader; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.utilities.files.WriteCSVFileWithHeader; + +public class AddExtraInfoToAtcToRxNormMap { + + public static void main(String[] args) { + RichConnection connection = new RichConnection("RNDUSRDHIT06", null, null, null, DbType.MSSQL); + connection.setContext(AddExtraInfoToAtcToRxNormMap.class); + connection.use("OMOP_Vocabulary"); + + Map atcToConceptId = new HashMap(); + Map conceptIdToRxNormCode = new HashMap(); + + String query = "SELECT concept_id,concept_name,concept_code FROM concept WHERE VOCABULARY_ID = 21"; + for (Row row : connection.query(query)) + atcToConceptId.put(row.get("CONCEPT_CODE"), row.getInt("CONCEPT_ID")); + + query = "SELECT concept_id,concept_name,concept_code FROM concept WHERE VOCABULARY_ID = 8"; + for (Row row : connection.query(query)) + conceptIdToRxNormCode.put(row.getInt("CONCEPT_ID"),row.get("CONCEPT_CODE")); + + WriteCSVFileWithHeader out = new WriteCSVFileWithHeader("c:/temp/AtcToRxNormIngredient.csv"); + for (Row row : new ReadCSVFileWithHeader(AddExtraInfoToAtcToRxNormMap.class.getResourceAsStream("ATCToConceptID.csv"))){ + Integer atcConceptId = atcToConceptId.get(row.get("ATC")); + if (atcConceptId == null) + atcConceptId = 0; + String rxNormCode = conceptIdToRxNormCode.get(row.getInt("ConceptID")); + if (rxNormCode == null) + rxNormCode = ""; + row.add("atc_concept_id", atcConceptId); + row.add("rxnorm_code", rxNormCode); + out.write(row); + } + out.close(); + } + +} diff --git a/src/org/ohdsi/whiteRabbit/etls/ars/AtcToRxNormIngredient.csv b/src/org/ohdsi/whiteRabbit/etls/ars/AtcToRxNormIngredient.csv new file mode 100644 index 00000000..a362bbf5 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/etls/ars/AtcToRxNormIngredient.csv @@ -0,0 +1,3285 @@ +atc,atc_name,rxnorm_concept_id,rxnorm_concept name,atc_concept_id,rxnorm_code +A01AA,CARIES PROPHYLACTIC AGENTS,19035704,Calcium Carbonate,21600004,1897 +A01AA,CARIES PROPHYLACTIC AGENTS,19068715,monofluorophosphate,21600004,52885 +A01AA01,SODIUM FLUORIDE,19069022,Sodium Fluoride,21600005,9873 +A01AA04,STANNOUS FLUORIDE,1036094,Stannous Fluoride,21600008,10030 +A01AA51,"SODIUM FLUORIDE, COMBINATIONS",927322,potassium nitrate,21600010,34316 +A01AA51,"SODIUM FLUORIDE, COMBINATIONS",19035704,Calcium Carbonate,21600010,1897 +A01AA51,"SODIUM FLUORIDE, COMBINATIONS",19069022,Sodium Fluoride,21600010,9873 +A01AB02,HYDROGEN PEROXIDE,1776430,Hydrogen Peroxide,21600012,5499 +A01AB03,CHLORHEXIDINE,1790812,Chlorhexidine,21600013,2358 +A01AB04,AMPHOTERICIN B,1717240,Amphotericin B,21600014,732 +A01AB11,VARIOUS,991706,SULFONATED PHENOL,21600021,236718 +A01AB11,VARIOUS,1036600,Sulfuric acid,21600021,10231 +A01AB11,VARIOUS,1750087,Povidone-Iodine,21600021,8611 +A01AB18,CLOTRIMAZOLE,1000632,Clotrimazole,21600028,2623 +A01AB22,DOXYCYCLINE,1738521,Doxycycline,21600031,3640 +A01AB23,MINOCYCLINE,1708880,Minocycline,21600032,6980 +A01AC01,TRIAMCINOLONE,903963,Triamcinolone,21600034,10759 +A01AD07,AMLEXANOX,957623,amlexanox,21600043,46307 +A01AD11,VARIOUS,906914,Urea,21600045,11002 +A01AD11,VARIOUS,916460,Benzalkonium,21600045,1378 +A01AD11,VARIOUS,917006,Benzocaine,21600045,1399 +A01AD11,VARIOUS,919681,Benzyl Alcohol,21600045,1426 +A01AD11,VARIOUS,942494,chlorophyllin copper complex,21600045,82242 +A01AD11,VARIOUS,958999,carbamide peroxide,21600045,47686 +A01AD11,VARIOUS,961145,Glycerin,21600045,4910 +A01AD11,VARIOUS,989301,Cetylpyridinium,21600045,2286 +A01AD11,VARIOUS,19044317,zinc chloride,21600045,39937 +A02AA01,MAGNESIUM CARBONATE,908464,magnesium carbonate,21600049,29155 +A02AA04,MAGNESIUM HYDROXIDE,992956,Magnesium Hydroxide,21600052,6581 +A02AA05,MAGNESIUM SILICATE,908730,magnesium trisilicate,21600053,29170 +A02AB,ALUMINIUM COMPOUNDS,934431,basic aluminum carbonate gel,21600055,18789 +A02AB,ALUMINIUM COMPOUNDS,959420,Aluminum carbonate,21600055,89858 +A02AB01,ALUMINIUM HYDROXIDE,985247,Aluminum Hydroxide,21600056,612 +A02AB03,ALUMINIUM PHOSPHATE,19030675,aluminum phosphate,21600058,17618 +A02AB04,DIHYDROXIALUMINI SODIUM CARBONATE,989727,dihydroxyaluminum sodium carbonate,21600059,23163 +A02AC,CALCIUM COMPOUNDS,1337159,Calcium Glycerophosphate,21600064,1909 +A02AC01,CALCIUM CARBONATE,1516800,Risedronate,21600065,73056 +A02AC01,CALCIUM CARBONATE,19035704,Calcium Carbonate,21600065,1897 +A02AD01,ORDINARY SALT COMBINATIONS,908464,magnesium carbonate,21600069,29155 +A02AD01,ORDINARY SALT COMBINATIONS,985247,Aluminum Hydroxide,21600069,612 +A02AD01,ORDINARY SALT COMBINATIONS,992956,Magnesium Hydroxide,21600069,6581 +A02AD01,ORDINARY SALT COMBINATIONS,19035704,Calcium Carbonate,21600069,1897 +A02AD02,MAGALDRATE,908360,magaldrate,21600070,29151 +A02AF01,MAGALDRATE AND ANTIFLATULENTS,908360,magaldrate,21600075,29151 +A02AF01,MAGALDRATE AND ANTIFLATULENTS,966991,Simethicone,21600075,9796 +A02AF02,ORDINARY SALT COMBINATIONS AND ANTIFLATULENTS,966991,Simethicone,21600076,9796 +A02AF02,ORDINARY SALT COMBINATIONS AND ANTIFLATULENTS,985247,Aluminum Hydroxide,21600076,612 +A02AF02,ORDINARY SALT COMBINATIONS AND ANTIFLATULENTS,992956,Magnesium Hydroxide,21600076,6581 +A02AF02,ORDINARY SALT COMBINATIONS AND ANTIFLATULENTS,1701928,Activated Charcoal,21600076,272 +A02AF02,ORDINARY SALT COMBINATIONS AND ANTIFLATULENTS,19035704,Calcium Carbonate,21600076,1897 +A02AH,ANTACIDS WITH SODIUM BICARBONATE,939506,Sodium Bicarbonate,21600078,36676 +A02AX,"ANTACIDS, OTHER COMBINATIONS",939506,Sodium Bicarbonate,21600079,36676 +A02AX,"ANTACIDS, OTHER COMBINATIONS",962398,Glycine,21600079,4919 +A02AX,"ANTACIDS, OTHER COMBINATIONS",19027080,potassium bicarbonate,21600079,34296 +A02AX,"ANTACIDS, OTHER COMBINATIONS",19035704,Calcium Carbonate,21600079,1897 +A02BA01,CIMETIDINE,997276,Cimetidine,21600082,2541 +A02BA02,RANITIDINE,961047,Ranitidine,21600083,9143 +A02BA03,FAMOTIDINE,953076,Famotidine,21600084,4278 +A02BA04,NIZATIDINE,950696,Nizatidine,21600085,42319 +A02BA07,RANITIDINE BISMUTH CITRATE,961047,Ranitidine,21600088,9143 +A02BA53,"FAMOTIDINE, COMBINATIONS",953076,Famotidine,21600091,4278 +A02BA53,"FAMOTIDINE, COMBINATIONS",992956,Magnesium Hydroxide,21600091,6581 +A02BA53,"FAMOTIDINE, COMBINATIONS",19035704,Calcium Carbonate,21600091,1897 +A02BB01,MISOPROSTOL,1150871,Misoprostol,21600093,42331 +A02BC,PROTON PUMP INHIBITORS,19039926,dexlansoprazole,21600095,816346 +A02BC01,OMEPRAZOLE,923645,Omeprazole,21600096,7646 +A02BC01,OMEPRAZOLE,939506,Sodium Bicarbonate,21600096,36676 +A02BC02,PANTOPRAZOLE,948078,pantoprazole,21600097,40790 +A02BC03,LANSOPRAZOLE,929887,lansoprazole,21600098,17128 +A02BC03,LANSOPRAZOLE,1115008,Naproxen,21600098,7258 +A02BC03,LANSOPRAZOLE,1713332,Amoxicillin,21600098,723 +A02BC03,LANSOPRAZOLE,1750500,Clarithromycin,21600098,21212 +A02BC05,ESOMEPRAZOLE,904453,Esomeprazole,21600100,283742 +A02BD07,"LANSOPRAZOLE, AMOXICILLIN AND CLARITHROMYCIN",929887,lansoprazole,21600108,17128 +A02BD07,"LANSOPRAZOLE, AMOXICILLIN AND CLARITHROMYCIN",1713332,Amoxicillin,21600108,723 +A02BD07,"LANSOPRAZOLE, AMOXICILLIN AND CLARITHROMYCIN",1750500,Clarithromycin,21600108,21212 +A02BX02,SUCRALFATE,1036228,Sucralfate,21600111,10156 +A02BX13,ALGINIC ACID,908464,magnesium carbonate,21600122,29155 +A02BX13,ALGINIC ACID,985247,Aluminum Hydroxide,21600122,612 +A03AA01,OXYPHENCYCLIMINE,19019094,oxyphencyclimine,21600130,32698 +A03AA07,DICYCLOVERINE,734275,Phenobarbital,21600135,8134 +A03AA07,DICYCLOVERINE,924724,Dicyclomine,21600135,3361 +A03AB,"SYNTH ANTICHOLINERGICS,QUATERNARY AMMONIUM CMPDS",950792,clidinium,21600139,21232 +A03AB02,GLYCOPYRRONIUM,963353,Glycopyrrolate,21600141,4955 +A03AB03,OXYPHENONIUM,19025928,Oxyphenonium,21600142,7818 +A03AB05,PROPANTHELINE,953391,Propantheline,21600144,8761 +A03AB07,METHANTHELINE,19004153,methantheline,21600146,6821 +A03AB08,TRIDIHEXETHYL,19042695,tridihexethyl,21600147,38617 +A03AB09,ISOPROPAMIDE,19058613,Isopropamide,21600148,89784 +A03AB10,HEXOCYCLIUM,19001653,hexocyclium,21600149,26867 +A03AB12,MEPENZOLATE,904704,Mepenzolate,21600151,107770 +A03AB15,DIPHEMANIL,19135822,Diphemanil,21600154,89782 +A03AD01,PAPAVERINE,1326901,Papaverine,21600166,7895 +A03AE01,ALOSETRON,948555,alosetron,21600170,85248 +A03AE02,TEGASEROD,916943,tegaserod,21600171,139778 +A03AX13,SILICONES,966991,Simethicone,21600187,9796 +A03BA,"BELLADONNA ALKALOIDS, TERTIARY AMINES",914335,Atropine,21600191,1223 +A03BA,"BELLADONNA ALKALOIDS, TERTIARY AMINES",923672,Hyoscyamine,21600191,153970 +A03BA,"BELLADONNA ALKALOIDS, TERTIARY AMINES",965748,Scopolamine,21600191,9601 +A03BA01,ATROPINE,914335,Atropine,21600192,1223 +A03BA03,HYOSCYAMINE,923672,Hyoscyamine,21600193,153970 +A03BA04,BELLADONNA TOTAL ALKALOIDS,1116109,Belladonna Alkaloids,21600194,1359 +A03BB03,METHYLSCOPOLAMINE,1158632,Methscopolamine,21600198,89785 +A03CA01,ISOPROPAMIDE AND PSYCHOLEPTICS,752061,Prochlorperazine,21600203,8704 +A03CA01,ISOPROPAMIDE AND PSYCHOLEPTICS,19058613,Isopropamide,21600203,89784 +A03CA02,CLIDINIUM AND PSYCHOLEPTICS,950792,clidinium,21600204,21232 +A03CA02,CLIDINIUM AND PSYCHOLEPTICS,990678,Chlordiazepoxide,21600204,2356 +A03CA02,CLIDINIUM AND PSYCHOLEPTICS,1158632,Methscopolamine,21600204,89785 +C01AA04,DIGITOXIN,19026180,Digitoxin,21600233,3403 +C01AA05,DIGOXIN,1326303,Digoxin,21600234,3407 +C01AA07,DESLANOSIDE,19017074,Deslanoside,21600236,3248 +C01AC01,G-STROPHANTHIN,19129640,Ouabain,21600244,7762 +C01BA02,PROCAINAMIDE,1351461,Procainamide,21600251,8700 +C01BA03,DISOPYRAMIDE,1335606,Disopyramide,21600252,3541 +C01BB01,LIDOCAINE,989878,Lidocaine,21600260,6387 +C01BB02,MEXILETINE,1307542,Mexiletine,21600261,6926 +C01BB03,TOCAINIDE,1351447,Tocainide,21600262,42359 +C01BC03,PROPAFENONE,1353256,Propafenone,21600265,8754 +C01BC04,FLECAINIDE,1354860,Flecainide,21600266,4441 +C01BC08,ENCAINIDE,19051513,Encainide,21600268,42368 +C01BD01,AMIODARONE,1309944,Amiodarone,21600270,703 +C01BD02,BRETYLIUM TOSILATE,19038998,bretylium,21600271,19685 +C01BD04,DOFETILIDE,1362979,dofetilide,21600273,49247 +C01BD05,IBUTILIDE,19050087,ibutilide,21600274,41289 +C01BG01,MORACIZINE,1344996,Moricizine,21600277,40169 +C01CA02,ISOPRENALINE,1183554,Isoproterenol,21600282,6054 +C01CA03,NOREPINEPHRINE,1321341,Norepinephrine,21600283,7512 +C01CA04,DOPAMINE,1337860,Dopamine,21600284,3628 +C01CA06,PHENYLEPHRINE,1135766,Phenylephrine,21600286,8163 +C01CA07,DOBUTAMINE,1337720,Dobutamine,21600287,3616 +C01CA09,METARAMINOL,19003303,Metaraminol,21600289,6805 +C01CA10,METHOXAMINE,19005208,Methoxamine,21600290,6853 +C01CA11,MEPHENTERMINE,19002664,Mephentermine,21600291,6756 +C01CA17,MIDODRINE,1308368,Midodrine,21600297,6963 +C01CA19,FENOLDOPAM,19095721,Fenoldopam,21600299,24853 +C01CA22,ARBUTAMINE,19086330,arbutamine,21600301,61609 +C01CA24,EPINEPHRINE,1192710,Chlorpheniramine,21600303,2400 +C01CA24,EPINEPHRINE,1343916,Epinephrine,21600303,3992 +C01CE01,AMRINONE,19017805,Inamrinone,21600307,738 +C01CE02,MILRINONE,1368671,Milrinone,21600308,52769 +C01DA02,GLYCERYL TRINITRATE,1361711,Nitroglycerin,21600317,4917 +C01DA05,PENTAERITHRITYL TETRANITRATE,19022446,pentaerythritol,21600319,33055 +C01DA08,ISOSORBIDE DINITRATE,1383925,Isosorbide Dinitrate,21600321,6058 +C01DA13,ERYTRITYL TETRANITRATE,19045644,Erythrityl Tetranitrate,21600323,4040 +C01DA14,ISOSORBIDE MONONITRATE,1383815,Isosorbide,21600324,6057 +C01DA55,"PENTAERITHRITYL TETRANITRATE, COMBINATIONS",734275,Phenobarbital,21600329,8134 +C01DA55,"PENTAERITHRITYL TETRANITRATE, COMBINATIONS",19022446,pentaerythritol,21600329,33055 +C01DB01,FLOSEQUINAN,19096489,flosequinan,21600336,25089 +C01DX19,NESIRITIDE,1338985,Brain natriuretic peptide,21600355,19666 +C01EA01,ALPROSTADIL,1381504,Alprostadil,21600362,598 +C01EB,OTHER CARDIAC PREPARATIONS,1351115,coenzyme Q10,21600363,21406 +C01EB,OTHER CARDIAC PREPARATIONS,1389885,red yeast rice,21600363,232540 +C01EB03,INDOMETACIN,1178663,Indomethacin,21600365,5781 +C01EB04,CRATAEGUS GLYCOSIDES,1324250,Hawthorn preparation,21600366,155097 +C01EB04,CRATAEGUS GLYCOSIDES,1401437,Garlic preparation,21600366,265647 +C01EB09,UBIDECARENONE,1306837,Ubiquinone,21600370,10975 +C01EB09,UBIDECARENONE,1351115,coenzyme Q10,21600370,21406 +C01EB09,UBIDECARENONE,19101786,ubiquinol,21600370,39085 +C01EB10,ADENOSINE,1309204,Adenosine,21600371,296 +C01EB10,ADENOSINE,19015230,Adenosine Triphosphate,21600371,318 +C01EB16,IBUPROFEN,1177480,Ibuprofen,21600375,5640 +C01EB18,RANOLAZINE,1337107,ranolazine,21600377,35829 +C01EB21,REGADENOSON,19090761,regadenoson,21600379,640062 +C01EX,OTHER CARDIAC COMBINATION PRODUCTS,1351115,coenzyme Q10,21600380,21406 +C01EX,OTHER CARDIAC COMBINATION PRODUCTS,1373928,Hydralazine,21600380,5470 +C01EX,OTHER CARDIAC COMBINATION PRODUCTS,1383925,Isosorbide Dinitrate,21600380,6058 +C01EX,OTHER CARDIAC COMBINATION PRODUCTS,1553610,Levocarnitine,21600380,42955 +C01EX,OTHER CARDIAC COMBINATION PRODUCTS,19009540,Vitamin E,21600380,11256 +C01EX,OTHER CARDIAC COMBINATION PRODUCTS,19062817,Riboflavin,21600380,9346 +C02AA01,RESCINNAMINE,19062195,rescinnamine,21600384,9259 +C02AA02,RESERPINE,1362225,Reserpine,21600385,9260 +C02AA04,"RAUWOLFIA ALKALOIDS, WHOLE ROOT",1326378,Rauwolfia preparation,21600387,78678 +C02AA05,DESERPIDINE,1387219,deserpidine,21600388,62174 +C02AB01,METHYLDOPA (LEVOROTATORY),1305447,Methyldopa,21600395,6876 +C02AB01,METHYLDOPA (LEVOROTATORY),1305496,Methyldopate,21600395,6877 +C02AC,IMIDAZOLINE RECEPTOR AGONISTS,1366237,Guanabenz,21600397,5033 +C02AC01,CLONIDINE,1398937,Clonidine,21600398,2599 +C02AC02,GUANFACINE,1344965,Guanfacine,21600399,40114 +C02BA01,TRIMETAPHAN,19005658,Trimethaphan,21600405,10828 +C02BB01,MECAMYLAMINE,1394333,Mecamylamine,21600407,6673 +C02CA01,PRAZOSIN,1350489,Prazosin,21600411,8629 +C02CA04,DOXAZOSIN,1363053,Doxazosin,21600414,49276 +C02CC,GUANIDINE DERIVATIVES,1400959,guanadrel,21600416,26296 +C02CC02,GUANETHIDINE,1366279,Guanethidine,21600418,5036 +C02DA01,DIAZOXIDE,1523280,Diazoxide,21600426,3327 +C02DB02,HYDRALAZINE,1373928,Hydralazine,21600429,5470 +C02DC01,MINOXIDIL,1309068,Minoxidil,21600433,6984 +C02DD01,NITROPRUSSIDE,19020994,Nitroprusside,21600435,7476 +C02KB01,METIROSINE,1401581,Metyrosine,21600442,266604 +C02KC01,PARGYLINE,19027413,Pargyline,21600444,7930 +C02KX,OTHER ANTIHYPERTENSIVES,1316262,sildenafil,21600447,136411 +C02KX01,BOSENTAN,1321636,bosentan,21600448,75207 +C02KX02,AMBRISENTAN,1337068,ambrisentan,21600449,358274 +C02LA01,RESERPINE AND DIURETICS,904639,Trichlormethiazide,21600453,10772 +C02LA01,RESERPINE AND DIURETICS,905273,Methyclothiazide,21600453,6860 +C02LA01,RESERPINE AND DIURETICS,948787,Polythiazide,21600453,8565 +C02LA01,RESERPINE AND DIURETICS,974166,Hydrochlorothiazide,21600453,5487 +C02LA01,RESERPINE AND DIURETICS,992590,Chlorothiazide,21600453,2396 +C02LA01,RESERPINE AND DIURETICS,1362225,Reserpine,21600453,9260 +C02LA01,RESERPINE AND DIURETICS,1373928,Hydralazine,21600453,5470 +C02LA01,RESERPINE AND DIURETICS,1376289,Hydroflumethiazide,21600453,5495 +C02LA01,RESERPINE AND DIURETICS,1395058,Chlorthalidone,21600453,2409 +C02LA01,RESERPINE AND DIURETICS,19036731,benzothiazide,21600453,19008 +C02LA03,DESERPIDINE AND DIURETICS,905273,Methyclothiazide,21600455,6860 +C02LA03,DESERPIDINE AND DIURETICS,974166,Hydrochlorothiazide,21600455,5487 +C02LA03,DESERPIDINE AND DIURETICS,1387219,deserpidine,21600455,62174 +C02LA08,"RAUWOLFIA ALKALOIDS, WHOLE ROOT AND DIURETICS",1316354,Bendroflumethiazide,21600458,1369 +C02LA08,"RAUWOLFIA ALKALOIDS, WHOLE ROOT AND DIURETICS",1326378,Rauwolfia preparation,21600458,78678 +C02LB01,METHYLDOPA (LEVOROTATORY) AND DIURETICS,974166,Hydrochlorothiazide,21600465,5487 +C02LB01,METHYLDOPA (LEVOROTATORY) AND DIURETICS,992590,Chlorothiazide,21600465,2396 +C02LB01,METHYLDOPA (LEVOROTATORY) AND DIURETICS,1305447,Methyldopa,21600465,6876 +C02LC01,CLONIDINE AND DIURETICS,1395058,Chlorthalidone,21600467,2409 +C02LC01,CLONIDINE AND DIURETICS,1398937,Clonidine,21600467,2599 +C02LE01,PRAZOSIN AND DIURETICS,948787,Polythiazide,21600471,8565 +C02LE01,PRAZOSIN AND DIURETICS,1350489,Prazosin,21600471,8629 +C02LF01,GUANETHIDINE AND DIURETICS,974166,Hydrochlorothiazide,21600473,5487 +C02LF01,GUANETHIDINE AND DIURETICS,1366279,Guanethidine,21600473,5036 +C02LG02,HYDRALAZINE AND DIURETICS,974166,Hydrochlorothiazide,21600476,5487 +C02LG02,HYDRALAZINE AND DIURETICS,1373928,Hydralazine,21600476,5470 +A03ED,ANTISPASMODICS IN COMBINATION WITH OTHER DRUGS,734275,Phenobarbital,21600481,8134 +A03ED,ANTISPASMODICS IN COMBINATION WITH OTHER DRUGS,914335,Atropine,21600481,1223 +A03ED,ANTISPASMODICS IN COMBINATION WITH OTHER DRUGS,923672,Hyoscyamine,21600481,153970 +A03ED,ANTISPASMODICS IN COMBINATION WITH OTHER DRUGS,965748,Scopolamine,21600481,9601 +A03ED,ANTISPASMODICS IN COMBINATION WITH OTHER DRUGS,966991,Simethicone,21600481,9796 +A03ED,ANTISPASMODICS IN COMBINATION WITH OTHER DRUGS,1116109,Belladonna Alkaloids,21600481,1359 +A03ED,ANTISPASMODICS IN COMBINATION WITH OTHER DRUGS,1123904,phenyltoloxamine,21600481,33408 +A03ED,ANTISPASMODICS IN COMBINATION WITH OTHER DRUGS,1145379,Ergotamine,21600481,4025 +A03FA01,METOCLOPRAMIDE,906780,Metoclopramide,21600484,6915 +A03FA02,CISAPRIDE,932196,Cisapride,21600485,35255 +A04AA01,ONDANSETRON,1000560,Ondansetron,21600493,26225 +A04AA02,GRANISETRON,1000772,Granisetron,21600494,26237 +A04AA04,DOLASETRON,903459,Dolasetron,21600496,68091 +A04AA05,PALONOSETRON,911354,palonosetron,21600497,70561 +A04AD,OTHER ANTIEMETICS,917006,Benzocaine,21600498,1399 +A04AD,OTHER ANTIEMETICS,942799,trimethobenzamide,21600498,38685 +A04AD,OTHER ANTIEMETICS,19089992,diphenidol,21600498,23370 +A04AD01,SCOPOLAMINE,965748,Scopolamine,21600499,9601 +A04AD10,DRONABINOL,1037005,Tetrahydrocannabinol,21600503,10402 +A04AD11,NABILONE,913440,nabilone,21600504,31447 +A04AD12,APREPITANT,936748,aprepitant,21600505,358255 +A05AA01,CHENODEOXYCHOLIC ACID,19052447,Chenodeoxycholate,21600512,42588 +A05AA02,URSODEOXYCHOLIC ACID,988095,Ursodeoxycholate,21600513,62427 +A05AB,PREPARATIONS FOR BILIARY TRACT THERAPY,19052817,Dehydrocholate,21600515,42625 +A05BA,LIVER THERAPY,19042345,Lecithin,21600522,8214 +A06AA,"SOFTENERS, EMOLLIENTS",941258,Docusate,21600533,82003 +A06AA01,LIQUID PARAFFIN,908523,Mineral Oil,21600534,6972 +A06AA02,DOCUSATE SODIUM,941258,Docusate,21600535,82003 +A06AB02,BISACODYL,908464,magnesium carbonate,21600539,29155 +A06AB02,BISACODYL,924939,Bisacodyl,21600539,1596 +A06AB02,BISACODYL,939506,Sodium Bicarbonate,21600539,36676 +A06AB02,BISACODYL,939871,sodium phosphate,21600539,36709 +A06AB02,BISACODYL,950435,Citric Acid,21600539,21183 +A06AB02,BISACODYL,967823,Sodium Chloride,21600539,9863 +A06AB02,BISACODYL,976545,potassium citrate,21600539,54993 +A06AB02,BISACODYL,986417,POLYETHYLENE GLYCOL 3350,21600539,221147 +A06AB02,BISACODYL,990499,"Sodium Phosphate, Monobasic",21600539,235496 +A06AB02,BISACODYL,19049105,Potassium Chloride,21600539,8591 +A06AB03,DANTRON,19086560,danthron,21600540,22293 +A06AB04,PHENOLPHTHALEIN,914085,Yellow phenolphthalein,21600541,314784 +A06AB04,PHENOLPHTHALEIN,924309,Phenolphthalein,21600541,155122 +A06AB04,PHENOLPHTHALEIN,941258,Docusate,21600541,82003 +A06AB05,CASTOR OIL,950933,Castor Oil,21600542,2129 +A06AB06,SENNA GLYCOSIDES,938268,Sennosides,21600543,36387 +A06AB06,SENNA GLYCOSIDES,960820,Senna Leaf Extract,21600543,485853 +A06AB06,SENNA GLYCOSIDES,966346,Senna Extract,21600543,9658 +A06AB06,SENNA GLYCOSIDES,19086491,standardized senna concentrate,21600543,221166 +A06AB07,CASCARA,900017,Cascara sagrada,21600544,66869 +A06AB53,"DANTRON, COMBINATIONS",941258,Docusate,21600550,82003 +A06AB53,"DANTRON, COMBINATIONS",19086560,danthron,21600550,22293 +A06AB56,"SENNA GLYCOSIDES, COMBINATIONS",938268,Sennosides,21600551,36387 +A06AB56,"SENNA GLYCOSIDES, COMBINATIONS",941258,Docusate,21600551,82003 +A06AB56,"SENNA GLYCOSIDES, COMBINATIONS",966346,Senna Extract,21600551,9658 +A06AB56,"SENNA GLYCOSIDES, COMBINATIONS",19094011,Prune preparation,21600551,340262 +A06AB57,"CASCARA, COMBINATIONS",900017,Cascara sagrada,21600552,66869 +A06AB57,"CASCARA, COMBINATIONS",900093,Casanthranol,21600552,66870 +A06AB57,"CASCARA, COMBINATIONS",941258,Docusate,21600552,82003 +A06AB57,"CASCARA, COMBINATIONS",960900,Aloe Extract,21600552,91263 +A06AC,BULK PRODUCERS,986517,Cellulose,21600554,2221 +A06AC,BULK PRODUCERS,990337,Malt extract,21600554,235375 +A06AC,BULK PRODUCERS,1000979,guar gum,21600554,26344 +A06AC,BULK PRODUCERS,1037015,Bran,21600554,104125 +A06AC01,ISPAGHULA (PSYLLA SEEDS),957797,Psyllium,21600555,8928 +A06AC01,ISPAGHULA (PSYLLA SEEDS),975125,Hydrocortisone,21600555,5492 +A06AC01,ISPAGHULA (PSYLLA SEEDS),989878,Lidocaine,21600555,6387 +A06AC01,ISPAGHULA (PSYLLA SEEDS),19132965,Plantago Seed,21600555,82088 +A06AC05,LINSEED,1315342,Flaxseed extract,21600558,318224 +A06AC05,LINSEED,19090767,Linseed Oil,21600558,6404 +A06AC06,METHYLCELLULOSE,905371,Methylcellulose,21600559,6873 +A06AC08,POLYCARBOPHIL CALCIUM,940426,calcium polycarbophil,21600561,20063 +A06AC51,"ISPAGHULA, COMBINATIONS",938268,Sennosides,21600562,36387 +A06AC51,"ISPAGHULA, COMBINATIONS",957797,Psyllium,21600562,8928 +A06AC51,"ISPAGHULA, COMBINATIONS",19035704,Calcium Carbonate,21600562,1897 +A06AD02,MAGNESIUM OXIDE,993631,Magnesium Oxide,21600567,6582 +A06AD04,MAGNESIUM SULFATE,19093848,Magnesium Sulfate,21600569,6585 +A06AD11,LACTULOSE,987245,Lactulose,21600571,6218 +A06AD17,SODIUM PHOSPHATE,990499,"Sodium Phosphate, Monobasic",21600577,235496 +A06AD17,SODIUM PHOSPHATE,991710,"Sodium Phosphate, Dibasic",21600577,236719 +A06AG01,SODIUM PHOSPHATE,990499,"Sodium Phosphate, Monobasic",21600584,235496 +A06AG01,SODIUM PHOSPHATE,991710,"Sodium Phosphate, Dibasic",21600584,236719 +A06AG02,BISACODYL,924939,Bisacodyl,21600585,1596 +A06AG04,GLYCEROL,961145,Glycerin,21600587,4910 +A06AG10,"DOCUSATE SODIUM, INCL. COMBINATIONS",917006,Benzocaine,21600590,1399 +A06AG10,"DOCUSATE SODIUM, INCL. COMBINATIONS",941258,Docusate,21600590,82003 +A06AH01,METHYLNALTREXONE BROMIDE,909841,methylnaltrexone,21600594,29899 +A06AH02,ALVIMOPAN,19059654,alvimopan,21600595,480639 +A06AX01,GLYCEROL,961145,Glycerin,21600597,4910 +A06AX03,LUBIPROSTONE,987366,lubiprostone,21600599,623033 +A07AA02,NYSTATIN,922570,Nystatin,21600604,7597 +A07AA06,PAROMOMYCIN,1727443,Paromomycin,21600608,7934 +A07AA08,KANAMYCIN,1784749,Kanamycin,21600610,6099 +A07AA09,VANCOMYCIN,1707687,Vancomycin,21600611,11124 +A07AA11,RIFAXIMIN,1735947,rifaximin,21600613,35619 +A07BA01,MEDICINAL CHARCOAL,1701928,Activated Charcoal,21600629,272 +A07BA51,"MEDICINAL CHARCOAL, COMBINATIONS",966991,Simethicone,21600630,9796 +A07BA51,"MEDICINAL CHARCOAL, COMBINATIONS",1701928,Activated Charcoal,21600630,272 +A07BB,BISMUTH PREPARATIONS,937725,bismuth subgallate,21600631,19476 +A07BB,BISMUTH PREPARATIONS,937791,bismuth subsalicylate,21600631,19478 +A07BB,BISMUTH PREPARATIONS,1707164,Metronidazole,21600631,6922 +A07BB,BISMUTH PREPARATIONS,1836948,Tetracycline,21600631,10395 +A07BC01,PECTIN,922191,pectin,21600633,32987 +A07BC04,ATTAPULGITE,933794,attapulgite,21600636,18516 +A07BC54,"ATTAPULGITE, COMBINATIONS",922191,pectin,21600639,32987 +A07BC54,"ATTAPULGITE, COMBINATIONS",933794,attapulgite,21600639,18516 +A07DA,ANTIPROPULSIVES,914335,Atropine,21600643,1223 +A07DA,ANTIPROPULSIVES,922024,paregoric,21600643,32926 +A07DA,ANTIPROPULSIVES,989567,difenoxin,21600643,23024 +A07DA01,DIPHENOXYLATE,914335,Atropine,21600644,1223 +A07DA01,DIPHENOXYLATE,930916,Diphenoxylate,21600644,3500 +A07DA02,OPIUM,923829,Opium,21600645,7676 +A07DA02,OPIUM,1116109,Belladonna Alkaloids,21600645,1359 +A07DA03,LOPERAMIDE,991876,Loperamide,21600646,6468 +A07DA53,"LOPERAMIDE, COMBINATIONS",966991,Simethicone,21600650,9796 +A07DA53,"LOPERAMIDE, COMBINATIONS",991876,Loperamide,21600650,6468 +A07EA02,HYDROCORTISONE,975125,Hydrocortisone,21600654,5492 +A07EA06,BUDESONIDE,939259,Budesonide,21600658,19831 +A07EB01,CROMOGLICIC ACID,1152631,Cromolyn,21600661,42612 +A07EC01,SULFASALAZINE,964339,Sulfasalazine,21600663,9524 +A07EC02,MESALAZINE,968426,mesalamine,21600664,52582 +A07EC03,OLSALAZINE,916282,olsalazine,21600665,32385 +A07EC04,BALSALAZIDE,934262,balsalazide,21600666,18747 +A07FA01,LACTIC ACID PRODUCING ORGANISMS,987153,Lactobacillus acidophilus,21600669,6205 +A07FA01,LACTIC ACID PRODUCING ORGANISMS,19136097,Bifidobacterium Infantis,21600669,100213 +A07FA02,SACCHAROMYCES BOULARDII,991855,Saccharomyces boulardii,21600670,236782 +A07FA51,"LACTIC ACID PRODUCING ORGANISMS, COMBINATIONS",987153,Lactobacillus acidophilus,21600671,6205 +A07FA51,"LACTIC ACID PRODUCING ORGANISMS, COMBINATIONS",19056614,Lactobacillus bifidus,21600671,236855 +A08AA,CENTRALLY ACTING ANTIOBESITY PRODUCTS,719128,Benzphetamine,21600681,1422 +A08AA,CENTRALLY ACTING ANTIOBESITY PRODUCTS,723344,phendimetrazine,21600681,33272 +A08AA01,PHENTERMINE,735340,Phentermine,21600682,8152 +A08AA02,FENFLURAMINE,753860,Fenfluramine,21600683,4328 +A08AA03,AMFEPRAMONE,725822,Diethylpropion,21600684,3389 +A08AA04,DEXFENFLURAMINE,719057,Dexfenfluramine,21600685,3268 +A08AA05,MAZINDOL,794229,Mazindol,21600686,6664 +A08AA10,SIBUTRAMINE,739363,sibutramine,21600691,36514 +A08AB,PERIPHERALLY ACTING ANTIOBESITY PRODUCTS,1378790,HOODIA GORDONII EXTRACT,21600693,578315 +A08AB01,ORLISTAT,741530,orlistat,21600694,37925 +A09AA,ENZYME PREPARATIONS,919204,Amylases,21600699,743 +A09AA,ENZYME PREPARATIONS,931973,Endopeptidases,21600699,8031 +A09AA,ENZYME PREPARATIONS,950183,Lactase,21600699,41397 +A09AA,ENZYME PREPARATIONS,990760,Lipase,21600699,6406 +A09AA,ENZYME PREPARATIONS,19030387,Bromelains,21600699,1752 +A09AA,ENZYME PREPARATIONS,19066564,"ENZYMES,DIGESTIVE (PLANT)",21600699,259374 +A09AA02,"MULTIENZYMES (LIPASE, PROTEASE ETC)",919204,Amylases,21600701,743 +A09AA02,"MULTIENZYMES (LIPASE, PROTEASE ETC)",926487,Pancreatin,21600701,7880 +A09AA02,"MULTIENZYMES (LIPASE, PROTEASE ETC)",931973,Endopeptidases,21600701,8031 +A09AA02,"MULTIENZYMES (LIPASE, PROTEASE ETC)",990760,Lipase,21600701,6406 +A09AA04,TILACTASE,950183,Lactase,21600703,41397 +A09AB01,GLUTAMIC ACID HYDROCHLORIDE,911486,Glutamate,21600705,70602 +A09AB02,BETAINE HYDROCHLORIDE,1520218,Betaine,21600706,1512 +A09AB03,HYDROCHLORIC ACID,974140,Hydrochloric Acid,21600707,5486 +A09AC,"ENZYME AND ACID PREPARATIONS, COMBINATIONS",931973,Endopeptidases,21600709,8031 +A09AC,"ENZYME AND ACID PREPARATIONS, COMBINATIONS",1520218,Betaine,21600709,1512 +A10AB01,INSULIN (HUMAN),1596977,"Regular Insulin, Human",21600715,253182 +A10AB02,INSULIN (BEEF),19013951,"Insulin, Regular, Beef",21600716,314686 +A10AB03,INSULIN (PORK),1586346,"Insulin, Regular, Pork",21600717,221109 +A10AB04,INSULIN LISPRO,1550023,Insulin Lispro,21600718,86009 +A10AB05,INSULIN ASPART,1567198,"Insulin, Aspart, Human",21600719,51428 +A10AB06,INSULIN GLULISINE,1544838,"Insulin, Glulisine, Human",21600720,400008 +A10AB30,COMBINATIONS,1590165,"Insulin, Regular, Beef-Pork",21600721,235275 +A10AC01,INSULIN (HUMAN),1596914,"NPH Insulin, Human",21600723,253181 +A10AC02,INSULIN (BEEF),19014950,"NPH Insulin, Beef",21600724,317235 +A10AC02,INSULIN (BEEF),19090180,"insulin, protamine zinc, beef",21600724,235278 +A10AC03,INSULIN (PORK),1586326,"NPH Insulin, Pork",21600725,221108 +A10AC30,COMBINATIONS,1515106,"NPH Insulin, Beef-Pork",21600727,317598 +A10AC30,COMBINATIONS,19013926,"Insulin, Protamine Zinc, Beef-Pork",21600727,314685 +A10AD01,INSULIN (HUMAN),1596914,"NPH Insulin, Human",21600729,253181 +A10AD01,INSULIN (HUMAN),1596977,"Regular Insulin, Human",21600729,253182 +A10AD03,INSULIN (PORK),1586326,"NPH Insulin, Pork",21600731,221108 +A10AD04,INSULIN LISPRO,1513876,"Insulin, Protamine Lispro, Human",21600732,314684 +A10AD04,INSULIN LISPRO,1550023,Insulin Lispro,21600732,86009 +A10AD05,INSULIN ASPART,1531601,"Insulin, Aspart Protamine, Human",21600733,352385 +A10AD05,INSULIN ASPART,1567198,"Insulin, Aspart, Human",21600733,51428 +A10AE01,INSULIN (HUMAN),1513849,"Insulin, Zinc, Human",21600736,314683 +A10AE01,INSULIN (HUMAN),1586369,"Ultralente Insulin, Human",21600736,221110 +A10AE02,INSULIN (BEEF),19090204,"Lente Insulin, Beef",21600737,235280 +A10AE03,INSULIN (PORK),1562586,"Insulin, Zinc, Pork",21600738,93108 +A10AE04,INSULIN GLARGINE,1502905,Insulin Glargine,21600739,274783 +A10AE05,INSULIN DETEMIR,1516976,insulin detemir,21600740,139825 +A10AE30,COMBINATIONS,1513843,"Lente Insulin, Beef-Pork",21600741,314682 +A10AE30,COMBINATIONS,19090221,"Ultralente Insulin, Beef-Pork",21600741,235281 +A10AE30,COMBINATIONS,19090229,"Insulin, Prompt Zinc, Beef-Pork",21600741,235283 +A10BA02,METFORMIN,1503297,Metformin,21600747,6809 +A10BB01,GLIBENCLAMIDE,1559684,Glyburide,21600750,4815 +A10BB02,CHLORPROPAMIDE,1594973,Chlorpropamide,21600751,2404 +A10BB03,TOLBUTAMIDE,1502855,Tolbutamide,21600752,10635 +A10BB05,TOLAZAMIDE,1502809,Tolazamide,21600754,10633 +A10BB07,GLIPIZIDE,1560171,Glipizide,21600756,4821 +A10BB12,GLIMEPIRIDE,1597756,glimepiride,21600761,25789 +A10BB31,ACETOHEXAMIDE,1530014,Acetohexamide,21600762,173 +A10BD,COMBINATIONS OF ORAL BLOOD GLUCOSE LOWERING DRUGS,1503297,Metformin,21600765,6809 +A10BD,COMBINATIONS OF ORAL BLOOD GLUCOSE LOWERING DRUGS,1516766,repaglinide,21600765,73044 +A10BD02,METFORMIN AND SULFONAMIDES,1503297,Metformin,21600767,6809 +A10BD02,METFORMIN AND SULFONAMIDES,1559684,Glyburide,21600767,4815 +A10BD02,METFORMIN AND SULFONAMIDES,1560171,Glipizide,21600767,4821 +A10BD03,METFORMIN AND ROSIGLITAZONE,1503297,Metformin,21600768,6809 +A10BD03,METFORMIN AND ROSIGLITAZONE,1547504,rosiglitazone,21600768,84108 +A10BD04,GLIMEPIRIDE AND ROSIGLITAZONE,1547504,rosiglitazone,21600769,84108 +A10BD04,GLIMEPIRIDE AND ROSIGLITAZONE,1597756,glimepiride,21600769,25789 +A10BD05,METFORMIN AND PIOGLITAZONE,1503297,Metformin,21600770,6809 +A10BD05,METFORMIN AND PIOGLITAZONE,1525215,pioglitazone,21600770,33738 +A10BD06,GLIMEPIRIDE AND PIOGLITAZONE,1525215,pioglitazone,21600771,33738 +A10BD06,GLIMEPIRIDE AND PIOGLITAZONE,1597756,glimepiride,21600771,25789 +A10BD07,METFORMIN AND SITAGLIPTIN,1503297,Metformin,21600772,6809 +A10BD07,METFORMIN AND SITAGLIPTIN,1580747,sitagliptin,21600772,593411 +A10BF01,ACARBOSE,1529331,Acarbose,21600776,16681 +A10BF02,MIGLITOL,1510202,miglitol,21600777,30009 +A10BG01,TROGLITAZONE,1515249,troglitazone,21600780,72610 +A10BG02,ROSIGLITAZONE,1547504,rosiglitazone,21600781,84108 +A10BG03,PIOGLITAZONE,1525215,pioglitazone,21600782,33738 +A10BH01,SITAGLIPTIN,1580747,sitagliptin,21600784,593411 +A10BX02,REPAGLINIDE,1516766,repaglinide,21600790,73044 +A10BX03,NATEGLINIDE,1502826,nateglinide,21600791,274332 +A10BX04,EXENATIDE,1583722,exenatide,21600792,60548 +A10BX05,PRAMLINTIDE,1517998,Pramlintide,21600793,139953 +A11AA,MULTIVITAMINS WITH MINERALS,1195334,Choline,21600802,2449 +A11AA,MULTIVITAMINS WITH MINERALS,1379525,Inositol,21600802,5833 +A11CA01,RETINOL (VIT A),19008339,Vitamin A,21600812,11246 +A11CA02,BETACAROTENE,19037223,Beta Carotene,21600813,19143 +A11CB,VITAMIN A AND D IN COMBINATION,19008339,Vitamin A,21600814,11246 +A11CB,VITAMIN A AND D IN COMBINATION,19045045,Ergocalciferol,21600814,4018 +A11CB,VITAMIN A AND D IN COMBINATION,19095164,Cholecalciferol,21600814,2418 +A11CC01,ERGOCALCIFEROL,19045045,Ergocalciferol,21600816,4018 +A11CC02,DIHYDROTACHYSTEROL,19027015,Dihydrotachysterol,21600817,3429 +A11CC04,CALCITRIOL,19035631,Calcitriol,21600819,1894 +A11CC05,COLECALCIFEROL,19038464,soy protein isolate,21600820,196238 +A11CC05,COLECALCIFEROL,19095164,Cholecalciferol,21600820,2418 +A11CC06,CALCIFEDIOL,19035569,Calcifediol,21600821,1889 +A11DA01,THIAMINE (VIT B1),19137312,Thiamine,21600825,10454 +A11EB,VITAMIN B-COMPLEX WITH VITAMIN C,1387426,Folate,21600831,62356 +A11EB,VITAMIN B-COMPLEX WITH VITAMIN C,19010970,Vitamin B Complex,21600831,11251 +A11EB,VITAMIN B-COMPLEX WITH VITAMIN C,19035704,Calcium Carbonate,21600831,1897 +A11GA01,ASCORBIC ACID (VIT C),19011773,Ascorbic Acid,21600837,1151 +A11GB,"ASCORBIC ACID (VITAMIN C), COMBINATIONS",922191,pectin,21600838,32987 +A11GB,"ASCORBIC ACID (VITAMIN C), COMBINATIONS",1389112,Echinacea Preparation,21600838,228041 +A11GB,"ASCORBIC ACID (VITAMIN C), COMBINATIONS",1399063,Echinacea purpurea extract,21600838,260025 +A11GB,"ASCORBIC ACID (VITAMIN C), COMBINATIONS",19010696,Zinc,21600838,11416 +A11GB,"ASCORBIC ACID (VITAMIN C), COMBINATIONS",19011773,Ascorbic Acid,21600838,1151 +A11GB,"ASCORBIC ACID (VITAMIN C), COMBINATIONS",19024669,Bioflavonoids,21600838,1562 +A11GB,"ASCORBIC ACID (VITAMIN C), COMBINATIONS",19055756,"BIOFLAVONOID, LEMON",21600838,236117 +A11GB,"ASCORBIC ACID (VITAMIN C), COMBINATIONS",19079204,Zinc Gluconate,21600838,58300 +A11GB,"ASCORBIC ACID (VITAMIN C), COMBINATIONS",19112632,"COLLAGEN, HYDROLYZED",21600838,477454 +A11HA,OTHER PLAIN VITAMIN PREPARATIONS,1308185,lycopene,21600841,29008 +A11HA,OTHER PLAIN VITAMIN PREPARATIONS,19018384,4-Aminobenzoic Acid,21600841,74 +A11HA,OTHER PLAIN VITAMIN PREPARATIONS,19087067,4-Aminobenzoate,21600841,618974 +A11HA01,NICOTINAMIDE,19018419,Niacinamide,21600842,7405 +A11HA02,PYRIDOXINE (VIT B6),1353228,Vitamin B6,21600843,42954 +A11HA03,TOCOPHEROL (VIT E),19009540,Vitamin E,21600844,11256 +A11HA03,TOCOPHEROL (VIT E),19014164,Wheat germ oil,21600844,72385 +A11HA04,RIBOFLAVIN (VIT B2),19056500,Flavin Mononucleotide,21600845,4509 +A11HA04,RIBOFLAVIN (VIT B2),19062817,Riboflavin,21600845,9346 +A11HA05,BIOTIN,19024770,Biotin,21600846,1588 +A11HA05,BIOTIN,19035704,Calcium Carbonate,21600846,1897 +A11HA05,BIOTIN,19080550,CHROMIUM PICOLINATE,21600846,59308 +A11HA06,PYRIDOXAL PHOSPHATE,19059817,Pyridoxal,21600847,9002 +A11HA07,INOSITOL,1379525,Inositol,21600848,5833 +A11HA08,TOCOFERSOLAN,19018322,tocophersolan,21600849,159151 +A11HA31,CALCIUM PANTOTHENATE,19026739,Pantothenic Acid,21600851,7891 +A11HA31,CALCIUM PANTOTHENATE,19088079,pantothenate,21600851,62400 +A11JA,COMBINATIONS OF VITAMINS,1195334,Choline,21600854,2449 +A11JA,COMBINATIONS OF VITAMINS,1308738,Vitamin B 12,21600854,11248 +A11JA,COMBINATIONS OF VITAMINS,1353228,Vitamin B6,21600854,42954 +A11JA,COMBINATIONS OF VITAMINS,19008339,Vitamin A,21600854,11246 +A11JA,COMBINATIONS OF VITAMINS,19009405,Vitamin D,21600854,11253 +A11JA,COMBINATIONS OF VITAMINS,19009540,Vitamin E,21600854,11256 +A11JA,COMBINATIONS OF VITAMINS,19011773,Ascorbic Acid,21600854,1151 +A11JA,COMBINATIONS OF VITAMINS,19026739,Pantothenic Acid,21600854,7891 +A11JA,COMBINATIONS OF VITAMINS,19037223,Beta Carotene,21600854,19143 +A11JA,COMBINATIONS OF VITAMINS,19062817,Riboflavin,21600854,9346 +A11JA,COMBINATIONS OF VITAMINS,19137312,Thiamine,21600854,10454 +A11JB,VITAMINS WITH MINERALS,1308738,Vitamin B 12,21600855,11248 +A11JB,VITAMINS WITH MINERALS,1353228,Vitamin B6,21600855,42954 +A11JB,VITAMINS WITH MINERALS,19010696,Zinc,21600855,11416 +A11JB,VITAMINS WITH MINERALS,19011773,Ascorbic Acid,21600855,1151 +A11JB,VITAMINS WITH MINERALS,19079390,ZINC PICOLINATE,21600855,58301 +A11JB,VITAMINS WITH MINERALS,19080550,CHROMIUM PICOLINATE,21600855,59308 +A11JB,VITAMINS WITH MINERALS,19095164,Cholecalciferol,21600855,2418 +A11JB,VITAMINS WITH MINERALS,19106287,Vitamin K 2,21600855,42781 +A11JC,"VITAMINS, OTHER COMBINATIONS",1195334,Choline,21600856,2449 +A11JC,"VITAMINS, OTHER COMBINATIONS",1308185,lycopene,21600856,29008 +A11JC,"VITAMINS, OTHER COMBINATIONS",1308738,Vitamin B 12,21600856,11248 +A11JC,"VITAMINS, OTHER COMBINATIONS",1310353,Lutein,21600856,11359 +A11JC,"VITAMINS, OTHER COMBINATIONS",1353228,Vitamin B6,21600856,42954 +A11JC,"VITAMINS, OTHER COMBINATIONS",1391889,Ginkgo biloba extract,21600856,236809 +A11JC,"VITAMINS, OTHER COMBINATIONS",19007600,Soybean preparation,21600856,287515 +A11JC,"VITAMINS, OTHER COMBINATIONS",19009540,Vitamin E,21600856,11256 +A11JC,"VITAMINS, OTHER COMBINATIONS",19011773,Ascorbic Acid,21600856,1151 +A11JC,"VITAMINS, OTHER COMBINATIONS",19035704,Calcium Carbonate,21600856,1897 +A11JC,"VITAMINS, OTHER COMBINATIONS",19095164,Cholecalciferol,21600856,2418 +A12AA,CALCIUM,19018602,Calcium Glucarate,21600859,1907 +A12AA,CALCIUM,19058572,Calcium Citrate,21600859,47613 +A12AA01,CALCIUM PHOSPHATE,19037401,calcium phosphate,21600860,1919 +A12AA02,CALCIUM GLUBIONATE,19097867,glubionate calcium,21600861,25806 +A12AA03,CALCIUM GLUCONATE,1560524,Glucose,21600862,4850 +A12AA03,CALCIUM GLUCONATE,19037038,Calcium Gluconate,21600862,1908 +A12AA04,CALCIUM CARBONATE,1516800,Risedronate,21600863,73056 +A12AA04,CALCIUM CARBONATE,19035704,Calcium Carbonate,21600863,1897 +A12AA05,CALCIUM LACTATE,19058896,calcium lactate,21600864,47622 +A12AA10,CALCIUM GLUCOHEPTONATE,19058867,Calcium gluceptate,21600869,47618 +A12AA11,CALCIUM PANGAMATE,19091973,pangamate,21600870,646818 +A12AA12,CALCIUM ACETATE ANHYDROUS,951469,calcium acetate,21600871,214342 +A12AA20,CALCIUM (DIFFERENT SALTS IN COMBINATION),1337159,Calcium Glycerophosphate,21600872,1909 +A12AA20,CALCIUM (DIFFERENT SALTS IN COMBINATION),19058896,calcium lactate,21600872,47622 +A12AA20,CALCIUM (DIFFERENT SALTS IN COMBINATION),19058971,CALCIUM LEVULINATE,21600872,47624 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",911486,Glutamate,21600874,70602 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",967861,magnesium citrate,21600874,52356 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",993631,Magnesium Oxide,21600874,6582 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",1391642,Chaste tree preparation,21600874,236664 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",1595799,Ferrous fumarate,21600874,24941 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19007600,Soybean preparation,21600874,287515 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19009405,Vitamin D,21600874,11253 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19010696,Zinc,21600874,11416 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19019904,Docosahexanoic acid,21600874,144450 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19029824,Boron,21600874,1705 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19035704,Calcium Carbonate,21600874,1897 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19037401,calcium phosphate,21600874,1919 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19038464,soy protein isolate,21600874,196238 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19044727,Vitamin K 1,21600874,8308 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19045045,Ergocalciferol,21600874,4018 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19058348,Gamboge,21600874,89698 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19058572,Calcium Citrate,21600874,47613 +A12AX,"CALCIUM, COMBINATIONS WITH OTHER DRUGS",19095164,Cholecalciferol,21600874,2418 +A12BA,POTASSIUM,19027080,potassium bicarbonate,21600876,34296 +A12BA,POTASSIUM,19049024,Potassium,21600876,8588 +A12BA01,POTASSIUM CHLORIDE,19049105,Potassium Chloride,21600877,8591 +A12BA02,POTASSIUM CITRATE,950435,Citric Acid,21600878,21183 +A12BA02,POTASSIUM CITRATE,976545,potassium citrate,21600878,54993 +A12BA05,POTASSIUM GLUCONATE,19059547,Potassium gluconate,21600881,89903 +A12BA51,"POTASSIUM CHLORIDE, COMBINATIONS",19019131,Magnesium Aspartate,21600883,142131 +A12CA01,SODIUM CHLORIDE,967823,Sodium Chloride,21600886,9863 +A12CB,ZINC,979096,Zinc Acetate,21600888,58295 +A12CB,ZINC,1135766,Phenylephrine,21600888,8163 +A12CB,ZINC,1140640,carbetapentane,21600888,20217 +A12CB,ZINC,1154332,Pseudoephedrine,21600888,8896 +A12CB,ZINC,1158632,Methscopolamine,21600888,89785 +A12CB,ZINC,1163944,Guaifenesin,21600888,5032 +A12CB,ZINC,1192710,Chlorpheniramine,21600888,2400 +A12CB,ZINC,19010696,Zinc,21600888,11416 +A12CB,ZINC,19079390,ZINC PICOLINATE,21600888,58301 +A12CB01,ZINC SULFATE,19044522,Zinc Sulfate,21600889,39954 +A12CB02,ZINC GLUCONATE,19079204,Zinc Gluconate,21600890,58300 +A12CC,MAGNESIUM,19059006,Magnesium glycinate,21600892,476818 +A12CC,MAGNESIUM,19060896,magnesium amino acid chelate,21600892,486895 +A12CC01,MAGNESIUM CHLORIDE,19092849,Magnesium Chloride,21600893,6579 +A12CC02,MAGNESIUM SULFATE,19093848,Magnesium Sulfate,21600894,6585 +A12CC03,MAGNESIUM GLUCONATE,19067971,MAGNESIUM GLUCONATE,21600895,52358 +A12CC06,MAGNESIUM LACTATE,19051926,Magnesium lactate,21600898,214688 +A12CC10,MAGNESIUM OXIDE,993631,Magnesium Oxide,21600902,6582 +A12CC30,MAGNESIUM (DIFFERENT SALTS IN COMBINATION),19019131,Magnesium Aspartate,21600903,142131 +A12CE,SELENIUM,19038024,Selenious Acid,21600908,36344 +A12CX,OTHER MINERAL PRODUCTS,1359148,Echinacea Root Extract,21600911,477379 +A12CX,OTHER MINERAL PRODUCTS,19004810,Copper Gluconate,21600911,2839 +A12CX,OTHER MINERAL PRODUCTS,19008893,manganese chloride,21600911,29261 +A12CX,OTHER MINERAL PRODUCTS,19008897,manganese sulfate,21600911,29268 +A12CX,OTHER MINERAL PRODUCTS,19009896,Molybdenum,21600911,7024 +A12CX,OTHER MINERAL PRODUCTS,19010696,Zinc,21600911,11416 +A12CX,OTHER MINERAL PRODUCTS,19029824,Boron,21600911,1705 +A12CX,OTHER MINERAL PRODUCTS,19038433,bone meal,21600911,19596 +A12CX,OTHER MINERAL PRODUCTS,19043266,vanadyl sulfate,21600911,39364 +A12CX,OTHER MINERAL PRODUCTS,19049877,chromic chloride,21600911,21009 +A12CX,OTHER MINERAL PRODUCTS,19057346,Copper Sulfate,21600911,21579 +A12CX,OTHER MINERAL PRODUCTS,19059405,Germanium,21600911,4784 +A12CX,OTHER MINERAL PRODUCTS,19073031,cupric chloride,21600911,21833 +A12CX,OTHER MINERAL PRODUCTS,19079390,ZINC PICOLINATE,21600911,58301 +A12CX,OTHER MINERAL PRODUCTS,19080550,CHROMIUM PICOLINATE,21600911,59308 +A12CX,OTHER MINERAL PRODUCTS,19082847,BORON CITRATE,21600911,324014 +A12CX,OTHER MINERAL PRODUCTS,19127669,Lithium Aspartate,21600911,746070 +A13A,TONICS,1398499,Hops extract,21600913,259266 +A13A,TONICS,19006410,Arginine,21600913,1091 +A13A,TONICS,19010128,Vitamin K,21600913,11258 +A13A,TONICS,19012197,Berberine,21600913,1437 +A13A,TONICS,19035704,Calcium Carbonate,21600913,1897 +A13A,TONICS,19082762,Maca preparation,21600913,319839 +A13A,TONICS,19095164,Cholecalciferol,21600913,2418 +A14AA02,STANOZOLOL,1636145,Stanozolol,21600918,10032 +A14AA05,OXYMETHOLONE,1525741,Oxymetholone,21600921,7813 +A14AA07,PRASTERONE,1312007,dehydroepiandrosterone,21600923,3143 +A14AA07,PRASTERONE,19035704,Calcium Carbonate,21600923,1897 +A14AA07,PRASTERONE,19037401,calcium phosphate,21600923,1919 +A14AA08,OXANDROLONE,1524769,Oxandrolone,21600924,7779 +A14AB01,NANDROLONE,1514412,Nandrolone,21600927,7244 +A14AB02,ETHYLESTRENOL,19050387,Ethylestrenol,21600928,4162 +A15,APPETITE STIMULANTS,1300978,Megestrol,21600931,6703 +A16AA,AMINO ACIDS AND DERIVATIVES,962398,Glycine,21600934,4919 +A16AA,AMINO ACIDS AND DERIVATIVES,1139042,Acetylcysteine,21600934,197 +A16AA,AMINO ACIDS AND DERIVATIVES,19000537,Threonine,21600934,10524 +A16AA,AMINO ACIDS AND DERIVATIVES,19007572,Valine,21600934,11115 +A16AA,AMINO ACIDS AND DERIVATIVES,19012686,Aspartic Acid,21600934,1169 +A16AA,AMINO ACIDS AND DERIVATIVES,19069149,Histidine,21600934,5340 +A16AA,AMINO ACIDS AND DERIVATIVES,19082306,Isoleucine,21600934,6033 +A16AA,AMINO ACIDS AND DERIVATIVES,19136716,Taurine,21600934,10337 +A16AA01,LEVOCARNITINE,1553610,Levocarnitine,21600935,42955 +A16AA03,GLUTAMINE,19060985,Glutamine,21600937,4885 +A16AB01,ALGLUCERASE,19057354,alglucerase,21600942,46049 +A16AB02,IMIGLUCERASE,1348407,imiglucerase,21600943,84959 +A16AB04,AGALSIDASE BETA,1525746,agalsidase beta,21600945,338817 +A16AB05,LARONIDASE,1543229,Laronidase,21600946,392509 +A16AB06,SACROSIDASE,951980,Sacrosidase,21600947,214817 +A16AB07,ALGLUCOSIDASE ALFA,19088328,alglucosidase alfa,21600948,629565 +A16AB08,GALSULFASE,19078649,galsulfase,21600949,578033 +A16AB09,IDURSULFASE,19091430,Idursulfase,21600950,644101 +A16AX,VARIOUS ALIMENTARY TRACT AND METABOLISM PRODUCTS,922191,pectin,21600951,32987 +A16AX,VARIOUS ALIMENTARY TRACT AND METABOLISM PRODUCTS,987128,Lactobacillus,21600951,6204 +A16AX,VARIOUS ALIMENTARY TRACT AND METABOLISM PRODUCTS,987153,Lactobacillus acidophilus,21600951,6205 +A16AX,VARIOUS ALIMENTARY TRACT AND METABOLISM PRODUCTS,988294,dexpanthenol,21600951,22701 +A16AX,VARIOUS ALIMENTARY TRACT AND METABOLISM PRODUCTS,19066563,fructooligosaccharide,21600951,259372 +A16AX01,TIOCTIC ACID,1351115,coenzyme Q10,21600952,21406 +A16AX01,TIOCTIC ACID,1386670,Thioctate,21600952,618060 +A16AX01,TIOCTIC ACID,19009540,Vitamin E,21600952,11256 +A16AX01,TIOCTIC ACID,19037596,Acetylcarnitine,21600952,193 +A16AX01,TIOCTIC ACID,19125750,Chromium Polynicotinate,21600952,700888 +A16AX03,SODIUM PHENYLBUTYRATE,1539954,phenylbutyrate,21600954,81647 +A16AX04,NITISINONE,1586640,nitisinone,21600955,61805 +A16AX06,MIGLUSTAT,19045272,Miglustat,21600957,402316 +A16AX07,SAPROPTERIN,19021959,Sapropterin,21600958,753340 +B01AA,VITAMIN K ANTAGONISTS,1332661,anisindione,21600962,17941 +B01AA01,DICOUMAROL,1325124,Dicumarol,21600963,1598 +B01AA03,WARFARIN,1310149,Warfarin,21600965,11289 +B01AA04,PHENPROCOUMON,19035344,Phenprocoumon,21600966,8150 +B01AB01,HEPARIN,1367571,Heparin,21600973,5224 +B01AB04,DALTEPARIN,1301065,Dalteparin,21600975,67109 +B01AB09,DANAPAROID,19026343,danaparoid,21600980,78484 +B01AB10,TINZAPARIN,1308473,tinzaparin,21600981,69646 +B01AC04,CLOPIDOGREL,1322184,clopidogrel,21600989,32968 +B01AC05,TICLOPIDINE,1302398,Ticlopidine,21600990,10594 +B01AC06,ACETYLSALICYLIC ACID,1112807,Aspirin,21600991,1191 +B01AC06,ACETYLSALICYLIC ACID,1551860,Pravastatin,21600991,42463 +B01AC07,DIPYRIDAMOLE,1331270,Dipyridamole,21600992,3521 +B01AC09,EPOPROSTENOL,1354118,Epoprostenol,21600994,8814 +B01AC11,ILOPROST,1344992,Iloprost,21600996,40138 +B01AC13,ABCIXIMAB,19047423,abciximab,21600997,83929 +B01AC16,EPTIFIBATIDE,1322199,eptifibatide,21600999,75635 +B01AC17,TIROFIBAN,19017067,tirofiban,21601000,73137 +B01AC21,TREPROSTINIL,1327256,Treprostinil,21601003,343048 +B01AC30,COMBINATIONS,1112807,Aspirin,21601005,1191 +B01AC30,COMBINATIONS,1331270,Dipyridamole,21601005,3521 +B01AD01,STREPTOKINASE,19136187,Streptokinase,21601007,10106 +B01AD02,ALTEPLASE,1347450,Alteplase,21601008,8410 +B01AD03,ANISTREPLASE,19044890,Anistreplase,21601009,40028 +B01AD04,UROKINASE,1307515,Urokinase,21601010,11055 +B01AD10,DROTRECOGIN ALFA (ACTIVATED),1731597,drotrecogin alfa,21601016,352374 +B01AD12,PROTEIN C,19014221,Protein C Concentrate (Human),21601018,723868 +B01AE02,LEPIRUDIN,19092139,lepirudin,21601021,237057 +B01AE03,ARGATROBAN,1322207,argatroban,21601022,15202 +B01AE06,BIVALRUDIN,19084670,bivalirudin,21601025,60819 +B01AX05,FONDAPARINUX,1315865,fondaparinux,21601030,321208 +B02AA01,AMINOCAPROIC ACID,1369939,6-Aminocaproic Acid,21601035,99 +B02AA02,TRANEXAMIC ACID,1303425,Tranexamic Acid,21601036,10691 +B02AB01,APROTININ,19000729,Aprotinin,21601039,1056 +B02AB02,ALFA1 ANTITRYPSIN,1169352,alpha 1-Antitrypsin,21601040,535 +B02AB03,C1-INHIBITOR,1333635,C1 inhibitor (Human),0,809864 +B02BA01,PHYTOMENADIONE,19044727,Vitamin K 1,21601045,8308 +B02BA02,MENADIONE,19009057,menadiol,21601046,29491 +B02BC06,THROMBIN,1300673,Thrombin,21601054,10528 +B02BD08,EPTACOG ALFA (ACTIVATED),1391474,"FACTOR VIIA,RECOMB(BHK CELLS)",21601068,236489 +B02BX04,ROMIPLOSTIM,19032407,Romiplostim,21601075,805452 +B02BX05,ELTROMBOPAG,19012346,eltrombopag,21601076,711942 +B03A,IRON PREPARATIONS,1303339,iron succinyl milk protein complex,21601078,27825 +B03A,IRON PREPARATIONS,1305063,FE HEME POLYPEPTIDE,21601078,284110 +B03A,IRON PREPARATIONS,1360067,Iron,21601078,90176 +B03A,IRON PREPARATIONS,1400498,Iron Carbonyl,21601078,262150 +B03A,IRON PREPARATIONS,19135928,Soy protein-iron complex,21601078,91495 +B03AA02,FERROUS FUMARATE,941258,Docusate,21601081,82003 +B03AA02,FERROUS FUMARATE,1521369,Norethindrone,21601081,7514 +B03AA02,FERROUS FUMARATE,1549786,Ethinyl Estradiol,21601081,4124 +B03AA02,FERROUS FUMARATE,1595799,Ferrous fumarate,21601081,24941 +B03AA03,FERROUS GLUCONATE,1396012,ferrous gluconate,21601082,24942 +B03AA07,FERROUS SULFATE,1300751,Polysaccharide iron complex,21601086,105669 +B03AA07,FERROUS SULFATE,1396131,ferrous sulfate,21601086,24947 +B03AA07,FERROUS SULFATE,1400498,Iron Carbonyl,21601086,262150 +B03AA07,FERROUS SULFATE,1595799,Ferrous fumarate,21601086,24941 +B03AA07,FERROUS SULFATE,19011773,Ascorbic Acid,21601086,1151 +B03AB02,SACCHARATED IRON OXIDE,1300751,Polysaccharide iron complex,21601093,105669 +B03AB02,SACCHARATED IRON OXIDE,1377898,Iron polysaccharide,21601093,219315 +B03AC,"IRON TRIVALENT, PARENTERAL PREPARATIONS",19055036,FERROUS CACODYLATE,21601101,235271 +B03AC02,SACCHARATED IRON OXIDE,1395773,"ferric oxide, saccharated",21601103,24909 +B03AC06,FERRIC OXIDE DEXTRAN COMPLEX,1381661,Iron-Dextran Complex,21601106,5992 +B03AC07,FERRIC SODIUM GLUCONATE COMPLEX,1399177,Sodium ferric gluconate complex,21601107,261435 +B03AD,IRON IN COMBINATION WITH FOLIC ACID,1305063,FE HEME POLYPEPTIDE,21601108,284110 +B03AD,IRON IN COMBINATION WITH FOLIC ACID,1360067,Iron,21601108,90176 +B03AD,IRON IN COMBINATION WITH FOLIC ACID,1387426,Folate,21601108,62356 +B03AD02,FERROUS FUMARATE,1387426,Folate,21601110,62356 +B03AD02,FERROUS FUMARATE,1595799,Ferrous fumarate,21601110,24941 +B03AD03,FERROUS SULFATE,1387426,Folate,21601111,62356 +B03AD03,FERROUS SULFATE,1396131,ferrous sulfate,21601111,24947 +B03AE01,"IRON, VITAMIN B12 AND FOLIC ACID",1300751,Polysaccharide iron complex,21601114,105669 +B03AE01,"IRON, VITAMIN B12 AND FOLIC ACID",1308738,Vitamin B 12,21601114,11248 +B03AE01,"IRON, VITAMIN B12 AND FOLIC ACID",1387426,Folate,21601114,62356 +B03AE02,"IRON, MULTIVITAMINS AND FOLIC ACID",1387426,Folate,21601115,62356 +B03AE02,"IRON, MULTIVITAMINS AND FOLIC ACID",1396131,ferrous sulfate,21601115,24947 +B03AE02,"IRON, MULTIVITAMINS AND FOLIC ACID",19011773,Ascorbic Acid,21601115,1151 +B03AE10,VARIOUS COMBINATIONS,941258,Docusate,21601118,82003 +B03AE10,VARIOUS COMBINATIONS,1308738,Vitamin B 12,21601118,11248 +B03AE10,VARIOUS COMBINATIONS,1360067,Iron,21601118,90176 +B03AE10,VARIOUS COMBINATIONS,1387426,Folate,21601118,62356 +B03AE10,VARIOUS COMBINATIONS,1595799,Ferrous fumarate,21601118,24941 +B03AE10,VARIOUS COMBINATIONS,19011773,Ascorbic Acid,21601118,1151 +B03BA,VITAMIN B12 (CYANOCOBALAMIN AND ANALOGUES),1139042,Acetylcysteine,21601120,197 +B03BA,VITAMIN B12 (CYANOCOBALAMIN AND ANALOGUES),19009025,mecobalamin,21601120,29421 +B03BA,VITAMIN B12 (CYANOCOBALAMIN AND ANALOGUES),19048046,L-METHYLFOLATE,21601120,407884 +B03BA,VITAMIN B12 (CYANOCOBALAMIN AND ANALOGUES),19091701,Liver Extract,21601120,6459 +B03BA01,CYANOCOBALAMIN,1308738,Vitamin B 12,21601121,11248 +B03BA03,HYDROXOCOBALAMIN,1377023,Hydroxocobalamin,21601123,5514 +B03BA05,MECOBALAMIN,19009025,mecobalamin,21601125,29421 +B03BA05,MECOBALAMIN,19059817,Pyridoxal,21601125,9002 +B03BA05,MECOBALAMIN,19112915,methylfolic acid,21601125,486456 +B03BA51,"CYANOCOBALAMIN, COMBINATIONS",1308738,Vitamin B 12,21601126,11248 +B03BA51,"CYANOCOBALAMIN, COMBINATIONS",1353228,Vitamin B6,21601126,42954 +B03BA51,"CYANOCOBALAMIN, COMBINATIONS",1380472,Intrinsic factor,21601126,5920 +B03BA51,"CYANOCOBALAMIN, COMBINATIONS",1387426,Folate,21601126,62356 +B03BA51,"CYANOCOBALAMIN, COMBINATIONS",19005046,pyridoxine,21601126,684879 +B03BA51,"CYANOCOBALAMIN, COMBINATIONS",19009025,mecobalamin,21601126,29421 +B03BA51,"CYANOCOBALAMIN, COMBINATIONS",19048026,cobamamide,21601126,21373 +B03BB01,FOLIC ACID,1387426,Folate,21601129,62356 +B03BB01,FOLIC ACID,19048046,L-METHYLFOLATE,21601129,407884 +B03BB51,"FOLIC ACID, COMBINATIONS",1387426,Folate,21601130,62356 +B03BB51,"FOLIC ACID, COMBINATIONS",19011773,Ascorbic Acid,21601130,1151 +B03XA01,ERYTHROPOIETIN,1301125,Epoetin Alfa,21601133,105694 +B03XA02,DARBEPOETIN ALFA,1304643,darbepoetin alfa,21601134,283838 +B05AA01,ALBUMIN,1344143,"Albumin Human, USP",21601139,828529 +B05AA02,OTHER PLASMA PROTEIN FRACTIONS,19025693,plasma protein fraction,21601140,33835 +B05AA05,DEXTRAN,1319156,Dextran 70,21601142,3274 +B05AA05,DEXTRAN,19019122,Dextran 40,21601142,3272 +B05AA05,DEXTRAN,19019193,Dextran 75,21601142,3275 +B05AA05,DEXTRAN,19051646,Dextran 1,21601142,214485 +B05AA07,HYDROXYETHYLSTARCH,19077117,Hetastarch,21601144,5531 +B05BA01,AMINO ACIDS,19010955,Cysteine,21601155,3024 +B05BA02,FAT EMULSIONS,961145,Glycerin,21601156,4910 +B05BA02,FAT EMULSIONS,19013789,EGG YOLK PHOSPHOLIPIDS,21601156,314605 +B05BA02,FAT EMULSIONS,19070224,Soybean Oil,21601156,9949 +B05BA03,CARBOHYDRATES,956691,Fructose,21601157,4570 +B05BA03,CARBOHYDRATES,1560524,Glucose,21601157,4850 +B05BA10,COMBINATIONS,19003107,invert sugar,21601159,27712 +B05BB01,ELECTROLYTES,904826,Lactic acid,21601161,28393 +B05BB01,ELECTROLYTES,967823,Sodium Chloride,21601161,9863 +B05BB01,ELECTROLYTES,19036781,Calcium Chloride,21601161,1901 +B05BB01,ELECTROLYTES,19049105,Potassium Chloride,21601161,8591 +B05BB01,ELECTROLYTES,19092849,Magnesium Chloride,21601161,6579 +B05BB01,ELECTROLYTES,19093848,Magnesium Sulfate,21601161,6585 +B05BB02,ELECTROLYTES WITH CARBOHYDRATES,904826,Lactic acid,21601162,28393 +B05BB02,ELECTROLYTES WITH CARBOHYDRATES,967823,Sodium Chloride,21601162,9863 +B05BB02,ELECTROLYTES WITH CARBOHYDRATES,1560524,Glucose,21601162,4850 +B05BB02,ELECTROLYTES WITH CARBOHYDRATES,19036781,Calcium Chloride,21601162,1901 +B05BB02,ELECTROLYTES WITH CARBOHYDRATES,19049105,Potassium Chloride,21601162,8591 +B05BB03,TROMETAMOL,19006047,Tromethamine,21601163,10865 +B05BC01,MANNITOL,994058,Mannitol,21601165,6628 +B05BC02,CARBAMIDE,906914,Urea,21601166,11002 +B05CA10,COMBINATIONS,915981,Neomycin,21601178,7299 +B05CA10,COMBINATIONS,948582,Polymyxin B,21601178,8536 +B05CB01,SODIUM CHLORIDE,967823,Sodium Chloride,21601180,9863 +B05CB10,COMBINATIONS,904826,Lactic acid,21601184,28393 +B05CB10,COMBINATIONS,967823,Sodium Chloride,21601184,9863 +B05CB10,COMBINATIONS,19036781,Calcium Chloride,21601184,1901 +B05CB10,COMBINATIONS,19049105,Potassium Chloride,21601184,8591 +B05CX,OTHER IRRIGATING SOLUTIONS,904826,Lactic acid,21601185,28393 +B05CX,OTHER IRRIGATING SOLUTIONS,929549,Acetic Acid,21601185,168 +B05CX,OTHER IRRIGATING SOLUTIONS,967823,Sodium Chloride,21601185,9863 +B05CX,OTHER IRRIGATING SOLUTIONS,19036781,Calcium Chloride,21601185,1901 +B05CX,OTHER IRRIGATING SOLUTIONS,19049105,Potassium Chloride,21601185,8591 +B05CX02,SORBITOL,970011,Sorbitol,21601187,9945 +B05CX03,GLYCINE,962398,Glycine,21601188,4919 +B05CX04,MANNITOL,994058,Mannitol,21601189,6628 +B05CX10,COMBINATIONS,970011,Sorbitol,21601190,9945 +B05CX10,COMBINATIONS,994058,Mannitol,21601190,6628 +B05XA,ELECTROLYTE SOLUTIONS,904826,Lactic acid,21601195,28393 +B05XA,ELECTROLYTE SOLUTIONS,19092849,Magnesium Chloride,21601195,6579 +B05XA,ELECTROLYTE SOLUTIONS,19093848,Magnesium Sulfate,21601195,6585 +B05XA01,POTASSIUM CHLORIDE,19049105,Potassium Chloride,21601196,8591 +B05XA02,SODIUM BICARBONATE,939506,Sodium Bicarbonate,21601197,36676 +B05XA03,SODIUM CHLORIDE,967823,Sodium Chloride,21601198,9863 +B05XA03,SODIUM CHLORIDE,19081343,"Sodium Chloride, Bacteriostatic",21601198,219965 +B05XA04,AMMONIUM CHLORIDE,912362,Ammonium Chloride,21601199,712 +B05XA05,MAGNESIUM SULFATE,19093848,Magnesium Sulfate,21601200,6585 +B05XA06,"POTASSIUM PHOS,INCL. COMB W/OTHER POTASSIUM SALTS",19027362,potassium phosphate,21601201,34322 +B05XA06,"POTASSIUM PHOS,INCL. COMB W/OTHER POTASSIUM SALTS",19049024,Potassium,21601201,8588 +B05XA07,CALCIUM CHLORIDE,19036781,Calcium Chloride,21601202,1901 +B05XA08,SODIUM ACETATE,19077884,Sodium Acetate,21601203,56443 +B05XA09,SODIUM PHOSPHATE,939871,sodium phosphate,21601204,36709 +B05XA12,ZINC CHLORIDE,19044317,zinc chloride,21601207,39937 +B05XA13,HYDROCHLORIC ACID,974140,Hydrochloric Acid,21601208,5486 +B05XA17,POTASSIUM ACETATE,19076414,Potassium Acetate,21601212,54987 +B06AA03,HYALURONIDASE,19073699,Hyaluronidase,21601229,5464 +B06AA04,CHYMOTRYPSIN,19096710,CHYMOTRYPSIN,21601230,2530 +B06AB01,HEMATIN,19067303,Hemin,21601236,5175 +C01AA03,DIGITALIS LEAVES,19054998,DIGITALIS LEAF,21601243,235219 +C01AA03,DIGITALIS LEAVES,19060903,Digitalis preparation,21601243,91235 +J06AA06,RABIES SERUM,544509,"rabies immune globulin, (human) vaccine",21601253,830471 +J06BA01,"IMMUNOGLOBULINS,NORMAL HUMAN,FOR EXTRAVASCULAR ADM",19117912,Immunoglobulin G,21601256,5666 +J06BA02,"IMMUNOGLOBULINS,NORMAL HUMAN,FOR INTRAVASCULAR ADM",19117912,Immunoglobulin G,21601257,5666 +J06BB,SPECIFIC IMMUNOGLOBULINS,19013765,respiratory syncytial virus immune globulin intravenous,21601258,119246 +J06BB01,ANTI-D (RH) IMMUNOGLOBULIN,535714,Rho(D) Immune Globulin,21601259,35465 +J06BB03,VARICELLA/ZOSTER IMMUNOGLOBULIN,543291,varicella-zoster immune globulin,21601261,39385 +J06BB04,HEPATITIS B IMMUNOGLOBULIN,501343,hepatitis B immune globulin,21601262,26744 +J06BB05,RABIES IMMUNOGLOBULIN,544509,"rabies immune globulin, (human) vaccine",21601263,830471 +J06BB09,CYTOMEGALOVIRUS IMMUNOGLOBULIN,586491,cytotect,21601267,22178 +J06BB16,PALIVIZUMAB,537647,palivizumab,21601274,194279 +J07AG51,"HEMOPHILUS INFLUENZAE B, COMBINATIONS WITH TOXOIDS",529118,"Haemophilus influenzae b, capsular polysaccharide inactivated tetanus toxoid conjugate vaccine",21601292,798279 +J07AG51,"HEMOPHILUS INFLUENZAE B, COMBINATIONS WITH TOXOIDS",529218,Acellular Pertussis Vaccine,21601292,798302 +J07AG51,"HEMOPHILUS INFLUENZAE B, COMBINATIONS WITH TOXOIDS",529303,Diphtheria Toxoid Vaccine,21601292,798304 +J07AG51,"HEMOPHILUS INFLUENZAE B, COMBINATIONS WITH TOXOIDS",529411,Tetanus Toxoid Vaccine,21601292,798306 +J07AG53,"HEMOPHILUS INFLUENZAE B, COMBOS W/MENING C, CONJ",530007,Haemophilus influenzae b (Ross strain) capsular polysaccharide Meningococcal Protein Conjugate Vaccine,21601294,798444 +J07AG53,"HEMOPHILUS INFLUENZAE B, COMBOS W/MENING C, CONJ",19056377,HAEMOPH B POLYSAC CONJ-MENING,21601294,236568 +J07AH04,"MENINGOCOCCUS, TETRAVALENT PURIF POLYSAC ANTIGEN",509079,meningococcal group A polysaccharide,21601299,29501 +J07AH04,"MENINGOCOCCUS, TETRAVALENT PURIF POLYSAC ANTIGEN",509081,meningococcal group C polysaccharide,21601299,29503 +J07AH04,"MENINGOCOCCUS, TETRAVALENT PURIF POLYSAC ANTIGEN",514012,MENINGOCOCCAL POLYSACCHARIDE VACCINE GROUP W-135,21601299,314724 +J07AH04,"MENINGOCOCCUS, TETRAVALENT PURIF POLYSAC ANTIGEN",514015,MENINGOCOCCAL POLYSACCHARIDE VACCINE GROUP Y,21601299,314725 +J07AH08,"MENINGOCOCCUS, TETRAVAL PURIF POLYSAC ANTIGEN CONJ",528271,Neisseria meningitidis serogroup A capsular polysaccharide diphtheria toxoid protein conjugate vaccine,21601303,797629 +J07AH08,"MENINGOCOCCUS, TETRAVAL PURIF POLYSAC ANTIGEN CONJ",528295,Neisseria meningitidis serogroup C capsular polysaccharide diphtheria toxoid protein conjugate vaccine,21601303,797631 +J07AH08,"MENINGOCOCCUS, TETRAVAL PURIF POLYSAC ANTIGEN CONJ",528297,Neisseria meningitidis serogroup W-135 capsular polysaccharide diphtheria toxoid protein conjugate vaccine,21601303,797633 +J07AH08,"MENINGOCOCCUS, TETRAVAL PURIF POLYSAC ANTIGEN CONJ",528301,Neisseria meningitidis serogroup Y capsular polysaccharide diphtheria toxoid protein conjugate vaccine,21601303,797635 +J07AJ51,"PERTUSSIS, INACT, WHOLE CELL, COMBOS W/TOXOIDS",529118,"Haemophilus influenzae b, capsular polysaccharide inactivated tetanus toxoid conjugate vaccine",21601307,798279 +J07AJ51,"PERTUSSIS, INACT, WHOLE CELL, COMBOS W/TOXOIDS",529218,Acellular Pertussis Vaccine,21601307,798302 +J07AJ51,"PERTUSSIS, INACT, WHOLE CELL, COMBOS W/TOXOIDS",529303,Diphtheria Toxoid Vaccine,21601307,798304 +J07AJ51,"PERTUSSIS, INACT, WHOLE CELL, COMBOS W/TOXOIDS",529411,Tetanus Toxoid Vaccine,21601307,798306 +J07AJ51,"PERTUSSIS, INACT, WHOLE CELL, COMBOS W/TOXOIDS",551943,"Pertussis, acellular",21601307,214755 +J07AJ52,"PERTUSSIS, PURIFIED ANTIGEN, COMBOS WITH TOXOIDS",529118,"Haemophilus influenzae b, capsular polysaccharide inactivated tetanus toxoid conjugate vaccine",21601308,798279 +J07AJ52,"PERTUSSIS, PURIFIED ANTIGEN, COMBOS WITH TOXOIDS",529218,Acellular Pertussis Vaccine,21601308,798302 +J07AJ52,"PERTUSSIS, PURIFIED ANTIGEN, COMBOS WITH TOXOIDS",529303,Diphtheria Toxoid Vaccine,21601308,798304 +J07AJ52,"PERTUSSIS, PURIFIED ANTIGEN, COMBOS WITH TOXOIDS",529411,Tetanus Toxoid Vaccine,21601308,798306 +J07AJ52,"PERTUSSIS, PURIFIED ANTIGEN, COMBOS WITH TOXOIDS",551943,"Pertussis, acellular",21601308,214755 +J07AL02,"PNEUMOCOCCUS, PURIF POLYSACCHARIDES ANTIGEN CONJ",528986,Streptococcus pneumoniae serotype 14 capsular antigen diphtheria CRM197 protein conjugate vaccine,21601313,798220 +J07AL02,"PNEUMOCOCCUS, PURIF POLYSACCHARIDES ANTIGEN CONJ",528988,Streptococcus pneumoniae serotype 18C capsular antigen diphtheria CRM197 protein conjugate vaccine,21601313,798222 +J07AL02,"PNEUMOCOCCUS, PURIF POLYSACCHARIDES ANTIGEN CONJ",528990,Streptococcus pneumoniae serotype 19F capsular antigen diphtheria CRM197 protein conjugate vaccine,21601313,798224 +J07AL02,"PNEUMOCOCCUS, PURIF POLYSACCHARIDES ANTIGEN CONJ",529042,Streptococcus pneumoniae serotype 23F capsular antigen diphtheria CRM197 protein conjugate vaccine,21601313,798226 +J07AL02,"PNEUMOCOCCUS, PURIF POLYSACCHARIDES ANTIGEN CONJ",529044,Streptococcus pneumoniae serotype 4 capsular antigen diphtheria CRM197 protein conjugate vaccine,21601313,798228 +J07AL02,"PNEUMOCOCCUS, PURIF POLYSACCHARIDES ANTIGEN CONJ",529046,Streptococcus pneumoniae serotype 6B capsular antigen diphtheria CRM197 protein conjugate vaccine,21601313,798230 +J07AL02,"PNEUMOCOCCUS, PURIF POLYSACCHARIDES ANTIGEN CONJ",529072,Streptococcus pneumoniae serotype 9V capsular antigen diphtheria CRM197 protein conjugate vaccine,21601313,798232 +J07AM01,TETANUS TOXOID,529411,Tetanus Toxoid Vaccine,21601316,798306 +J07AM51,"TETANUS TOXOID, COMBINATIONS W/DIPHTHERIA TOXOID",529303,Diphtheria Toxoid Vaccine,21601317,798304 +J07AM51,"TETANUS TOXOID, COMBINATIONS W/DIPHTHERIA TOXOID",529411,Tetanus Toxoid Vaccine,21601317,798306 +J07AP03,"TYPHOID, PURIFIED POLYSACCHARIDE ANTIGEN",532881,"Typhoid Vi Polysaccharide Vaccine, S typhi Ty2 strain",21601324,807219 +J07AX,OTHER BACTERIAL VACCINES,551463,Lyme Disease Vaccine,21601328,214177 +J07BC01,"HEPATITIS B, PURIFIED ANTIGEN",501488,Hepatitis B Vaccine,21601338,26746 +J07BC01,"HEPATITIS B, PURIFIED ANTIGEN",528323,Hepatitis B Surface Antigen Vaccine,21601338,797752 +J07BC01,"HEPATITIS B, PURIFIED ANTIGEN",19030114,"Hepatitis B Surface Antigen (Australia antigen) MSD, Vaccine",21601338,798456 +J07BC02,"HEPATITIS A, INACTIVATED, WHOLE VIRUS",596876,"Hepatitis A Vaccine, Inactivated",21601339,253174 +J07BC20,COMBINATIONS,501488,Hepatitis B Vaccine,21601340,26746 +J07BC20,COMBINATIONS,596876,"Hepatitis A Vaccine, Inactivated",21601340,253174 +J07BG01,"RABIES, INACTIVATED, WHOLE VIRUS",544505,rabies virus vaccine wistar strain PM-1503-3M (Human),21601354,830464 +J07BH01,"ROTA VIRUS, LIVE ATTENUATED",19032599,"Rotavirus Vaccine, Live Attenuated, G1P[8] Human 89-12 strain",21601356,805573 +J07BM01,"PAPILLOMAVIRUS (HUMAN TYPES 6,11,16,18)",529076,"L1 protein, Human papillomavirus type 11 Vaccine",21601367,798262 +J07BM01,"PAPILLOMAVIRUS (HUMAN TYPES 6,11,16,18)",529112,"L1 protein, Human papillomavirus type 16 Vaccine",21601367,798264 +J07BM01,"PAPILLOMAVIRUS (HUMAN TYPES 6,11,16,18)",529114,"L1 protein, Human papillomavirus type 18 Vaccine",21601367,798266 +J07BM01,"PAPILLOMAVIRUS (HUMAN TYPES 6,11,16,18)",529116,"L1 protein, Human papillomavirus type 6 Vaccine",21601367,798268 +J07CA06,DIPHTHERIA-HEMOPH INFLUENZAE B-PERTUSSIS-POLIO-TET,529118,"Haemophilus influenzae b, capsular polysaccharide inactivated tetanus toxoid conjugate vaccine",21601377,798279 +J07CA06,DIPHTHERIA-HEMOPH INFLUENZAE B-PERTUSSIS-POLIO-TET,529218,Acellular Pertussis Vaccine,21601377,798302 +J07CA06,DIPHTHERIA-HEMOPH INFLUENZAE B-PERTUSSIS-POLIO-TET,529303,Diphtheria Toxoid Vaccine,21601377,798304 +J07CA06,DIPHTHERIA-HEMOPH INFLUENZAE B-PERTUSSIS-POLIO-TET,529411,Tetanus Toxoid Vaccine,21601377,798306 +J07CA06,DIPHTHERIA-HEMOPH INFLUENZAE B-PERTUSSIS-POLIO-TET,19031464,"Inactivated Polioviruses Type 1, Mahoney strain vaccine",21601377,801830 +J07CA06,DIPHTHERIA-HEMOPH INFLUENZAE B-PERTUSSIS-POLIO-TET,19031466,"Inactivated Polioviruses Type 2, MEF-1 strain vaccine",21601377,801832 +J07CA06,DIPHTHERIA-HEMOPH INFLUENZAE B-PERTUSSIS-POLIO-TET,19031468,"Inactivated Polioviruses Type 3, Saukett strain vaccine",21601377,801834 +L01AA01,CYCLOPHOSPHAMIDE,1310317,Cyclophosphamide,21601390,3002 +L01AA02,CHLORAMBUCIL,1390051,Chlorambucil,21601391,2346 +L01AA03,MELPHALAN,1301267,Melphalan,21601392,6718 +L01AA05,CHLORMETHINE,1394337,Mechlorethamine,21601393,6674 +L01AA06,IFOSFAMIDE,1354698,Mesna,21601394,44 +L01AA06,IFOSFAMIDE,19078187,Ifosfamide,21601394,5657 +L01AA09,BENDAMUSTINE,19015523,bendamustine,21601397,134547 +L01AB01,BUSULFAN,1333357,Busulfan,21601399,1828 +L01AC01,THIOTEPA,19137385,Thiotepa,21601403,10473 +L01AD01,CARMUSTINE,1350066,Carmustine,21601407,2105 +L01AD02,LOMUSTINE,1391846,Lomustine,21601408,6466 +L01AD04,STREPTOZOCIN,19136210,Streptozocin,21601410,10114 +L01AX02,PIPOBROMAN,19046625,Pipobroman,21601418,8347 +L01AX03,TEMOZOLOMIDE,1341149,temozolomide,21601419,37776 +L01AX04,DACARBAZINE,1311409,Dacarbazine,21601420,3098 +L01BA01,METHOTREXATE,1305058,Methotrexate,21601423,6851 +L01BA04,PEMETREXED,1304919,pemetrexed,21601425,68446 +L01BB02,MERCAPTOPURINE,1436650,6-Mercaptopurine,21601428,103 +L01BB03,TIOGUANINE,1437379,Thioguanine,21601429,10485 +L01BB04,CLADRIBINE,19054825,Cladribine,21601430,44157 +L01BB05,FLUDARABINE,1395557,fludarabine,21601431,24698 +L01BB06,CLOFARABINE,19054821,clofarabine,21601432,44151 +L01BB07,NELARABINE,19002912,nelarabine,21601433,274771 +L01BC,PYRIMIDINE ANALOGUES,1355509,Floxuridine,21601434,4488 +L01BC01,CYTARABINE,1311078,Cytarabine,21601435,3041 +L01BC01,CYTARABINE,19041067,cytarabine liposomal,21601435,81932 +L01BC02,FLUOROURACIL,955632,Fluorouracil,21601436,4492 +L01BC05,GEMCITABINE,1314924,gemcitabine,21601439,12574 +L01BC06,CAPECITABINE,1337620,capecitabine,21601440,194000 +L01BC07,AZACITABINE,1314865,Azacitidine,21601441,1251 +L01BC08,DECITABINE,19024728,decitabine,21601442,15657 +L01CA01,VINBLASTINE,19008264,Vinblastine,21601447,11198 +L01CA02,VINCRISTINE,1308290,Vincristine,21601448,11202 +L01CA04,VINORELBINE,1343346,vinorelbine,21601450,39541 +C03AA01,BENDROFLUMETHIAZIDE,1316354,Bendroflumethiazide,21601464,1369 +C03AA02,HYDROFLUMETHIAZIDE,1376289,Hydroflumethiazide,21601465,5495 +C03AA03,HYDROCHLOROTHIAZIDE,974166,Hydrochlorothiazide,21601466,5487 +C03AA04,CHLOROTHIAZIDE,992590,Chlorothiazide,21601467,2396 +C03AA05,POLYTHIAZIDE,948787,Polythiazide,21601468,8565 +C03AA06,TRICHLORMETHIAZIDE,904639,Trichlormethiazide,21601469,10772 +C03AA08,METHYCLOTHIAZIDE,905273,Methyclothiazide,21601471,6860 +C03AA09,CYCLOTHIAZIDE,19082886,cyclothiazide,21601472,22033 +C03BA04,CHLORTALIDONE,1395058,Chlorthalidone,21601493,2409 +C03BA08,METOLAZONE,907013,Metolazone,21601496,6916 +C03BA11,INDAPAMIDE,978555,Indapamide,21601499,5764 +C03BB02,QUINETHAZONE AND POTASSIUM,19081320,quinethazone,21601504,59743 +C03BD,XANTHINE DERIVATIVES,912362,Ammonium Chloride,21601511,712 +C03BD,XANTHINE DERIVATIVES,1134439,Caffeine,21601511,1886 +C03CA01,FUROSEMIDE,956874,Furosemide,21601518,4603 +C03CA02,BUMETANIDE,932745,Bumetanide,21601519,1808 +C03CA04,TORASEMIDE,942350,torsemide,21601521,38413 +C03CC01,ETACRYNIC ACID,987406,Ethacrynate,21601526,62349 +C03DA01,SPIRONOLACTONE,970250,Spironolactone,21601534,9997 +C03DA04,EPLERENONE,1309799,eplerenone,21601537,298869 +C03DB01,AMILORIDE,991382,Amiloride,21601539,644 +C03DB02,TRIAMTERENE,904542,Triamterene,21601540,10763 +C03EA01,HYDROCHLOROTHIAZIDE AND POTASSIUM-SPARING AGENTS,904542,Triamterene,21601543,10763 +C03EA01,HYDROCHLOROTHIAZIDE AND POTASSIUM-SPARING AGENTS,970250,Spironolactone,21601543,9997 +C03EA01,HYDROCHLOROTHIAZIDE AND POTASSIUM-SPARING AGENTS,974166,Hydrochlorothiazide,21601543,5487 +C03EA01,HYDROCHLOROTHIAZIDE AND POTASSIUM-SPARING AGENTS,991382,Amiloride,21601543,644 +C03XA01,TOLVAPTAN,19036797,tolvaptan,21601558,358257 +C03XA02,CONIVAPTAN,19010927,conivaptan,21601559,302285 +C04A,PERIPHERAL VASODILATORS,19095288,ethaverine,21601561,24464 +C04AA01,ISOXSUPRINE,1384360,Isoxsuprine,21601563,6066 +C04AA02,BUPHENINE,19022494,Nylidrin,21601564,7595 +C04AB01,PHENTOLAMINE,1335539,Phentolamine,21601567,8153 +C04AB02,TOLAZOLINE,19002829,Tolazoline,21601568,10634 +C04AC01,NICOTINIC ACID,1517824,Niacin,21601570,7393 +C04AC02,NICOTINYL ALCOHOL (PYRIDYLCARBINOL),19018823,Nicotinyl Alcohol,21601571,7414 +C04AD03,PENTOXIFYLLINE,1331247,Pentoxifylline,21601577,8013 +C04AE01,ERGOLOID MESYLATES,745268,"ergoloid mesylates, USP",21601580,4024 +C04AX,OTHER PERIPHERAL VASODILATORS,19008269,Vincamine,21601587,11201 +C04AX,OTHER PERIPHERAL VASODILATORS,19098505,GINKGO BILOBA LEAF,21601587,259265 +C04AX01,CYCLANDELATE,1309323,Cyclandelate,21601588,2970 +C04AX02,PHENOXYBENZAMINE,1335301,Phenoxybenzamine,21601589,8149 +C04AX33,CILOSTAZOL,1350310,cilostazol,0,21107 +C05AA01,HYDROCORTISONE,927478,pramoxine,21601608,34347 +C05AA01,HYDROCORTISONE,957797,Psyllium,21601608,8928 +C05AA01,HYDROCORTISONE,975125,Hydrocortisone,21601608,5492 +C05AA01,HYDROCORTISONE,989878,Lidocaine,21601608,6387 +C05AD01,LIDOCAINE,989878,Lidocaine,21601618,6387 +C05AD03,BENZOCAINE,916802,Benzethonium,21601620,1390 +C05AD03,BENZOCAINE,917006,Benzocaine,21601620,1399 +C05AD04,CINCHOCAINE,923840,Dibucaine,21601621,3339 +C05AD07,PRAMOCAINE,911064,Zinc Oxide,21601624,11423 +C05AD07,PRAMOCAINE,927478,pramoxine,21601624,34347 +C05AD07,PRAMOCAINE,961145,Glycerin,21601624,4910 +C05AD07,PRAMOCAINE,1135766,Phenylephrine,21601624,8163 +C05AX03,"OTHER PREPARATIONS, COMBINATIONS",959196,Witch Hazel,21601631,89821 +C05AX03,"OTHER PREPARATIONS, COMBINATIONS",961145,Glycerin,21601631,4910 +C05AX03,"OTHER PREPARATIONS, COMBINATIONS",1135766,Phenylephrine,21601631,8163 +C05AX04,ZINC PREPARATIONS,911064,Zinc Oxide,21601632,11423 +C05AX04,ZINC PREPARATIONS,1135766,Phenylephrine,21601632,8163 +C05BA04,PENTOSAN POLYSULFATE SODIUM,924151,Pentosan Polysulfate,21601639,155046 +C05BB01,MONOETHANOLAMINE OLEATE,19095285,ethanolamine oleate,21601643,24460 +C05BB03,INVERT SUGAR,19003107,invert sugar,21601645,27712 +C05BB04,SODIUM TETRADECYL SULFATE,19070012,Sodium Tetradecyl Sulfate,21601646,9913 +C05BX,OTHER SCLEROSING AGENTS,19069904,Sodium Morrhuate,21601649,9892 +C05CA,BIOFLAVONOIDS,19024669,Bioflavonoids,21601653,1562 +C05CA01,RUTOSIDE,19063981,Rutin,21601654,9500 +C05CA03,DIOSMIN,19029488,Diosmin,21601656,3489 +C05CA53,"DIOSMIN, COMBINATIONS",19029488,Diosmin,21601660,3489 +C05CA53,"DIOSMIN, COMBINATIONS",19068688,Hesperidin,21601660,5281 +C07AA03,PINDOLOL,1345858,Pindolol,21601669,8332 +C07AA05,PROPRANOLOL,1353766,Propranolol,21601670,8787 +C07AA06,TIMOLOL,902427,Timolol,21601671,10600 +C07AA07,SOTALOL,1370109,Sotalol,21601672,9947 +C07AA12,NADOLOL,1313200,Nadolol,21601673,7226 +C07AA15,CARTEOLOL,950370,Carteolol,21601675,2116 +C07AA23,PENBUTOLOL,1327978,Penbutolol,21601679,7973 +C07AB02,METOPROLOL,1307046,Metoprolol,21601684,6918 +C07AB03,ATENOLOL,1314002,Atenolol,21601685,1202 +C07AB04,ACEBUTOLOL,1319998,Acebutolol,21601686,149 +C07AB05,BETAXOLOL,1322081,Betaxolol,21601687,1520 +C07AB07,BISOPROLOL,1338005,Bisoprolol,21601689,19484 +C07AB09,ESMOLOL,19063575,esmolol,21601691,49737 +C07AB12,NEBIVOLOL,1314577,nebivolol,21601694,31555 +C07AG01,LABETALOL,1386957,Labetalol,21601699,6185 +C07AG02,CARVEDILOL,1346823,carvedilol,21601700,20352 +C07BA06,TIMOLOL AND THIAZIDES,902427,Timolol,21601705,10600 +C07BA06,TIMOLOL AND THIAZIDES,974166,Hydrochlorothiazide,21601705,5487 +C07BA12,NADOLOL AND THIAZIDES,1313200,Nadolol,21601707,7226 +C07BA12,NADOLOL AND THIAZIDES,1316354,Bendroflumethiazide,21601707,1369 +C07BB02,METOPROLOL AND THIAZIDES,974166,Hydrochlorothiazide,21601710,5487 +C07BB02,METOPROLOL AND THIAZIDES,1307046,Metoprolol,21601710,6918 +C07BG01,LABETALOL AND THIAZIDES,974166,Hydrochlorothiazide,21601717,5487 +C07BG01,LABETALOL AND THIAZIDES,1386957,Labetalol,21601717,6185 +C07CB03,ATENOLOL AND OTHER DIURETICS,1314002,Atenolol,21601726,1202 +C07CB03,ATENOLOL AND OTHER DIURETICS,1395058,Chlorthalidone,21601726,2409 +C08CA,DIHYDROPYRIDINE DERIVATIVES,19089969,clevidipine,21601746,233603 +C08CA01,AMLODIPINE,1332418,Amlodipine,21601747,17767 +C08CA02,FELODIPINE,1353776,Felodipine,21601748,4316 +C08CA03,ISRADIPINE,1326012,Isradipine,21601749,33910 +C08CA04,NICARDIPINE,1318137,Nicardipine,21601750,7396 +C08CA05,NIFEDIPINE,1318853,Nifedipine,21601751,7417 +C08CA06,NIMODIPINE,1319133,Nimodipine,21601752,7426 +C08CA07,NISOLDIPINE,1319880,Nisoldipine,21601753,7435 +C08CX01,MIBEFRADIL,1345141,Mibefradil,21601764,83213 +C08DA01,VERAPAMIL,1307863,Verapamil,21601767,11170 +C08DB01,DILTIAZEM,1328165,Diltiazem,21601771,3443 +C08EA02,BEPRIDIL,1319751,Bepridil,21601775,1436 +C09AA01,CAPTOPRIL,1340128,Captopril,21601785,1998 +C09AA02,ENALAPRIL,1341927,Enalapril,21601786,3827 +C09AA02,ENALAPRIL,1342001,Enalaprilat,21601786,3829 +C09AA03,LISINOPRIL,1308216,Lisinopril,21601787,29046 +C09AA05,RAMIPRIL,1334456,Ramipril,21601789,35296 +C09AA06,QUINAPRIL,1331235,quinapril,21601790,35208 +C09AA07,BENAZEPRIL,1335471,benazepril,21601791,18867 +C09AA10,TRANDOLAPRIL,1342439,trandolapril,21601794,38454 +C09AA13,MOEXIPRIL,1310756,moexipril,21601797,30131 +C09BA01,CAPTOPRIL AND DIURETICS,974166,Hydrochlorothiazide,21601803,5487 +C09BA01,CAPTOPRIL AND DIURETICS,1340128,Captopril,21601803,1998 +C09BA02,ENALAPRIL AND DIURETICS,974166,Hydrochlorothiazide,21601804,5487 +C09BA02,ENALAPRIL AND DIURETICS,1341927,Enalapril,21601804,3827 +C09BA03,LISINOPRIL AND DIURETICS,974166,Hydrochlorothiazide,21601805,5487 +C09BA03,LISINOPRIL AND DIURETICS,1308216,Lisinopril,21601805,29046 +C09BA06,QUINAPRIL AND DIURETICS,974166,Hydrochlorothiazide,21601808,5487 +C09BA06,QUINAPRIL AND DIURETICS,1331235,quinapril,21601808,35208 +C09BA07,BENAZEPRIL AND DIURETICS,974166,Hydrochlorothiazide,21601809,5487 +C09BA07,BENAZEPRIL AND DIURETICS,1335471,benazepril,21601809,18867 +C09BA13,MOXEIPRIL AND DIURETICS,974166,Hydrochlorothiazide,21601813,5487 +C09BA13,MOXEIPRIL AND DIURETICS,1310756,moexipril,21601813,30131 +C09BB,ACE INHIBITORS AND CALCIUM CHANNEL BLOCKERS,1332418,Amlodipine,21601815,17767 +C09BB,ACE INHIBITORS AND CALCIUM CHANNEL BLOCKERS,1335471,benazepril,21601815,18867 +C09BB,ACE INHIBITORS AND CALCIUM CHANNEL BLOCKERS,1341927,Enalapril,21601815,3827 +C09BB,ACE INHIBITORS AND CALCIUM CHANNEL BLOCKERS,1353776,Felodipine,21601815,4316 +C09BB10,TRANDOLAPRIL AND VERAPAMIL,1307863,Verapamil,21601820,11170 +C09BB10,TRANDOLAPRIL AND VERAPAMIL,1342439,trandolapril,21601820,38454 +C09CA01,LOSARTAN,1367500,Losartan,21601824,52175 +C09CA02,EPROSARTAN,1346686,eprosartan,21601825,83515 +C09CA03,VALSARTAN,1308842,valsartan,21601826,69749 +C09CA04,IRBESARTAN,1347384,irbesartan,21601827,83818 +C09CA06,CANDESARTAN,1351557,candesartan,21601829,214354 +C09CA07,TELMISARTAN,1317640,telmisartan,21601830,73494 +C09CA08,OLMESARTAN MEDOXOMIL,1312742,Olmesartan medoxomil,21601831,118463 +C09DA01,LOSARTAN AND DIURETICS,974166,Hydrochlorothiazide,21601834,5487 +C09DA01,LOSARTAN AND DIURETICS,1367500,Losartan,21601834,52175 +C09DA02,EPROSARTAN AND DIURETICS,974166,Hydrochlorothiazide,21601835,5487 +C09DA02,EPROSARTAN AND DIURETICS,1346686,eprosartan,21601835,83515 +C09DA03,VALSARTAN AND DIURETICS,974166,Hydrochlorothiazide,21601836,5487 +C09DA03,VALSARTAN AND DIURETICS,1308842,valsartan,21601836,69749 +C09DA04,IRBESARTAN AND DIURETICS,974166,Hydrochlorothiazide,21601837,5487 +C09DA04,IRBESARTAN AND DIURETICS,1347384,irbesartan,21601837,83818 +C09DA06,CANDESARTAN AND DIURETICS,974166,Hydrochlorothiazide,21601838,5487 +C09DA06,CANDESARTAN AND DIURETICS,1351557,candesartan,21601838,214354 +C09DA07,TELMISARTAN AND DIURETICS,974166,Hydrochlorothiazide,21601839,5487 +C09DA07,TELMISARTAN AND DIURETICS,1317640,telmisartan,21601839,73494 +C09DA08,OLMESARTAN MEDOXOMIL AND DIURETICS,974166,Hydrochlorothiazide,21601840,5487 +C09DA08,OLMESARTAN MEDOXOMIL AND DIURETICS,1312742,Olmesartan medoxomil,21601840,118463 +C09DB01,VALSARTAN AND AMLODIPINE,1308842,valsartan,21601842,69749 +C09DB01,VALSARTAN AND AMLODIPINE,1332418,Amlodipine,21601842,17767 +C09DB02,OLMESARTAN MEDOXOMIL AND AMLODIPINE,1312742,Olmesartan medoxomil,21601843,118463 +C09DB02,OLMESARTAN MEDOXOMIL AND AMLODIPINE,1332418,Amlodipine,21601843,17767 +C09DX01,"VALSARTAN, AMLODIPINE AND HYDROCHLOROTHIAZIDE",974166,Hydrochlorothiazide,21601846,5487 +C09DX01,"VALSARTAN, AMLODIPINE AND HYDROCHLOROTHIAZIDE",1308842,valsartan,21601846,69749 +C09DX01,"VALSARTAN, AMLODIPINE AND HYDROCHLOROTHIAZIDE",1332418,Amlodipine,21601846,17767 +C09XA02,ALISKIREN,1317967,aliskiren,21601851,325646 +C09XA52,ALISKIREN AND HYDROCHLOROTHIAZIDE,974166,Hydrochlorothiazide,21601852,5487 +C09XA52,ALISKIREN AND HYDROCHLOROTHIAZIDE,1317967,aliskiren,21601852,325646 +C10AA01,SIMVASTATIN,1539403,Simvastatin,21601856,36567 +C10AA02,LOVASTATIN,1592085,Lovastatin,21601857,6472 +C10AA03,PRAVASTATIN,1112807,Aspirin,21601858,1191 +C10AA03,PRAVASTATIN,1551860,Pravastatin,21601858,42463 +C10AA04,FLUVASTATIN,1549686,fluvastatin,21601859,41127 +C10AA05,ATROVASTATIN,1545958,atorvastatin,21601860,83367 +C10AA06,CERIVASTATIN,1586226,Cerivastatin sodium,21601861,221072 +C10AA07,ROSUVASTATIN,1510813,rosuvastatin,21601862,301542 +C10AB,FIBRATES,1551803,Fenofibrate,21601864,8703 +C10AB01,CLOFIBRATE,1598658,Clofibrate,21601865,2594 +C10AB04,GEMFIBROZIL,1558242,Gemfibrozil,21601868,4719 +C10AB05,FENOFIBRATE,1551803,Fenofibrate,21601869,8703 +C10AC01,COLESTYRAMINE,19095309,Cholestyramine,21601876,2447 +C10AC02,COLESTIPOL,1501617,Colestipol,21601877,2685 +C10AC04,COLESEVELAM,1518148,colesevelam,21601879,141626 +C10AD02,NICOTINIC ACID,1379525,Inositol,21601882,5833 +C10AD02,NICOTINIC ACID,1517824,Niacin,21601882,7393 +C10AX,OTHER LIPID MODIFYING AGENTS,1195334,Choline,21601888,2449 +C10AX,OTHER LIPID MODIFYING AGENTS,1379525,Inositol,21601888,5833 +C10AX,OTHER LIPID MODIFYING AGENTS,1398573,plant stanol ester,21601888,259320 +C10AX,OTHER LIPID MODIFYING AGENTS,1401437,Garlic preparation,21601888,265647 +C10AX,OTHER LIPID MODIFYING AGENTS,1508241,policosanol,21601888,69440 +C10AX,OTHER LIPID MODIFYING AGENTS,19019877,eicosapentanoic acid,21601888,144449 +C10AX,OTHER LIPID MODIFYING AGENTS,19042345,Lecithin,21601888,8214 +C10AX01,DEXTROTHYROXINE,19022003,Dextrothyroxine,21601889,3292 +C10AX02,PROBUCOL,19051463,Probucol,21601890,8699 +C10AX06,OMEGA-3-TRIGLYCERIDES INCL. OTHER ESTERS AND ACIDS,1315342,Flaxseed extract,21601893,318224 +C10AX06,OMEGA-3-TRIGLYCERIDES INCL. OTHER ESTERS AND ACIDS,1560305,Omega-3 Acid Ethyl Esters (USP),21601893,484348 +C10AX06,OMEGA-3-TRIGLYCERIDES INCL. OTHER ESTERS AND ACIDS,19009540,Vitamin E,21601893,11256 +C10AX06,OMEGA-3-TRIGLYCERIDES INCL. OTHER ESTERS AND ACIDS,19016670,Docosahexaenoate,21601893,73 +C10AX06,OMEGA-3-TRIGLYCERIDES INCL. OTHER ESTERS AND ACIDS,19087063,Eicosapentaenoate,21601893,618597 +C10AX08,POLICOSANOL,1508241,policosanol,21601895,69440 +C10AX09,EZETIMIBE,1526475,ezetimibe,21601896,341248 +C10BA,HMG COA REDUCTASE INHIB COMB W/OTHER LIPID MOD AGT,1517824,Niacin,21601899,7393 +C10BA,HMG COA REDUCTASE INHIB COMB W/OTHER LIPID MOD AGT,1539403,Simvastatin,21601899,36567 +C10BA01,LOVASTATIN AND NICOTINIC ACID,1517824,Niacin,21601900,7393 +C10BA01,LOVASTATIN AND NICOTINIC ACID,1592085,Lovastatin,21601900,6472 +C10BA02,SIMVASTATIN AND EZEMTIMIBE,1526475,ezetimibe,21601901,341248 +C10BA02,SIMVASTATIN AND EZEMTIMIBE,1539403,Simvastatin,21601901,36567 +C10BX03,ATORVASTATIN AND AMLOPIDINE,1332418,Amlodipine,21601906,17767 +C10BX03,ATORVASTATIN AND AMLOPIDINE,1545958,atorvastatin,21601906,83367 +D01AA01,NYSTATIN,922570,Nystatin,21601911,7597 +D01AC,IMIDAZOLE AND TRIAZOLE DERIVATIVES,975125,Hydrocortisone,21601919,5492 +D01AC,IMIDAZOLE AND TRIAZOLE DERIVATIVES,985708,Ketoconazole,21601919,6135 +D01AC01,CLOTRIMAZOLE,1000632,Clotrimazole,21601920,2623 +D01AC02,MICONAZOLE,907879,Miconazole,21601921,6932 +D01AC08,KETOCONAZOLE,931035,pyrithione,21601927,35100 +D01AC08,KETOCONAZOLE,944360,zinc pyrithione,21601927,39952 +D01AC08,KETOCONAZOLE,975125,Hydrocortisone,21601927,5492 +D01AC08,KETOCONAZOLE,985708,Ketoconazole,21601927,6135 +D01AC09,SULCONAZOLE,940535,sulconazole,21601928,37319 +D01AC11,OXICONAZOLE,918222,oxiconazole,21601930,32638 +D01AC14,SERTACONAZOLE,939134,sertaconazole,21601933,36435 +D01AC52,"MICONAZOLE, COMBINATIONS",907879,Miconazole,21601937,6932 +D01AC52,"MICONAZOLE, COMBINATIONS",911064,Zinc Oxide,21601937,11423 +D01AE,OTHER ANTIFUNGALS FOR TOPICAL USE,19003914,Triacetin,21601939,10756 +D01AE02,METHYLROSANILINE,959362,Gentian Violet,21601941,4778 +D01AE04,UNDECYLENIC ACID,914244,Undecylenate,21601943,314881 +D01AE11,HALOPROGIN,19101422,haloprogin,21601950,26422 +D01AE13,SELENIUM SULFIDE,938061,selenium disulfide,21601952,36345 +D01AE14,CICLOPIROX,950098,ciclopirox,21601953,21090 +D01AE15,TERBINAFINE,1741309,terbinafine,21601954,37801 +D01AE18,TOLNAFTATE,902950,Tolnaftate,21601957,10637 +D01AE20,COMBINATIONS,936519,Benzoic Acid,21601959,18989 +D01AE20,COMBINATIONS,940004,sodium thiosulfate,21601959,36726 +D01AE20,COMBINATIONS,964407,Salicylic Acid,21601959,9525 +D01AE22,NAFTIFINE,914053,naftifine,21601961,31476 +D01AE23,BUTENAFINE,958396,butenafine,21601962,47461 +D01AE54,"UNDECYLENIC ACID, COMBINATIONS",914244,Undecylenate,21601963,314881 +D01AE54,"UNDECYLENIC ACID, COMBINATIONS",949459,chloroxylenol,21601963,20877 +D01BA01,GRISEOFULVIN,1763779,Griseofulvin,21601966,5021 +D01BA02,TERBINAFINE,1741309,terbinafine,21601967,37801 +D02AA,SILICONE PRODUCTS,916662,dimethicone,21601970,324072 +D02AA,SILICONE PRODUCTS,966376,Allantoin,21601970,508 +D02AA,SILICONE PRODUCTS,986261,Colloidal oatmeal,21601970,221082 +D02AA,SILICONE PRODUCTS,19066894,Silicones,21601970,9778 +D02AB,ZINC PRODUCTS,901656,Menthol,21601971,6750 +D02AB,ZINC PRODUCTS,911064,Zinc Oxide,21601971,11423 +D02AB,ZINC PRODUCTS,916662,dimethicone,21601971,324072 +D02AB,ZINC PRODUCTS,923540,phenol,21601971,33290 +D02AB,ZINC PRODUCTS,942172,"Petrolatum, White",21601971,82074 +D02AB,ZINC PRODUCTS,979096,Zinc Acetate,21601971,58295 +D02AB,ZINC PRODUCTS,984801,Kaolin,21601971,6102 +D02AB,ZINC PRODUCTS,1036667,Talc,21601971,10323 +D02AB,ZINC PRODUCTS,19007539,Corn starch preparation,21601971,2858 +D02AB,ZINC PRODUCTS,19033354,Petrolatum,21601971,8091 +D02AC,SOFT PARAFFIN AND FAT PRODUCTS,908523,Mineral Oil,21601972,6972 +D02AC,SOFT PARAFFIN AND FAT PRODUCTS,911064,Zinc Oxide,21601972,11423 +D02AC,SOFT PARAFFIN AND FAT PRODUCTS,929128,Propylene glycol,21601972,34693 +D02AC,SOFT PARAFFIN AND FAT PRODUCTS,942172,"Petrolatum, White",21601972,82074 +D02AC,SOFT PARAFFIN AND FAT PRODUCTS,942691,triethanolamine,21601972,38623 +D02AC,SOFT PARAFFIN AND FAT PRODUCTS,19033354,Petrolatum,21601972,8091 +D02AC,SOFT PARAFFIN AND FAT PRODUCTS,19087317,Lanolin,21601972,6227 +D02AE01,CARBAMIDE,906914,Urea,21601975,11002 +D02AE01,CARBAMIDE,1036252,Sulfacetamide,21601975,10169 +D02AE51,"CARBAMIDE, COMBINATIONS",904826,Lactic acid,21601976,28393 +D02AE51,"CARBAMIDE, COMBINATIONS",906914,Urea,21601976,11002 +D02AE51,"CARBAMIDE, COMBINATIONS",926770,Papain,21601976,7892 +D02AE51,"CARBAMIDE, COMBINATIONS",942494,chlorophyllin copper complex,21601976,82242 +D02AE51,"CARBAMIDE, COMBINATIONS",1036252,Sulfacetamide,21601976,10169 +D02AF,SALICYLIC ACID PREPARATIONS,901656,Menthol,21601977,6750 +D02AF,SALICYLIC ACID PREPARATIONS,923540,phenol,21601977,33290 +D02AF,SALICYLIC ACID PREPARATIONS,938205,Camphor,21601977,1952 +D02AF,SALICYLIC ACID PREPARATIONS,964407,Salicylic Acid,21601977,9525 +D02AF,SALICYLIC ACID PREPARATIONS,1738521,Doxycycline,21601977,3640 +D02AX,OTHER EMOLLIENTS AND PROTECTIVES,904826,Lactic acid,21601978,28393 +D02AX,OTHER EMOLLIENTS AND PROTECTIVES,916802,Benzethonium,21601978,1390 +D02AX,OTHER EMOLLIENTS AND PROTECTIVES,961145,Glycerin,21601978,4910 +D02AX,OTHER EMOLLIENTS AND PROTECTIVES,966376,Allantoin,21601978,508 +D02AX,OTHER EMOLLIENTS AND PROTECTIVES,977949,ichthammol,21601978,5645 +D02AX,OTHER EMOLLIENTS AND PROTECTIVES,986261,Colloidal oatmeal,21601978,221082 +D02AX,OTHER EMOLLIENTS AND PROTECTIVES,992308,dyclonine,21601978,23744 +D02AX,OTHER EMOLLIENTS AND PROTECTIVES,19008339,Vitamin A,21601978,11246 +D02AX,OTHER EMOLLIENTS AND PROTECTIVES,19009540,Vitamin E,21601978,11256 +D02BA,PROTECTIVES AGAINST UV-RADIATION FOR TOPICAL USE,19071908,cinoxate,21601980,288262 +D02BA01,AMINOBENZOIC ACID,19018384,4-Aminobenzoic Acid,21601981,74 +D03AX01,CADEXOMER IODINE,1740226,cadexomer iodine,21601989,20012 +D03AX03,DEXPANTHENOL,988294,dexpanthenol,21601991,22701 +D03AX05,HYALURONIC ACID,787787,hyaluronate,21601993,62372 +D03AX05,HYALURONIC ACID,918172,Benzoyl Peroxide,21601993,1418 +D03AX06,BECAPLERMIN,912476,Becaplermin,21601994,115238 +D03BA01,TRYPSIN,906149,TRYPSIN,21601999,10890 +D03BA01,TRYPSIN,922976,Peruvian balsam,21601999,33219 +D03BA01,TRYPSIN,950933,Castor Oil,21601999,2129 +D03BA02,COLLAGENASE,980311,COLLAGENASE,21602000,58939 +D04AA02,MEPYRAMINE,917006,Benzocaine,21602006,1399 +D04AA02,MEPYRAMINE,1159811,Pyrilamine,21602006,9009 +D04AA02,MEPYRAMINE,19010696,Zinc,21602006,11416 +D04AA04,TRIPELENNAMINE,1105853,Tripelennamine,21602008,10847 +D04AA32,DIPHENHYDRAMINE,902616,Calamine,21602016,106212 +D04AA32,DIPHENHYDRAMINE,911064,Zinc Oxide,21602016,11423 +D04AA32,DIPHENHYDRAMINE,938205,Camphor,21602016,1952 +D04AA32,DIPHENHYDRAMINE,979096,Zinc Acetate,21602016,58295 +D04AA32,DIPHENHYDRAMINE,1129625,Diphenhydramine,21602016,3498 +D04AB,ANESTHETICS FOR TOPICAL USE,914840,Dichlorotetrafluoroethane,21602019,124848 +D04AB,ANESTHETICS FOR TOPICAL USE,917006,Benzocaine,21602019,1399 +D04AB,ANESTHETICS FOR TOPICAL USE,939726,butamben,21602019,19861 +D04AB,ANESTHETICS FOR TOPICAL USE,950316,Ethyl Chloride,21602019,4141 +D04AB,ANESTHETICS FOR TOPICAL USE,1036884,Tetracaine,21602019,10391 +D04AB01,LIDOCAINE,901656,Menthol,21602020,6750 +D04AB01,LIDOCAINE,916460,Benzalkonium,21602020,1378 +D04AB01,LIDOCAINE,916802,Benzethonium,21602020,1390 +D04AB01,LIDOCAINE,989878,Lidocaine,21602020,6387 +D04AB02,CINCHOCAINE,923840,Dibucaine,21602021,3339 +D04AB04,BENZOCAINE,901656,Menthol,21602023,6750 +D04AB04,BENZOCAINE,916802,Benzethonium,21602023,1390 +D04AB04,BENZOCAINE,917006,Benzocaine,21602023,1399 +D04AB04,BENZOCAINE,923540,phenol,21602023,33290 +D04AB04,BENZOCAINE,935390,resorcinol,21602023,35382 +D04AB04,BENZOCAINE,961145,Glycerin,21602023,4910 +D04AB04,BENZOCAINE,1704758,Triclosan,21602023,10795 +D04AB06,TETRACAINE,1036884,Tetracaine,21602025,10391 +D04AB07,PRAMOCAINE,901656,Menthol,21602026,6750 +D04AB07,PRAMOCAINE,902616,Calamine,21602026,106212 +D04AB07,PRAMOCAINE,904826,Lactic acid,21602026,28393 +D04AB07,PRAMOCAINE,916662,dimethicone,21602026,324072 +D04AB07,PRAMOCAINE,919681,Benzyl Alcohol,21602026,1426 +D04AB07,PRAMOCAINE,927478,pramoxine,21602026,34347 +D04AB07,PRAMOCAINE,966376,Allantoin,21602026,508 +D04AB07,PRAMOCAINE,979096,Zinc Acetate,21602026,58295 +D04AB07,PRAMOCAINE,19033354,Petrolatum,21602026,8091 +D04AX,OTHER ANTIPRURITICS,738156,Doxepin,21602027,3638 +D04AX,OTHER ANTIPRURITICS,901656,Menthol,21602027,6750 +D04AX,OTHER ANTIPRURITICS,902616,Calamine,21602027,106212 +D04AX,OTHER ANTIPRURITICS,911064,Zinc Oxide,21602027,11423 +D04AX,OTHER ANTIPRURITICS,923540,phenol,21602027,33290 +D04AX,OTHER ANTIPRURITICS,938205,Camphor,21602027,1952 +D04AX,OTHER ANTIPRURITICS,1036690,Tannic Acid,21602027,10328 +D04AX,OTHER ANTIPRURITICS,19092412,Chlorobutanol,21602027,2378 +D05AA,TARS,901656,Menthol,21602030,6750 +D05AA,TARS,935390,resorcinol,21602030,35382 +D05AA,TARS,964407,Salicylic Acid,21602030,9525 +D05AA,TARS,966376,Allantoin,21602030,508 +D05AA,TARS,1000995,Coal Tar,21602030,2635 +D05AC01,DITHRANOL,952538,Anthralin,21602032,873 +D05AD02,METHOXSALEN,905223,Methoxsalen,21602036,6854 +D05AX,OTHER ANTIPSORIATICS FOR TOPICAL USE,964407,Salicylic Acid,21602037,9525 +D05AX,OTHER ANTIPSORIATICS FOR TOPICAL USE,19009148,"Mercury, Ammoniated",21602037,29542 +D05AX02,CALCIPOTRIOL,908921,calcipotriene,21602039,29365 +D05AX05,TAZAROTENE,947416,tazarotene,21602042,83947 +D05BA01,TRIOXYSALEN,905829,Trioxsalen,21602046,10844 +D05BA02,METHOXSALEN,905223,Methoxsalen,21602047,6854 +D05BB01,ETRETINATE,19050554,Etretinate,21602050,4182 +D05BB02,ACITRETIN,929638,Acitretin,21602051,16818 +D05BX,OTHER ANTIPSORIATICS FOR SYSTEMIC USE,1036525,Sulfur,21602052,10223 +D05BX,OTHER ANTIPSORIATICS FOR SYSTEMIC USE,19082458,nickel sulfate,21602052,31738 +D05BX,OTHER ANTIPSORIATICS FOR SYSTEMIC USE,19095079,potassium bromide,21602052,34299 +D05BX51,"FUMARIC ACID DERIVATIVES, COMBINATIONS",19082458,nickel sulfate,21602053,31738 +D05BX51,"FUMARIC ACID DERIVATIVES, COMBINATIONS",19095079,potassium bromide,21602053,34299 +D05BX51,"FUMARIC ACID DERIVATIVES, COMBINATIONS",19126510,fumarate,21602053,70598 +D06AA02,CHLORTETRACYCLINE,19095043,Chlortetracycline,21602058,2408 +D06AA04,TETRACYCLINE,1836948,Tetracycline,21602060,10395 +D06AX02,CHLORAMPHENICOL,990069,Chloramphenicol,21602063,2348 +D06AX04,NEOMYCIN,915175,Bacitracin,21602064,1291 +D06AX04,NEOMYCIN,915981,Neomycin,21602064,7299 +D06AX04,NEOMYCIN,927478,pramoxine,21602064,34347 +D06AX04,NEOMYCIN,948582,Polymyxin B,21602064,8536 +D06AX04,NEOMYCIN,963742,Gramicidin,21602064,5011 +D06AX05,BACITRACIN,915175,Bacitracin,21602065,1291 +D06AX05,BACITRACIN,948582,Polymyxin B,21602065,8536 +D06AX07,GENTAMICIN,919345,Gentamicin Sulfate (USP),21602066,142438 +D06AX09,MUPIROCIN,951511,Mupirocin,21602068,42372 +D06AX13,RETAPAMULIN,991003,retapamulin,21602072,642274 +D06BA,SULFONAMIDES,906914,Urea,21602074,11002 +D06BA,SULFONAMIDES,1036252,Sulfacetamide,21602074,10169 +D06BA01,SILVER SULFADIAZINE,966956,Silver Sulfadiazine,21602075,9793 +D06BA02,SULFATHIAZOLE,1036487,sulfathiazole,21602076,10193 +D06BA03,MAFENIDE,992716,Mafenide,21602077,6572 +D06BB,ANTIVIRALS,921956,Sinecatechins,21602082,753346 +D06BB03,ACICLOVIR,1703687,Acyclovir,21602085,281 +D06BB04,PODOPHYLLOTOXIN,947651,podophyllin,21602086,8462 +D06BB04,PODOPHYLLOTOXIN,947705,podophyllotoxin,21602086,8463 +D06BB06,PENCICLOVIR,981654,penciclovir,21602088,59839 +D06BB10,IMIQUIMOD,981691,imiquimod,21602092,59943 +D06BB11,DOCOSANOL,980955,docosanol,21602093,594680 +D06BX01,METRONIDAZOLE,1707164,Metronidazole,21602096,6922 +D07AA01,METHYLPREDNISOLONE,1506270,Methylprednisolone,21602101,6902 +D07AA02,HYDROCORTISONE,964407,Salicylic Acid,21602102,9525 +D07AA02,HYDROCORTISONE,975125,Hydrocortisone,21602102,5492 +D07AA02,HYDROCORTISONE,985708,Ketoconazole,21602102,6135 +D07AA02,HYDROCORTISONE,1036525,Sulfur,21602102,10223 +D07AB02,HYDROCORTISONE BUTYRATE,975125,Hydrocortisone,21602106,5492 +D07AB03,FLUMETASONE,19055156,Flumethasone,21602107,4458 +D07AB08,DESONIDE,917205,Desonide,21602112,3254 +D07AB09,TRIAMCINOLONE,903963,Triamcinolone,21602113,10759 +D07AB11,HYDROCORTISONE BUTEPRATE,975125,Hydrocortisone,21602115,5492 +D07AB19,DEXAMETHASONE,1518254,Dexamethasone,21602116,3264 +D07AB21,CLOCORTOLONE,950882,clocortolone,21602117,21249 +D07AC01,BETAMETHASONE,920458,Betamethasone,21602120,1514 +D07AC03,DESOXIMETASONE,917336,Desoximetasone,21602122,3255 +D07AC04,FLUOCINOLONE ACETONIDE,996541,fluocinolone,21602123,25126 +D07AC07,FLUDROXYCORTIDE,956266,Flurandrenolide,21602126,4500 +D07AC08,FLUOCINONIDE,955252,Fluocinonide,21602127,4462 +D07AC10,DIFLORASONE,960988,Diflorasone,21602129,91311 +D07AC11,AMCINONIDE,930747,amcinonide,21602130,17652 +D07AC13,MOMETASONE,905233,Mometasone,21602132,108118 +D07AC17,FLUTICASONE,1149380,fluticasone,21602136,41126 +D07AC18,PREDNICARBATE,928110,prednicarbate,21602137,34369 +D07AC21,ULOBETASOL,949759,halobetasol,21602139,41208 +D07AD01,CLOBETASOL,998415,Clobetasol,21602141,2590 +D07AD02,HALCINONIDE,966468,Halcinonide,21602142,5084 +D07BA04,HYDROCORTISONE AND ANTISEPTICS,918172,Benzoyl Peroxide,21602146,1418 +D07BA04,HYDROCORTISONE AND ANTISEPTICS,928006,Iodoquinol,21602146,3435 +D07BA04,HYDROCORTISONE AND ANTISEPTICS,958994,Aloe Polysaccharide,21602146,476786 +D07BA04,HYDROCORTISONE AND ANTISEPTICS,975125,Hydrocortisone,21602146,5492 +D07BA04,HYDROCORTISONE AND ANTISEPTICS,980867,Clioquinol,21602146,5942 +D07CA01,HYDROCORTISONE AND ANTIBIOTICS,915175,Bacitracin,21602160,1291 +D07CA01,HYDROCORTISONE AND ANTIBIOTICS,915981,Neomycin,21602160,7299 +D07CA01,HYDROCORTISONE AND ANTIBIOTICS,928006,Iodoquinol,21602160,3435 +D07CA01,HYDROCORTISONE AND ANTIBIOTICS,948582,Polymyxin B,21602160,8536 +D07CA01,HYDROCORTISONE AND ANTIBIOTICS,975125,Hydrocortisone,21602160,5492 +D07CB01,TRIAMCINOLONE AND ANTIBIOTICS,903963,Triamcinolone,21602164,10759 +D07CB01,TRIAMCINOLONE AND ANTIBIOTICS,922570,Nystatin,21602164,7597 +D07CC01,BETAMETHASONE AND ANTIBIOTICS,920458,Betamethasone,21602170,1514 +D07CC01,BETAMETHASONE AND ANTIBIOTICS,1000632,Clotrimazole,21602170,2623 +D07XA,"CORTICOSTEROIDS, WEAK, OTHER COMBINATIONS",927478,pramoxine,21602179,34347 +D07XA,"CORTICOSTEROIDS, WEAK, OTHER COMBINATIONS",975125,Hydrocortisone,21602179,5492 +D07XA,"CORTICOSTEROIDS, WEAK, OTHER COMBINATIONS",980867,Clioquinol,21602179,5942 +D07XA01,HYDROCORTISONE,906914,Urea,21602180,11002 +D07XA01,HYDROCORTISONE,916802,Benzethonium,21602180,1390 +D07XA01,HYDROCORTISONE,927478,pramoxine,21602180,34347 +D07XA01,HYDROCORTISONE,958994,Aloe Polysaccharide,21602180,476786 +D07XA01,HYDROCORTISONE,975125,Hydrocortisone,21602180,5492 +D07XA01,HYDROCORTISONE,979096,Zinc Acetate,21602180,58295 +D07XA01,HYDROCORTISONE,990413,chlorcyclizine,21602180,2354 +D07XA01,HYDROCORTISONE,1129625,Diphenhydramine,21602180,3498 +D07XB02,TRIAMCINOLONE,903963,Triamcinolone,21602184,10759 +D07XB02,TRIAMCINOLONE,906914,Urea,21602184,11002 +D07XC01,BETAMETHASONE,908921,calcipotriene,21602190,29365 +D07XC01,BETAMETHASONE,920458,Betamethasone,21602190,1514 +D08AC02,CHLORHEXIDINE,1790812,Chlorhexidine,21602204,2358 +D08AC52,"CHLORHEXIDINE,COMBINATIONS",1790812,Chlorhexidine,21602208,2358 +D08AD,BORIC ACID PRODUCTS,929698,boric acid,21602209,1700 +D08AE01,HEXACHLOROPHENE,1768734,Hexachlorophene,21602211,5293 +D08AE03,PHENOL,923540,phenol,21602213,33290 +D08AE03,PHENOL,938205,Camphor,21602213,1952 +D08AE04,TRICLOSAN,1704758,Triclosan,21602214,10795 +D08AE05,CHLOROXYLENOL,949459,chloroxylenol,21602215,20877 +D08AF,NITROFURAN DERIVATIVES,920378,Nitrofurazone,21602217,7455 +D08AG02,POVIDONE-IODINE,1750087,Povidone-Iodine,21602221,8611 +D08AG02,POVIDONE-IODINE,19028106,Isopropyl Alcohol,21602221,797541 +D08AH30,CLIOQUINOL,980867,Clioquinol,21602228,5942 +D08AJ01,BENZALKONIUM,916460,Benzalkonium,21602230,1378 +D08AJ01,BENZALKONIUM,946340,Piperonyl Butoxide,21602230,8345 +D08AJ01,BENZALKONIUM,959665,Pyrethrins,21602230,8991 +D08AJ08,BENZETHONIUM CHLORIDE,916802,Benzethonium,21602236,1390 +D08AK04,MERCUROCHROME,1703026,Merbromin,21602244,6762 +D08AK06,THIOMERSAL,19137377,Thimerosal,21602246,10472 +D08AL01,SILVER NITRATE,966913,Silver Nitrate,21602249,9789 +D08AX,OTHER ANTISEPTICS AND DISINFECTANTS,949459,chloroxylenol,21602251,20877 +D08AX,OTHER ANTISEPTICS AND DISINFECTANTS,1761033,Glutaral,21602251,4888 +D08AX,OTHER ANTISEPTICS AND DISINFECTANTS,19060367,Pyrogallol,21602251,9022 +D08AX01,HYDROGEN PEROXIDE,1776430,Hydrogen Peroxide,21602252,5499 +D08AX05,ISOPROPANOL,19028106,Isopropyl Alcohol,21602256,797541 +D08AX06,POTASSIUM PERMANGANATE,19135788,Potassium Permanganate,21602257,8604 +D08AX07,SODIUM HYPOCHLORITE,1769774,Sodium Hypochlorite,21602258,9881 +D08AX08,ETHANOL,955372,Ethanol,21602259,448 +D10AB02,SULFUR,906914,Urea,21602289,11002 +D10AB02,SULFUR,918172,Benzoyl Peroxide,21602289,1418 +D10AB02,SULFUR,935390,resorcinol,21602289,35382 +D10AB02,SULFUR,964407,Salicylic Acid,21602289,9525 +D10AB02,SULFUR,975125,Hydrocortisone,21602289,5492 +D10AB02,SULFUR,1036252,Sulfacetamide,21602289,10169 +D10AB02,SULFUR,1036525,Sulfur,21602289,10223 +D10AD01,TRETINOIN,903643,Tretinoin,21602293,10753 +D10AD03,ADAPALENE,981774,adapalene,21602295,60223 +D10AD51,"TRETINOIN, COMBINATIONS",903643,Tretinoin,21602298,10753 +D10AD51,"TRETINOIN, COMBINATIONS",997881,Clindamycin,21602298,2582 +D10AD53,"ADAPALENE, COMBINATIONS",918172,Benzoyl Peroxide,21602299,1418 +D10AD53,"ADAPALENE, COMBINATIONS",981774,adapalene,21602299,60223 +D10AE01,BENZOYL PEROXIDE,787787,hyaluronate,21602302,62372 +D10AE01,BENZOYL PEROXIDE,918172,Benzoyl Peroxide,21602302,1418 +D10AE51,"BENZOYL PEROXIDE, COMBINATIONS",906914,Urea,21602303,11002 +D10AE51,"BENZOYL PEROXIDE, COMBINATIONS",918172,Benzoyl Peroxide,21602303,1418 +D10AE51,"BENZOYL PEROXIDE, COMBINATIONS",964407,Salicylic Acid,21602303,9525 +D10AF01,CLINDAMYCIN,997881,Clindamycin,21602305,2582 +D10AF02,ERYTHROMYCIN,1746940,Erythromycin,21602306,4053 +D10AF04,MECLOCYCLINE,19009022,meclocycline,21602308,29418 +D10AF51,"CLINDAMYCIN, COMBINATIONS",918172,Benzoyl Peroxide,21602309,1418 +D10AF51,"CLINDAMYCIN, COMBINATIONS",997881,Clindamycin,21602309,2582 +D10AF52,"ERYTHROMYCIN, COMBINATIONS",918172,Benzoyl Peroxide,21602310,1418 +D10AF52,"ERYTHROMYCIN, COMBINATIONS",1746940,Erythromycin,21602310,4053 +D10AX,OTHER ANTI-ACNE PREPARATIONS FOR TOPICAL USE,19018419,Niacinamide,21602311,7405 +D10AX02,RESORCINOL,923540,phenol,21602313,33290 +D10AX02,RESORCINOL,935390,resorcinol,21602313,35382 +D10AX03,AZELAIC ACID,986790,Azelate,21602314,618278 +D10AX05,DAPSONE,1711759,Dapsone,21602316,3108 +D10AX30,VARIOUS COMBINATIONS,964407,Salicylic Acid,21602317,9525 +D10AX30,VARIOUS COMBINATIONS,19028106,Isopropyl Alcohol,21602317,797541 +D10BA01,ISOTRETINOIN,984232,Isotretinoin,21602320,6064 +D10BX,OTHER ANTI-ACNE PREPARATIONS FOR SYSTEMIC USE,1387426,Folate,21602321,62356 +D10BX,OTHER ANTI-ACNE PREPARATIONS FOR SYSTEMIC USE,19010696,Zinc,21602321,11416 +D10BX,OTHER ANTI-ACNE PREPARATIONS FOR SYSTEMIC USE,19018419,Niacinamide,21602321,7405 +D11AA,ANTIHIDROTICS,929698,boric acid,21602325,1700 +D11AA,ANTIHIDROTICS,930604,aluminum acetate,21602325,17609 +D11AA,ANTIHIDROTICS,957393,aluminum chloride,21602325,46241 +D11AA,ANTIHIDROTICS,1756524,Formaldehyde,21602325,4530 +D11AC03,SELENIUM COMPOUNDS,901656,Menthol,21602329,6750 +D11AC03,SELENIUM COMPOUNDS,938061,selenium disulfide,21602329,36345 +D11AC06,POVIDONE-IODINE,1750087,Povidone-Iodine,21602330,8611 +D11AC30,OTHERS,904826,Lactic acid,21602333,28393 +D11AC30,OTHERS,916460,Benzalkonium,21602333,1378 +D11AC30,OTHERS,931035,pyrithione,21602333,35100 +D11AC30,OTHERS,944360,zinc pyrithione,21602333,39952 +D11AC30,OTHERS,949453,chloroxine,21602333,20875 +D11AC30,OTHERS,964407,Salicylic Acid,21602333,9525 +D11AC30,OTHERS,975125,Hydrocortisone,21602333,5492 +D11AC30,OTHERS,985708,Ketoconazole,21602333,6135 +D11AC30,OTHERS,1036525,Sulfur,21602333,10223 +D11AF,WART AND ANTI-CORN PREPARATIONS,964407,Salicylic Acid,21602336,9525 +D11AF,WART AND ANTI-CORN PREPARATIONS,19039679,Cantharidin,21602336,1984 +D11AH01,TACROLIMUS,950637,Tacrolimus,21602338,42316 +D11AH02,PIMECROLIMUS,915935,Pimecrolimus,21602339,321952 +D11AX,OTHER DERMATOLOGICALS,903643,Tretinoin,21602341,10753 +D11AX,OTHER DERMATOLOGICALS,904525,bimatoprost,21602341,283810 +D11AX,OTHER DERMATOLOGICALS,911638,glycolate,21602341,70603 +D11AX,OTHER DERMATOLOGICALS,920113,mequinol,21602341,15080 +D11AX,OTHER DERMATOLOGICALS,925209,N6-furfuryladenine,21602341,16054 +D11AX,OTHER DERMATOLOGICALS,927194,Dihydroxyacetone,21602341,3430 +D11AX,OTHER DERMATOLOGICALS,986790,Azelate,21602341,618278 +D11AX,OTHER DERMATOLOGICALS,987009,Trichloroacetate,21602341,618564 +D11AX,OTHER DERMATOLOGICALS,1036690,Tannic Acid,21602341,10328 +D11AX,OTHER DERMATOLOGICALS,19027308,Potassium Hydroxide,21602341,34311 +D11AX,OTHER DERMATOLOGICALS,19056581,ALPHA HYDROXY ACIDS,21602341,236797 +D11AX01,MINOXIDIL,1309068,Minoxidil,21602342,6984 +D11AX02,GAMOLENIC ACID,19086939,gamma-Linolenate,21602343,618453 +D11AX03,CALCIUM GLUCONATE,19037038,Calcium Gluconate,21602344,1908 +D11AX11,HYDROQUINONE,903643,Tretinoin,21602351,10753 +D11AX11,HYDROQUINONE,976778,hydroquinone,21602351,5509 +D11AX11,HYDROQUINONE,996416,Finasteride,21602351,25025 +D11AX11,HYDROQUINONE,996541,fluocinolone,21602351,25126 +D11AX11,HYDROQUINONE,19011773,Ascorbic Acid,21602351,1151 +D11AX12,PYRITHIONE ZINC,901656,Menthol,21602352,6750 +D11AX12,PYRITHIONE ZINC,944360,zinc pyrithione,21602352,39952 +D11AX13,MONOBENZONE,929983,monobenzone,21602353,17145 +D11AX16,EFLORNITHINE,978236,Eflornithine,21602354,569 +D11AX19,ALITRETINOIN,941052,alitretinoin,0,81864 +D11AX52,"GAMOLENIC ACID, COMBINATIONS",19009540,Vitamin E,21602357,11256 +D11AX52,"GAMOLENIC ACID, COMBINATIONS",19086939,gamma-Linolenate,21602357,618453 +G01AA01,NYSTATIN,922570,Nystatin,21602363,7597 +G01AA05,CHLORAMPHENICOL,990069,Chloramphenicol,21602367,2348 +G01AA10,CLINDAMYCIN,997881,Clindamycin,21602372,2582 +G01AC30,OXYQUINOLINE,906874,Oxyquinoline,21602383,110 +G01AC30,OXYQUINOLINE,929549,Acetic Acid,21602383,168 +G01AD,ORGANIC ACIDS,906874,Oxyquinoline,21602384,110 +G01AD,ORGANIC ACIDS,929549,Acetic Acid,21602384,168 +G01AD,ORGANIC ACIDS,19123754,Ricinoleate,21602384,618482 +G01AF01,METRONIDAZOLE,1707164,Metronidazole,21602392,6922 +G01AF02,CLOTRIMAZOLE,1000632,Clotrimazole,21602393,2623 +G01AF04,MICONAZOLE,907879,Miconazole,21602394,6932 +G01AF08,TIOCONAZOLE,942028,tioconazole,21602398,38298 +G01AF15,BUTOCONAZOLE,939784,butoconazole,21602403,19884 +G01AG02,TERCONAZOLE,941472,terconazole,21602409,37806 +G01AX06,FURAZOLIDONE,1756822,Furazolidone,21602415,4601 +G01AX09,METHYLROSANILINE,959362,Gentian Violet,21602416,4778 +G01AX11,POVIDONE-IODINE,1750087,Povidone-Iodine,21602417,8611 +G02AB01,METHYLERGOMETRINE,1305637,Methylergonovine,21602432,6883 +G02AB02,ERGOT ALKALOIDS,19102230,Ergot Alkaloids,21602433,4023 +G02AB03,ERGOMETRINE,1345205,Ergonovine,21602434,4021 +G02AD01,DINOPROST,19029421,Dinoprost,21602438,3477 +G02AD02,DINOPROSTONE,1329415,Dinoprostone,21602439,3478 +G02AD04,CARBOPROST,19049150,Carboprost,21602441,2051 +G02BA03,PLASTIC IUD WITH PROGESTOGEN,1589505,Levonorgestrel,21602449,6373 +G02BB,INTRAVAGINAL CONTRACEPTIVES,969444,Nonoxynol-9,21602450,53750 +G02BB,INTRAVAGINAL CONTRACEPTIVES,970277,Octoxynol-9,21602450,54034 +G02CA01,RITODRINE,1563413,Ritodrine,21602454,9392 +G02CB01,BROMOCRIPTINE,730548,Bromocriptine,21602458,1760 +G02CB03,CABERGOLINE,1558471,cabergoline,21602460,47579 +G03AA01,ETYNODIOL AND ESTROGEN,1503184,Mestranol,21602474,6782 +G03AA01,ETYNODIOL AND ESTROGEN,1549786,Ethinyl Estradiol,21602474,4124 +G03AA01,ETYNODIOL AND ESTROGEN,1595461,ethynodiol,21602474,24591 +G03AA05,NORETHISTERONE AND ESTROGEN,1503184,Mestranol,21602478,6782 +G03AA05,NORETHISTERONE AND ESTROGEN,1521369,Norethindrone,21602478,7514 +G03AA05,NORETHISTERONE AND ESTROGEN,1549786,Ethinyl Estradiol,21602478,4124 +G03AA05,NORETHISTERONE AND ESTROGEN,1595799,Ferrous fumarate,21602478,24941 +G03AA06,NORGESTREL AND ESTROGEN,1521592,Norgestrel,21602479,7518 +G03AA06,NORGESTREL AND ESTROGEN,1549786,Ethinyl Estradiol,21602479,4124 +G03AA07,LEVONORGESTREL AND ESTROGEN,1549786,Ethinyl Estradiol,21602480,4124 +G03AA07,LEVONORGESTREL AND ESTROGEN,1589505,Levonorgestrel,21602480,6373 +G03AA08,MEDROXYPROGESTERONE AND ESTROGEN,1500211,Medroxyprogesterone,21602481,6691 +G03AA08,MEDROXYPROGESTERONE AND ESTROGEN,1548195,Estradiol,21602481,4083 +G03AA09,DESOGESTREL AND ESTROGEN,1549786,Ethinyl Estradiol,21602482,4124 +G03AA09,DESOGESTREL AND ESTROGEN,1588000,Desogestrel,21602482,22656 +G03AA11,NORGESTIMATE AND ESTROGEN,1515774,norgestimate,21602484,31994 +G03AA11,NORGESTIMATE AND ESTROGEN,1549786,Ethinyl Estradiol,21602484,4124 +G03AA12,DROSPIRENONE AND ESTROGEN,1512674,drospirenone,21602485,11636 +G03AA12,DROSPIRENONE AND ESTROGEN,1549786,Ethinyl Estradiol,21602485,4124 +G03AA13,NORELGESTROMIN AND ESTROGEN,1518198,norelgestromin,21602486,326374 +G03AA13,NORELGESTROMIN AND ESTROGEN,1549786,Ethinyl Estradiol,21602486,4124 +G03AB03,LEVONORGESTREL AND ESTROGEN,1548195,Estradiol,21602491,4083 +G03AB03,LEVONORGESTREL AND ESTROGEN,1549786,Ethinyl Estradiol,21602491,4124 +G03AB03,LEVONORGESTREL AND ESTROGEN,1589505,Levonorgestrel,21602491,6373 +G03AB04,NORETHISTERONE AND ESTROGEN,1521369,Norethindrone,21602492,7514 +G03AB04,NORETHISTERONE AND ESTROGEN,1549786,Ethinyl Estradiol,21602492,4124 +G03AB04,NORETHISTERONE AND ESTROGEN,1595799,Ferrous fumarate,21602492,24941 +G03AC,PROGESTOGENS,1521592,Norgestrel,21602496,7518 +G03AC01,NORETHISTERONE,1521369,Norethindrone,21602497,7514 +G03AC03,LEVONORGESTREL,1549786,Ethinyl Estradiol,21602499,4124 +G03AC03,LEVONORGESTREL,1589505,Levonorgestrel,21602499,6373 +G03AC06,MEDROXYPROGESTERONE,1500211,Medroxyprogesterone,21602502,6691 +G03AC08,ETONOGESTREL,1519936,Etonogestrel,21602504,14584 +G03BA01,FLUOXYMESTERONE,1555887,Fluoxymesterone,21602508,4494 +G03BA02,METHYLTESTOSTERONE,1506602,Methyltestosterone,21602509,6904 +G03BA03,TESTOSTERONE,1636780,Testosterone,21602510,10379 +G03CA,"NATURAL AND SEMISYNTHETIC ESTROGENS, PLAIN",1551673,"Estrogens, Esterified (USP)",21602515,214549 +G03CA01,ETHINYLESTRADIOL,1549786,Ethinyl Estradiol,21602516,4124 +G03CA01,ETHINYLESTRADIOL,1588000,Desogestrel,21602516,22656 +G03CA01,ETHINYLESTRADIOL,1589505,Levonorgestrel,21602516,6373 +G03CA03,ESTRADIOL,1515774,norgestimate,21602517,31994 +G03CA03,ESTRADIOL,1548195,Estradiol,21602517,4083 +G03CA06,CHLOROTRIANISENE,19092684,Chlorotrianisene,21602519,2397 +G03CA07,ESTRONE,1525278,estropipate,21602520,33747 +G03CA07,ESTRONE,1549254,Estrone,21602520,4103 +G03CA57,CONJUGATED ESTROGENS,1500211,Medroxyprogesterone,21602523,6691 +G03CA57,CONJUGATED ESTROGENS,1549080,"Estrogens, Conjugated (USP)",21602523,4099 +G03CA57,CONJUGATED ESTROGENS,1586808,"estrogens, conjugated synthetic B",21602523,618365 +G03CA57,CONJUGATED ESTROGENS,1596779,"estrogens, conjugated synthetic A",21602523,253166 +G03CB01,DIENESTROL,925102,Dienestrol,21602525,3368 +G03CC,"ESTROGENS, COMBINATIONS WITH OTHER DRUGS",702865,Meprobamate,21602529,6760 +G03CC,"ESTROGENS, COMBINATIONS WITH OTHER DRUGS",990678,Chlordiazepoxide,21602529,2356 +G03CC,"ESTROGENS, COMBINATIONS WITH OTHER DRUGS",1549080,"Estrogens, Conjugated (USP)",21602529,4099 +G03CC,"ESTROGENS, COMBINATIONS WITH OTHER DRUGS",1551673,"Estrogens, Esterified (USP)",21602529,214549 +G03DA02,MEDROXYPROGESTERONE,1500211,Medroxyprogesterone,21602540,6691 +G03DA02,MEDROXYPROGESTERONE,1549080,"Estrogens, Conjugated (USP)",21602540,4099 +G03DA03,HYDROXYPROGESTERONE,19077143,Hydroxyprogesterone,21602541,5542 +G03DA04,PROGESTERONE,1552310,Progesterone,21602542,8727 +G03DC02,NORETHISTERONE,1521369,Norethindrone,21602553,7514 +G03EA,ANDROGENS AND ESTROGENS,1549786,Ethinyl Estradiol,21602559,4124 +G03EA,ANDROGENS AND ESTROGENS,1555887,Fluoxymesterone,21602559,4494 +G03EA02,TESTOSTERONE AND ESTROGEN,1548195,Estradiol,21602561,4083 +G03EA02,TESTOSTERONE AND ESTROGEN,1636780,Testosterone,21602561,10379 +G03EK01,METHYLTESTOSTERONE,1506602,Methyltestosterone,21602565,6904 +G03EK01,METHYLTESTOSTERONE,1525866,Diethylstilbestrol,21602565,3390 +G03EK01,METHYLTESTOSTERONE,1549080,"Estrogens, Conjugated (USP)",21602565,4099 +G03EK01,METHYLTESTOSTERONE,1551673,"Estrogens, Esterified (USP)",21602565,214549 +G03FA01,NORETHISTERONE AND ESTROGEN,1503184,Mestranol,21602568,6782 +G03FA01,NORETHISTERONE AND ESTROGEN,1521369,Norethindrone,21602568,7514 +G03FA01,NORETHISTERONE AND ESTROGEN,1548195,Estradiol,21602568,4083 +G03FA01,NORETHISTERONE AND ESTROGEN,1549786,Ethinyl Estradiol,21602568,4124 +G03FA01,NORETHISTERONE AND ESTROGEN,1595799,Ferrous fumarate,21602568,24941 +G03FA09,NORETYNODREL AND ESTROGEN,1503184,Mestranol,21602576,6782 +G03FA12,MEDROXYPROGESTERONE AND ESTROGEN,1500211,Medroxyprogesterone,21602579,6691 +G03FA12,MEDROXYPROGESTERONE AND ESTROGEN,1549080,"Estrogens, Conjugated (USP)",21602579,4099 +G03FA13,NORGESTIMATE AND ESTROGEN,1515774,norgestimate,21602580,31994 +G03FA13,NORGESTIMATE AND ESTROGEN,1548195,Estradiol,21602580,4083 +G03FA17,DROSPIRENONE AND ESTROGEN,1512674,drospirenone,21602584,11636 +G03FA17,DROSPIRENONE AND ESTROGEN,1549786,Ethinyl Estradiol,21602584,4124 +G03FB09,LEVONORGESTREL AND ESTROGEN,1548195,Estradiol,21602594,4083 +G03FB09,LEVONORGESTREL AND ESTROGEN,1589505,Levonorgestrel,21602594,6373 +G03GA01,CHORIONIC GONADOTROPIN,1563600,Chorionic Gonadotropin,21602599,4986 +G03GA01,CHORIONIC GONADOTROPIN,19071182,"HCG ALPHA,RECOMBINANT",21602599,283783 +G03GA02,HUMAN MENOPAUSAL GONADOTROPIN,1588712,Follicle Stimulating Hormone,21602600,227518 +G03GA02,HUMAN MENOPAUSAL GONADOTROPIN,1589795,Luteinizing Hormone,21602600,6383 +G03GA04,UROFOLLITROPIN,1515417,Urofollitropin,21602602,134404 +G03GA05,FOLLITROPIN ALFA,1542948,Follitropin Alfa,21602603,386938 +G03GA06,FOLLITROPIN BETA,1597235,follitropin beta,21602604,25357 +G03GA07,LUTROPIN ALFA,1543112,Lutropin alfa,21602605,388084 +G03GB02,CLOMIFENE,1598819,Clomiphene,21602611,2596 +G03XA01,DANAZOL,1511449,Danazol,21602620,3102 +G03XB01,MIFEPRISTONE,1508439,Mifepristone,21602623,6964 +G03XC01,RALOXIFENE,1513103,Raloxifene,21602625,72143 +G04BA,ACIDIFIERS,939871,sodium phosphate,21602629,36709 +G04BA,ACIDIFIERS,19027362,potassium phosphate,21602629,34322 +G04BA,ACIDIFIERS,19060837,Racemethionine,21602629,9100 +G04BA01,AMMONIUM CHLORIDE,912362,Ammonium Chloride,21602630,712 +G04BC,URINARY CONCREMENT SOLVENTS,908464,magnesium carbonate,21602632,29155 +G04BC,URINARY CONCREMENT SOLVENTS,950435,Citric Acid,21602632,21183 +G04BC,URINARY CONCREMENT SOLVENTS,976545,potassium citrate,21602632,54993 +G04BC,URINARY CONCREMENT SOLVENTS,977968,sodium citrate,21602632,56466 +G04BC,URINARY CONCREMENT SOLVENTS,993631,Magnesium Oxide,21602632,6582 +G04BC,URINARY CONCREMENT SOLVENTS,998392,Gluconolactone,21602632,25842 +G04BC,URINARY CONCREMENT SOLVENTS,1353228,Vitamin B6,21602632,42954 +G04BD02,FLAVOXATE,954853,Flavoxate,21602635,4440 +G04BD04,OXYBUTYNIN,918906,oxybutynin,21602637,32675 +G04BD08,SOLIFENACIN,916005,Solifenacin,21602641,322167 +G04BD10,DARIFENACIN,916230,darifenacin,21602643,136198 +G04BD11,FESOTERODINE,19027958,fesoterodine,21602644,797195 +G04BE01,ALPROSTADIL,1381504,Alprostadil,21602646,598 +G04BE03,SILDENAFIL,1316262,sildenafil,21602648,136411 +G04BE04,YOHIMBIN,1385800,Yohimbe Preparation,21602649,220982 +G04BE08,TADALAFIL,1336926,tadalafil,21602653,358263 +G04BE09,VARDENAFIL,1311276,vardenafil,21602654,306674 +G04BE30,COMBINATIONS,1326901,Papaverine,21602655,7895 +G04BE30,COMBINATIONS,1335539,Phentolamine,21602655,8153 +G04BE30,COMBINATIONS,1385800,Yohimbe Preparation,21602655,220982 +G04BE30,COMBINATIONS,19044522,Zinc Sulfate,21602655,39954 +G04BX,OTHER UROLOGICALS,976545,potassium citrate,21602657,54993 +G04BX03,ACETOHYDROXAMIC ACID,929542,acetohydroxamic acid,21602659,16728 +G04BX06,PHENAZOPYRIDINE,923672,Hyoscyamine,21602660,153970 +G04BX06,PHENAZOPYRIDINE,933724,Phenazopyridine,21602660,8120 +G04BX06,PHENAZOPYRIDINE,959174,butabarbital,21602660,477631 +G04BX13,DIMETHYL SULFOXIDE,928980,Dimethyl Sulfoxide,21602664,3455 +G04CA01,ALFUZOSIN,930021,alfuzosin,21602668,17300 +G04CA02,TAMSULOSIN,924566,tamsulosin,21602669,77492 +G04CA03,TERAZOSIN,1341238,Terazosin,21602670,37798 +G04CA04,SILODOSIN,19012925,silodosin,21602671,720825 +G04CB01,FINASTERIDE,996416,Finasteride,21602675,25025 +G04CB02,DUTASTERIDE,989482,Dutasteride,21602676,228790 +G04CX,OTHER DRUGS USED IN BENIGN PROSTATIC HYPERTROPHY,1391307,Saw palmetto extract,21602677,236344 +G04CX,OTHER DRUGS USED IN BENIGN PROSTATIC HYPERTROPHY,19004810,Copper Gluconate,21602677,2839 +G04CX,OTHER DRUGS USED IN BENIGN PROSTATIC HYPERTROPHY,19010696,Zinc,21602677,11416 +G04CX,OTHER DRUGS USED IN BENIGN PROSTATIC HYPERTROPHY,19017671,Ginseng Preparation,21602677,325526 +G04CX,OTHER DRUGS USED IN BENIGN PROSTATIC HYPERTROPHY,19079011,African Pygeum Extract,21602677,580117 +G04CX,OTHER DRUGS USED IN BENIGN PROSTATIC HYPERTROPHY,19079204,Zinc Gluconate,21602677,58300 +G04CX,OTHER DRUGS USED IN BENIGN PROSTATIC HYPERTROPHY,19112533,Pumpkin seed oil extract,21602677,466570 +G04CX01,PYGEUM AFRICANUM,1391440,Pygeum Africanum Preparation,21602678,236466 +G04CX02,SERENOA REPENS,1391307,Saw palmetto extract,21602679,236344 +G04CX02,SERENOA REPENS,19059155,Saw Palmetto Fruit Extract,21602679,477189 +G04CX02,SERENOA REPENS,19079390,ZINC PICOLINATE,21602679,58301 +H01AA01,CORTICOTROPIN,1541079,Corticotropin,21602685,376 +H01AA02,TETRACOSACTIDE,19008009,Cosyntropin,21602686,2890 +H01AC01,SOMATROPIN,1584910,Somatropin,21602690,61148 +H01AC02,SOMATREM,1578181,somatrem,21602691,56570 +H01AC03,MECASERMIN,1502877,mecasermin,21602692,274403 +H01AC04,SERMORELIN,19077457,Sermorelin,21602693,56188 +H01AC05,MECASERMIN RINFABATE,1586449,mecasermin rinfabate,21602694,616877 +H01AX01,PEGVISOMANT,1503432,pegvisomant,21602696,278739 +H01BA01,VASOPRESSIN,1507835,Vasopressin (USP),21602699,11149 +H01BA02,DESMOPRESSIN,1517070,desmopressin,21602700,3251 +H01BA03,LYPRESSIN,19092373,lypressin,21602701,6531 +H01BB02,OXYTOCIN,1326115,Oxytocin,21602707,7824 +H01CA,GONADOTROPIN-RELEASING HORMONES,1351541,Leuprolide,21602710,42375 +H01CA01,GONADORELIN,19089810,Gonadorelin,21602711,6384 +H01CA03,HISTRELIN,1366773,histrelin,21602713,50975 +H01CB02,OCTREOTIDE,1522957,Octreotide,21602716,7617 +H02AA02,FLUDROCORTISONE,1555120,Fludrocortisone,21602726,4452 +H02AA03,DESOXYCORTONE,19017895,Deoxycorticosterone,21602727,3256 +H02AB01,BETAMETHASONE,920458,Betamethasone,21602729,1514 +H02AB02,DEXAMETHASONE,1518254,Dexamethasone,21602730,3264 +H02AB04,METHYLPREDNISOLONE,1506270,Methylprednisolone,21602732,6902 +H02AB05,PARAMETHASONE,19027186,Paramethasone,21602733,7910 +H02AB06,PREDNISOLONE,1550557,prednisolone,21602734,8638 +H02AB07,PREDNISONE,1551099,Prednisone,21602735,8640 +H02AB08,TRIAMCINOLONE,903963,Triamcinolone,21602736,10759 +H02AB09,HYDROCORTISONE,975125,Hydrocortisone,21602737,5492 +H02AB10,CORTISONE,1507705,Cortisone,21602738,2878 +H02AB15,MEPREDNISONE,19009116,meprednisone,21602743,29523 +H02CA01,TRILOSTANE,19042801,trilostane,21602750,38668 +H03AA01,LEVOTHYROXINE SODIUM,1501700,Thyroxine,21602754,10582 +H03AA02,LIOTHYRONINE SODIUM,1505346,Triiodothyronine,21602755,10814 +H03AA03,COMBINATIONS OF LEVOTHYROXINE AND LIOTHYRONINE,1501700,Thyroxine,21602756,10582 +H03AA03,COMBINATIONS OF LEVOTHYROXINE AND LIOTHYRONINE,1505346,Triiodothyronine,21602756,10814 +H03AA05,THYROID GLAND PREPARATIONS,1501309,Desiccated Thyroid Extract,21602758,10572 +H03AA05,THYROID GLAND PREPARATIONS,1590418,THYROID (PORK),21602758,235479 +H03AA05,THYROID GLAND PREPARATIONS,1590479,THYROID STRONG,21602758,235480 +H03AA05,THYROID GLAND PREPARATIONS,19000732,Thyroglobulin,21602758,10565 +H03AA05,THYROID GLAND PREPARATIONS,19017575,THYROID (BEEF),21602758,325521 +H03AA05,THYROID GLAND PREPARATIONS,19032857,Thyroid preparation,21602758,80697 +H03BA02,PROPYLTHIOURACIL,1554072,Propylthiouracil,21602762,8794 +H03BB02,THIAMAZOLE,1504620,Methimazole,21602766,6835 +H03CA,IODINE THERAPY,1103137,iodinated glycerol,21602774,27723 +H03CA,IODINE THERAPY,1780601,Iodine,21602774,5933 +H03CA,IODINE THERAPY,19049909,Potassium Iodide,21602774,8597 +H03CA,IODINE THERAPY,19069873,Sodium Iodide,21602774,9884 +H04AA01,GLUCAGON,1560278,Glucagon,21602778,4832 +H05AA02,TERIPARATIDE,1521987,Teriparatide,21602783,32915 +H05BA01,CALCITONIN (SALMON SYNTHETIC),1537655,salmon calcitonin,21602787,36118 +H05BX01,CINACALCET,1548111,cinacalcet,21602792,407990 +H05BX02,PARICALCITOL,1517740,paricalcitol,21602793,73710 +H05BX03,DOXERCALCIFEROL,1512446,Doxercalciferol,21602794,11516 +J01AA01,DEMECLOCYCLINE,1714527,Demeclocycline,21602799,3154 +J01AA02,DOXYCYCLINE,964407,Salicylic Acid,21602800,9525 +J01AA02,DOXYCYCLINE,1738521,Doxycycline,21602800,3640 +J01AA05,METACYCLINE,19003644,Methacycline,21602803,6812 +J01AA06,OXYTETRACYCLINE,925952,Oxytetracycline,21602804,7821 +J01AA07,TETRACYCLINE,937791,bismuth subsalicylate,21602805,19478 +J01AA07,TETRACYCLINE,1707164,Metronidazole,21602805,6922 +J01AA07,TETRACYCLINE,1836948,Tetracycline,21602805,10395 +J01AA08,MINOCYCLINE,1708880,Minocycline,21602806,6980 +J01AA12,TIGECYCLINE,1742432,tigecycline,21602810,384455 +J01AA56,"OXYTETRACYCLINE, COMBINATIONS",925952,Oxytetracycline,21602812,7821 +J01AA56,"OXYTETRACYCLINE, COMBINATIONS",989878,Lidocaine,21602812,6387 +J01BA01,CHLORAMPHENICOL,990069,Chloramphenicol,21602815,2348 +J01CA01,AMPICILLIN,1717327,Ampicillin,21602820,733 +J01CA03,CARBENICILLIN,1740546,Carbenicillin,21602822,2015 +J01CA04,AMOXICILLIN,929887,lansoprazole,21602823,17128 +J01CA04,AMOXICILLIN,1713332,Amoxicillin,21602823,723 +J01CA04,AMOXICILLIN,1750500,Clarithromycin,21602823,21212 +J01CA05,CARINDACILLIN,1740546,Carbenicillin,21602824,2015 +J01CA06,BACAMPICILLIN,1734205,bacampicillin,21602825,18687 +J01CA09,AZLOCILLIN,19015123,Azlocillin,21602828,1266 +J01CA10,MEZLOCILLIN,19007701,Mezlocillin,21602829,6927 +J01CA12,PIPERACILLIN,1746114,Piperacillin,21602831,8339 +J01CA13,TICARCILLIN,1702364,Ticarcillin,21602832,10591 +J01CA18,HETACILLIN,19069006,hetacillin,21602837,26797 +J01CE01,BENZYLPENICILLIN,1728416,Penicillin G,21602841,7980 +J01CE02,PHENOXYMETHYLPENICILLIN,1729720,Penicillin V,21602842,7984 +J01CE08,BENZATHINE BENZYLPENICILLIN,1728416,Penicillin G,21602848,7980 +J01CE09,PROCAINE BENZYLPENICILLIN,1728416,Penicillin G,21602849,7980 +J01CF,BETA-LACTAMASE RESISTANT PENICILLINS,1713930,Nafcillin,21602852,7233 +J01CF01,DICLOXACILLIN,1724666,Dicloxacillin,21602853,3356 +J01CF02,CLOXACILLIN,1800835,Cloxacillin,21602854,2625 +J01CF03,METHICILLIN,19001323,Methicillin Sodium,21602855,267073 +J01CF04,OXACILLIN,1724703,Oxacillin,21602856,7773 +J01CR01,AMPICILLIN AND ENZYME INHIBITOR,1717327,Ampicillin,21602862,733 +J01CR01,AMPICILLIN AND ENZYME INHIBITOR,1836241,Sulbactam,21602862,10167 +J01CR02,AMOXICILLIN AND ENZYME INHIBITOR,1713332,Amoxicillin,21602863,723 +J01CR02,AMOXICILLIN AND ENZYME INHIBITOR,1759842,Clavulanate,21602863,48203 +J01CR03,TICARCILLIN AND ENZYME INHIBITOR,1702364,Ticarcillin,21602864,10591 +J01CR03,TICARCILLIN AND ENZYME INHIBITOR,1759842,Clavulanate,21602864,48203 +J01CR05,PIPERACILLIN AND ENZYME INHIBITOR,1741122,tazobactam,21602866,37617 +J01CR05,PIPERACILLIN AND ENZYME INHIBITOR,1746114,Piperacillin,21602866,8339 +J01CR50,COMBINATIONS OF PENICILLINS,1728416,Penicillin G,21602867,7980 +J01DB01,CEFALEXIN,1786621,Cephalexin,21602870,2231 +J01DB03,CEFALOTIN,19086759,Cephalothin,21602872,2236 +J01DB04,CEFAZOLIN,1771162,Cefazolin,21602873,2180 +J01DB05,CEFADROXIL,1769535,Cefadroxil,21602874,2177 +J01DB08,CEFAPIRIN,19086790,Cephapirin,21602877,2238 +J01DB09,CEFRADINE,1786842,Cephradine,21602878,2239 +J01DC01,CEFOXITIN,1775741,Cefoxitin,21602883,2189 +J01DC02,CEFUROXIME,1778162,Cefuroxime,21602884,2194 +J01DC03,CEFAMANDOLE,19070174,Cefamandole,21602885,2178 +J01DC04,CEFACLOR,1768849,Cefaclor,21602886,2176 +J01DC05,CEFOTETAN,1774932,Cefotetan,21602887,2187 +J01DC06,CEFONICIDE,19072857,Cefonicid,21602888,2183 +J01DC08,LORACARBEF,1708100,loracarbef,21602890,28981 +J01DC09,CEFMETAZOLE,19072255,Cefmetazole,21602891,2182 +J01DC10,CEFPROZIL,1738366,cefprozil,21602892,19552 +J01DD01,CEFOTAXIME,1774470,Cefotaxime,21602895,2186 +J01DD02,CEFTAZIDIME,1776684,Ceftazidime,21602896,2191 +J01DD04,CEFTRIAXONE,1777806,Ceftriaxone,21602898,2193 +J01DD07,CEFTIZOXIME,1777254,Ceftizoxime,21602901,2192 +J01DD08,CEFIXIME,1796435,Cefixime,21602902,25033 +J01DD12,CEFOPERAZONE,1773402,Cefoperazone,21602906,2184 +J01DD13,CEFPODOXIME,1749008,cefpodoxime,21602907,20489 +J01DD14,CEFTIBUTEN,1749083,ceftibuten,21602908,20492 +J01DD15,CEFDINIR,1796458,cefdinir,21602909,25037 +J01DD16,CEFDITOREN,1747005,cefditoren,21602910,83682 +J01DE01,CEFEPIME,1748975,cefepime,21602915,20481 +J01DF01,AZTREONAM,1715117,Aztreonam,21602919,1272 +J01DH02,MEROPENEM,1709170,meropenem,21602921,29561 +J01DH03,ERTAPENEM,1717963,ertapenem,21602922,325642 +J01DH04,DORIPENEM,1713905,doripenem,21602923,119771 +J01DH51,IMIPENEM AND ENZYME INHIBITOR,1778262,Imipenem,21602925,5690 +J01DH51,IMIPENEM AND ENZYME INHIBITOR,1797258,Cilastatin,21602925,2540 +J01EA01,TRIMETHOPRIM,1705674,Trimethoprim,21602931,10829 +J01EB,SHORT-ACTING SULFONAMIDES,19026707,sulfacytine,21602934,78902 +J01EB02,SULFAMETHIZOLE,1036425,Sulfamethizole,21602936,10179 +J01EB04,SULFAPYRIDINE,19136493,Sulfapyridine,21602938,10188 +J01EB05,SULFAFURAZOLE,933724,Phenazopyridine,21602939,8120 +J01EB05,SULFAFURAZOLE,1836503,Sulfisoxazole,21602939,10207 +J01EB06,SULFANILAMIDE,1036475,Sulfanilamide,21602940,10184 +J01EC01,SULFAMETHOXAZOLE,933724,Phenazopyridine,21602945,8120 +J01EC01,SULFAMETHOXAZOLE,1836430,Sulfamethoxazole,21602945,10180 +J01EC02,SULFADIAZINE,1836391,Sulfadiazine,21602946,10171 +J01EE01,SULFAMETHOXAZOLE AND TRIMETHOPRIM,1705674,Trimethoprim,21602961,10829 +J01EE01,SULFAMETHOXAZOLE AND TRIMETHOPRIM,1836430,Sulfamethoxazole,21602961,10180 +J01FA01,ERYTHROMYCIN,1746940,Erythromycin,21602970,4053 +J01FA08,TROLEANDOMYCIN,19006043,Troleandomycin,21602976,10864 +J01FA09,CLARITHROMYCIN,929887,lansoprazole,21602977,17128 +J01FA09,CLARITHROMYCIN,1713332,Amoxicillin,21602977,723 +J01FA09,CLARITHROMYCIN,1750500,Clarithromycin,21602977,21212 +J01FA10,AZITHROMYCIN,1712549,trovafloxacin,21602978,115552 +J01FA10,AZITHROMYCIN,1734104,Azithromycin,21602978,18631 +J01FA13,DIRITHROMYCIN,1790024,dirithromycin,21602981,23437 +J01FA15,TELIITHROMYCIN,1702911,telithromycin,21602983,274786 +J01FF01,CLINDAMYCIN,997881,Clindamycin,21602985,2582 +J01FF02,LINCOMYCIN,1790692,Lincomycin,21602986,6398 +J01FG02,QUINUPRISTIN/DALFOPRISTIN,1789515,quinupristin,21602989,229367 +J01FG02,QUINUPRISTIN/DALFOPRISTIN,1789517,dalfopristin,21602989,229369 +J01GA01,STREPTOMYCIN,1836191,Streptomycin,21602992,10109 +J01GB01,TOBRAMYCIN,902722,Tobramycin,21602995,10627 +J01GB03,GENTAMICIN,919345,Gentamicin Sulfate (USP),21602996,142438 +J01GB04,KANAMYCIN,1784749,Kanamycin,21602997,6099 +J01GB05,NEOMYCIN,915981,Neomycin,21602998,7299 +J01GB06,AMIKACIN,1790868,Amikacin,21602999,641 +J01GB07,NETILMICIN,19017585,Netilmicin,21603000,7337 +J01MA,FLUOROQUINOLONES,19018154,alatrofloxacin,21603007,141440 +J01MA01,OFLOXACIN,923081,Ofloxacin,21603008,7623 +J01MA02,CIPROFLOXACIN,1797513,Ciprofloxacin,21603009,2551 +J01MA04,ENOXACIN,1743222,Enoxacin,21603011,3925 +J01MA05,TEMAFLOXACIN,19041153,temafloxacin,21603012,37771 +J01MA06,NORFLOXACIN,1721543,Norfloxacin,21603013,7517 +J01MA07,LOMEFLOXACIN,1707800,lomefloxacin,21603014,28872 +J01MA09,SPARFLOXACIN,1733765,sparfloxacin,21603016,18469 +J01MA11,GREPAFLOXACIN,1747032,grepafloxacin,21603018,83719 +J01MA12,LEVOFLOXACIN,1742253,Levofloxacin,21603019,82122 +J01MA13,TROVAFLOXACIN,1712549,trovafloxacin,21603020,115552 +J01MA13,TROVAFLOXACIN,1734104,Azithromycin,21603020,18631 +J01MA14,MOXIFLOXACIN,1716903,moxifloxacin,21603021,139462 +J01MA15,GEMIFLOXACIN,1716721,gemifloxacin,21603022,138099 +J01MA16,GATIFLOXACIN,1789276,gatifloxacin,21603023,228476 +J01MB06,CINOXACIN,997496,Cinoxacin,21603033,2550 +J01RA02,"SULFONAMIDES,COMBOS W-OTHER ANTIBACT (EXCL TMP)",1746940,Erythromycin,21603038,4053 +J01RA02,"SULFONAMIDES,COMBOS W-OTHER ANTIBACT (EXCL TMP)",1836503,Sulfisoxazole,21603038,10207 +J01XA01,VANCOMYCIN,1707687,Vancomycin,21603043,11124 +J01XB01,COLISTIN,1701677,colistimethate,21603049,2708 +J01XB02,POLYMYXIN B,948582,Polymyxin B,21603050,8536 +J01XD01,METRONIDAZOLE,1707164,Metronidazole,21603054,6922 +J01XE01,NITROFURANTOIN,920293,Nitrofurantoin,21603058,7454 +J01XX,OTHER ANTIBACTERIALS,915175,Bacitracin,21603060,1291 +J01XX04,SPECTINOMYCIN,1701651,Spectinomycin,21603064,270 +J01XX05,METHENAMINE,904356,Methenamine,21603065,6832 +J01XX05,METHENAMINE,939871,sodium phosphate,21603065,36709 +J01XX05,METHENAMINE,986389,"SODIUM PHOSPHATE,MONOBASIC,MONOHYDRATE",21603065,221125 +J01XX05,METHENAMINE,990499,"Sodium Phosphate, Monobasic",21603065,235496 +J01XX08,LINEZOLID,1736887,linezolid,21603068,190376 +J01XX09,DAPTOMYCIN,1786617,Daptomycin,21603069,22299 +J02AA01,AMPHOTERICIN B,1717240,Amphotericin B,21603074,732 +J02AB01,MICONAZOLE,907879,Miconazole,21603077,6932 +J02AB02,KETOCONAZOLE,985708,Ketoconazole,21603078,6135 +J02AC01,FLUCONAZOLE,1754994,Fluconazole,21603080,4450 +J02AC02,ITRACONAZOLE,1703653,Itraconazole,21603081,28031 +J02AC03,VORICONAZOLE,1714277,voriconazole,21603082,121243 +J02AC04,POSACONAZOLE,1704139,posaconazole,21603083,282446 +J02AX01,FLUCYTOSINE,1755112,Flucytosine,21603085,4451 +J02AX04,CASPOFUNGIN,1718054,Caspofungin,21603086,140108 +J02AX05,MICAFUNGIN,19018013,micafungin,21603087,325887 +J02AX06,ANIDULAFUNGIN,19026450,anidulafungin,21603088,341018 +J04AA01,AMINOSALICYLIC ACID,1726228,aminosalicylic acid,21603092,7833 +J04AA02,SODIUM AMINOSALICYLATE,1726228,aminosalicylic acid,21603093,7833 +J04AA02,SODIUM AMINOSALICYLATE,19010337,AMINOSALICYLATE,21603093,113374 +J04AB01,CYCLOSERINE,1710446,Cycloserine,21603096,3007 +J04AB02,RIFAMPICIN,1763204,Rifampin,21603097,9384 +J04AB04,RIFABUTIN,1777417,Rifabutin,21603099,55672 +J04AB05,RIFAPENTINE,19035953,rifapentine,21603100,35617 +J04AB30,CAPREOMYCIN,19026710,Capreomycin,21603101,78903 +J04AC01,ISONIAZID,1782521,isoniazid,21603103,6038 +J04AC51,"ISONIAZID, COMBINATIONS",1353228,Vitamin B6,21603104,42954 +J04AC51,"ISONIAZID, COMBINATIONS",1782521,isoniazid,21603104,6038 +J04AC51,"ISONIAZID, COMBINATIONS",19005046,pyridoxine,21603104,684879 +J04AD03,ETHIONAMIDE,1750074,Ethionamide,21603108,4127 +J04AK01,PYRAZINAMIDE,1759455,Pyrazinamide,21603110,8987 +J04AK02,ETHAMBUTOL,1749301,Ethambutol,21603111,4110 +J04AM02,RIFAMPICIN AND ISONIAZID,1763204,Rifampin,21603116,9384 +J04AM02,RIFAMPICIN AND ISONIAZID,1782521,isoniazid,21603116,6038 +J04AM05,"RIFAMPICIN, PYRAZINAMIDE AND ISONIAZID",1759455,Pyrazinamide,21603119,8987 +J04AM05,"RIFAMPICIN, PYRAZINAMIDE AND ISONIAZID",1763204,Rifampin,21603119,9384 +J04AM05,"RIFAMPICIN, PYRAZINAMIDE AND ISONIAZID",1782521,isoniazid,21603119,6038 +J04BA01,CLOFAZIMINE,1798476,Clofazimine,21603123,2592 +J04BA02,DAPSONE,1711759,Dapsone,21603124,3108 +J05AB01,ACICLOVIR,1703687,Acyclovir,21603131,281 +J05AB03,VIDARABINE,908126,Vidarabine,21603133,11194 +J05AB04,RIBAVIRIN,1380068,Interferon Alfa-2b,21603134,5880 +J05AB04,RIBAVIRIN,1762711,Ribavirin,21603134,9344 +J05AB06,GANCICLOVIR,1757803,Ganciclovir,21603135,4678 +J05AB09,FAMCICLOVIR,1703603,famciclovir,21603136,68099 +J05AB11,VALACICLOVIR,1717704,valacyclovir,21603137,73645 +J05AB12,CIDOFOVIR,1745072,Cidofovir,21603138,83171 +J05AB14,VALGANCICLOVIR,1703063,valganciclovir,21603140,275891 +J05AE01,SAQUINAVIR,1746244,Saquinavir,21603149,83395 +J05AE02,INDINAVIR,1711523,Indinavir,21603150,114289 +J05AE03,RITONAVIR,1748921,Ritonavir,21603151,85762 +J05AE04,NELFINAVIR,1715472,Nelfinavir,21603152,134527 +J05AE05,AMPRENAVIR,1789428,Amprenavir,21603153,228656 +J05AE05,AMPRENAVIR,19009540,Vitamin E,21603153,11256 +J05AE06,LOPINAVIR,1738170,lopinavir,21603154,195088 +J05AE06,LOPINAVIR,1748921,Ritonavir,21603154,85762 +J05AE07,FOSAMPRENAVIR,1736829,fosamprenavir,21603155,358262 +J05AE08,ATAZANAVIR,1727223,Atazanavir,21603156,343047 +J05AE09,TIPRANAVIR,1736999,tipranavir,21603157,190548 +J05AE10,DARUNAVIR,1756831,darunavir,21603158,460132 +J05AF01,ZIDOVUDINE,1710612,Zidovudine,21603160,11413 +J05AF02,DIDANOSINE,1724869,Didanosine,21603161,3364 +J05AF03,ZALCITABINE,1724827,Zalcitabine,21603162,3363 +J05AF04,STAVUDINE,1781406,Stavudine,21603163,59763 +J05AF05,LAMIVUDINE,1704183,Lamivudine,21603164,68244 +J05AF06,ABACAVIR,1736971,abacavir,21603165,190521 +J05AF07,TENOFOVIR DISOPROXIL,1710281,tenofovir disoproxil,21603166,300195 +J05AF08,ADEFOVIR DIPIVOXIL,1729323,adefovir,21603167,16521 +J05AF09,EMTRICITABINE,1703069,emtricitabine,21603168,276237 +J05AF10,ENTECAVIR,1711246,entecavir,21603169,306266 +J05AF11,TELBIVUDINE,1758392,telbivudine,21603170,474128 +J05AG01,NEVIRAPINE,1769389,Nevirapine,21603173,53654 +J05AG03,EFAVIRENZ,1738135,efavirenz,21603175,195085 +J05AG04,ETRAVIRINE,1758536,etravirine,21603176,475969 +J05AH01,ZANAMIVIR,1708748,Zanamivir,21603178,69722 +J05AH02,OSELTAMIVIR,1799139,Oseltamivir,21603179,260101 +J05AR01,ZIDOVUDINE AND LAMIVUDINE,1704183,Lamivudine,21603181,68244 +J05AR01,ZIDOVUDINE AND LAMIVUDINE,1710612,Zidovudine,21603181,11413 +J05AR02,LAMIVUDINE AND ABACAVIR,1704183,Lamivudine,21603182,68244 +J05AR02,LAMIVUDINE AND ABACAVIR,1736971,abacavir,21603182,190521 +J05AR03,TENOFOVIR DISOPROXIL AND EMTRICITABINE,1703069,emtricitabine,21603183,276237 +J05AR03,TENOFOVIR DISOPROXIL AND EMTRICITABINE,1710281,tenofovir disoproxil,21603183,300195 +J05AR04,"ZIDOVUDINE, LAMIVUDINE AND ABACAVIR",1704183,Lamivudine,21603184,68244 +J05AR04,"ZIDOVUDINE, LAMIVUDINE AND ABACAVIR",1710612,Zidovudine,21603184,11413 +J05AR04,"ZIDOVUDINE, LAMIVUDINE AND ABACAVIR",1736971,abacavir,21603184,190521 +J05AR06,"EMTRICITABINE,TENOFOVIR DISOPROXIL AND EFAVIRENZ",1703069,emtricitabine,21603186,276237 +J05AR06,"EMTRICITABINE,TENOFOVIR DISOPROXIL AND EFAVIRENZ",1710281,tenofovir disoproxil,21603186,300195 +J05AR06,"EMTRICITABINE,TENOFOVIR DISOPROXIL AND EFAVIRENZ",1738135,efavirenz,21603186,195085 +J05AX07,ENFUVIRTIDE,1717002,enfuvirtide,21603193,139896 +J05AX08,RALTEGRAVIR,1712889,Raltegravir,21603194,719872 +J05AX09,MARAVIROC,1787101,maraviroc,21603195,620216 +R01AX03,IPRATROPIUM BROMIDE,1112921,Ipratropium,21603199,7213 +R01AX06,MUPIROCIN,951511,Mupirocin,21603201,42372 +R01AX10,VARIOUS,967823,Sodium Chloride,21603205,9863 +R01AX30,COMBINATIONS,929128,Propylene glycol,21603206,34693 +R01AX30,COMBINATIONS,948515,Polyethylene Glycols,21603206,8516 +R01BA01,PHENYLPROPANOLAMINE,1139993,Phenylpropanolamine,21603209,8175 +R01BA02,PSEUDOEPHEDRINE,1154332,Pseudoephedrine,21603210,8896 +R01BA03,PHENYLEPHRINE,1135766,Phenylephrine,21603211,8163 +R01BA51,"PHENYLPROPANOLAMINE, COMBINATIONS",1130863,Brompheniramine,21603212,1767 +R01BA51,"PHENYLPROPANOLAMINE, COMBINATIONS",1135766,Phenylephrine,21603212,8163 +R01BA51,"PHENYLPROPANOLAMINE, COMBINATIONS",1139993,Phenylpropanolamine,21603212,8175 +R01BA51,"PHENYLPROPANOLAMINE, COMBINATIONS",1192710,Chlorpheniramine,21603212,2400 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",965748,Scopolamine,21603213,9601 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",979096,Zinc Acetate,21603213,58295 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1103006,desloratadine,21603213,275635 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1105889,Triprolidine,21603213,10849 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1107830,Loratadine,21603213,28889 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1116109,Belladonna Alkaloids,21603213,1359 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1129625,Diphenhydramine,21603213,3498 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1130863,Brompheniramine,21603213,1767 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1133993,azatadine,21603213,18600 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1135766,Phenylephrine,21603213,8163 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1140123,acrivastine,21603213,19959 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1141018,carbinoxamine,21603213,20220 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1149196,Cetirizine,21603213,20610 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1153428,fexofenadine,21603213,87636 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1154332,Pseudoephedrine,21603213,8896 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1158632,Methscopolamine,21603213,89785 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1159811,Pyrilamine,21603213,9009 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1188052,dexbrompheniramine,21603213,22696 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1188114,dexchlorpheniramine,21603213,22697 +R01BA52,"PSEUDOEPHEDRINE, COMBINATIONS",1192710,Chlorpheniramine,21603213,2400 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",933952,Pheniramine,21603214,8132 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",965748,Scopolamine,21603214,9601 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",979096,Zinc Acetate,21603214,58295 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1105889,Triprolidine,21603214,10849 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1119510,Dextromethorphan,21603214,3289 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1123904,phenyltoloxamine,21603214,33408 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1129625,Diphenhydramine,21603214,3498 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1130863,Brompheniramine,21603214,1767 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1135766,Phenylephrine,21603214,8163 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1141018,carbinoxamine,21603214,20220 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1153013,Promethazine,21603214,8745 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1154332,Pseudoephedrine,21603214,8896 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1158632,Methscopolamine,21603214,89785 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1159811,Pyrilamine,21603214,9009 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1163944,Guaifenesin,21603214,5032 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1188052,dexbrompheniramine,21603214,22696 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1188114,dexchlorpheniramine,21603214,22697 +R01BA53,"PHENYLEPHRINE, COMBINATIONS",1192710,Chlorpheniramine,21603214,2400 +R02AA06,CETYLPYRIDINIUM,917006,Benzocaine,21603222,1399 +R02AA06,CETYLPYRIDINIUM,989301,Cetylpyridinium,21603222,2286 +R02AA12,HEXYLRESORCINOL,969004,Hexylresorcinol,21603226,5321 +R02AA19,PHENOL,923540,phenol,21603233,33290 +R02AA20,VARIOUS,901656,Menthol,21603234,6750 +R02AA20,VARIOUS,917006,Benzocaine,21603234,1399 +R02AA20,VARIOUS,989301,Cetylpyridinium,21603234,2286 +R02AA20,VARIOUS,19009686,methylbenzethonium,21603234,29829 +R02AD,"ANESTHETICS, LOCAL",901656,Menthol,21603241,6750 +R02AD,"ANESTHETICS, LOCAL",917006,Benzocaine,21603241,1399 +R02AD01,BENZOCAINE,917006,Benzocaine,21603242,1399 +R02AD01,BENZOCAINE,961145,Glycerin,21603242,4910 +R02AD04,DYCLONINE,992308,dyclonine,21603245,23744 +R03AA01,EPINEPHRINE,1300153,Racepinephrine,21603251,66887 +R03AA01,EPINEPHRINE,1343916,Epinephrine,21603251,3992 +R03AB02,ISOPRENALINE,1183554,Isoproterenol,21603253,6054 +R03AB03,ORCIPRENALINE,1123995,Orciprenaline,21603254,7688 +R03AC,SELECTIVE BETA-2-ADRENOCEPTOR AGONISTS,1111220,arformoterol,21603255,304962 +R03AC,SELECTIVE BETA-2-ADRENOCEPTOR AGONISTS,1192218,Levalbuterol,21603255,237159 +R03AC02,SALBUTAMOL,1154343,Albuterol,21603256,435 +R03AC07,ISOETARINE,1181809,Isoetharine,21603261,6023 +R03AC08,PIRBUTEROL,1125449,pirbuterol,21603262,33767 +R03AC12,SALMETEROL,1137529,salmeterol,21603266,36117 +R03AC13,FORMOTEROL,1196677,formoterol,21603267,25255 +R03AC17,BITOLTEROL,1138050,bitolterol,21603271,19499 +R03AK01,EPINEPHRINE & OTHER DRUGS FOR OBSTRUCT AIRWAY DIS,1300153,Racepinephrine,21603275,66887 +R03AK04,SALBUTAMOL & OTHER DRUGS FOR OBSTRUCT AIRWAY DIS,1112921,Ipratropium,21603278,7213 +R03AK04,SALBUTAMOL & OTHER DRUGS FOR OBSTRUCT AIRWAY DIS,1154343,Albuterol,21603278,435 +R03AK06,SALMETEROL & OTHER DRUGS FOR OBSTRUCT AIRWAY DIS,1137529,salmeterol,21603280,36117 +R03AK06,SALMETEROL & OTHER DRUGS FOR OBSTRUCT AIRWAY DIS,1149380,fluticasone,21603280,41126 +R03AK07,FORMOTEROL & OTHER DRUGS FOR OBSTRUCT AIRWAY DIS,939259,Budesonide,21603281,19831 +R03AK07,FORMOTEROL & OTHER DRUGS FOR OBSTRUCT AIRWAY DIS,1196677,formoterol,21603281,25255 +R03BA01,BECLOMETASONE,1115572,Beclomethasone,21603284,1347 +R03BA02,BUDESONIDE,939259,Budesonide,21603285,19831 +R03BA03,FLUNISOLIDE,1196514,flunisolide,21603286,25120 +R03BA05,FLUTICASONE,1149380,fluticasone,21603288,41126 +R03BA06,TRIAMCINOLONE,903963,Triamcinolone,21603289,10759 +R03BA07,MOMETASONE,905233,Mometasone,21603290,108118 +R03BA08,CICLESONIDE,902938,ciclesonide,21603291,274964 +R03BB01,IPRATROPIUM BROMIDE,1112921,Ipratropium,21603293,7213 +R03BB04,TIOTROPIUM BROMIDE,1106776,tiotropium,21603296,69120 +R03BC01,CROMOGLICIC ACID,1152631,Cromolyn,21603298,42612 +R03BC03,NEDOCROMIL,1114620,Nedocromil,21603299,31563 +R03CA02,EPHEDRINE,1143374,Ephedrine,21603304,3966 +R03CB02,METHOXYPHENAMINE,19009365,methoxyphenamine,21603307,29704 +R03CB03,ORCIPRENALINE,1123995,Orciprenaline,21603308,7688 +R03CC02,SALBUTAMOL,1154343,Albuterol,21603312,435 +R03DA01,DIPROPHYLLINE,1140088,Dyphylline,21603329,3714 +R03DA02,CHOLINE THEOPHYLLINATE,19049816,cholinophyllin,21603330,20976 +R03DA04,THEOPHYLLINE,1237049,Theophylline,21603332,10438 +R03DA05,AMINOPHYLLINE,1105775,Aminophylline,21603333,689 +R03DA54,"THEOPHYLLINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1163944,Guaifenesin,21603342,5032 +R03DA54,"THEOPHYLLINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1237049,Theophylline,21603342,10438 +R03DA54,"THEOPHYLLINE, COMBINATIONS EXCL. PSYCHOLEPTICS",19049816,cholinophyllin,21603342,20976 +R03DB04,THEOPHYLLINE AND ADRENERGICS,734275,Phenobarbital,21603350,8134 +R03DB04,THEOPHYLLINE AND ADRENERGICS,1143374,Ephedrine,21603350,3966 +R03DB04,THEOPHYLLINE AND ADRENERGICS,1237049,Theophylline,21603350,10438 +R03DC01,ZAFIRLUKAST,1111706,zafirlukast,21603354,114970 +R03DC03,MONTELUKAST,1154161,montelukast,21603356,88249 +R03DX,OTHER SYSTEMIC DRUGS FOR OBSTRUCTIVE AIRWAY DISEAS,1147878,zileuton,21603358,40575 +R03DX05,OMALIZUMAB,1110942,omalizumab,21603362,302379 +R05CA,EXPECTORANTS,19059707,Terpin hydrate,21603367,89916 +R05CA02,POTASSIUM IODIDE,1237049,Theophylline,21603369,10438 +R05CA02,POTASSIUM IODIDE,19049909,Potassium Iodide,21603369,8597 +R05CA03,GUAIFENESIN,1163944,Guaifenesin,21603370,5032 +R05CA09,GUAIACOLSULFONATE,1189220,guaiacolsulfonate,21603376,636827 +R05CA10,COMBINATIONS,976545,potassium citrate,21603377,54993 +R05CA10,COMBINATIONS,979096,Zinc Acetate,21603377,58295 +R05CA10,COMBINATIONS,1130863,Brompheniramine,21603377,1767 +R05CA10,COMBINATIONS,1135766,Phenylephrine,21603377,8163 +R05CA10,COMBINATIONS,1139993,Phenylpropanolamine,21603377,8175 +R05CA10,COMBINATIONS,1140088,Dyphylline,21603377,3714 +R05CA10,COMBINATIONS,1143374,Ephedrine,21603377,3966 +R05CA10,COMBINATIONS,1154332,Pseudoephedrine,21603377,8896 +R05CA10,COMBINATIONS,1158632,Methscopolamine,21603377,89785 +R05CA10,COMBINATIONS,1159811,Pyrilamine,21603377,9009 +R05CA10,COMBINATIONS,1163944,Guaifenesin,21603377,5032 +R05CA10,COMBINATIONS,1189220,guaiacolsulfonate,21603377,636827 +R05CA10,COMBINATIONS,1192710,Chlorpheniramine,21603377,2400 +R05CA10,COMBINATIONS,1200939,guaiacolsulfonic acid,21603377,26288 +R05CA10,COMBINATIONS,1201620,Codeine,21603377,2670 +R05CA10,COMBINATIONS,19049909,Potassium Iodide,21603377,8597 +R05CB01,ACETYLCYSTEINE,1139042,Acetylcysteine,21603380,197 +R05CB03,CARBOCISTEINE,19041843,Carbocysteine,21603382,2023 +R05CB12,TIOPRONIN,903031,Thiopronine,21603391,6765 +R05CB13,DORNASE ALFA (DESOXYRIBONUCLEASE),1125443,Dornase Alfa,21603392,337623 +R05DA04,CODEINE,1201620,Codeine,21603399,2670 +R05DA09,DEXTROMETHORPHAN,1119510,Dextromethorphan,21603404,3289 +R05DA20,COMBINATIONS,738818,Doxylamine,21603408,3642 +R05DA20,COMBINATIONS,917006,Benzocaine,21603408,1399 +R05DA20,COMBINATIONS,961145,Glycerin,21603408,4910 +R05DA20,COMBINATIONS,965748,Scopolamine,21603408,9601 +R05DA20,COMBINATIONS,1101703,homatropine,21603408,27084 +R05DA20,COMBINATIONS,1105889,Triprolidine,21603408,10849 +R05DA20,COMBINATIONS,1119510,Dextromethorphan,21603408,3289 +R05DA20,COMBINATIONS,1129625,Diphenhydramine,21603408,3498 +R05DA20,COMBINATIONS,1130863,Brompheniramine,21603408,1767 +R05DA20,COMBINATIONS,1135766,Phenylephrine,21603408,8163 +R05DA20,COMBINATIONS,1139216,bromodiphenhydramine,21603408,19759 +R05DA20,COMBINATIONS,1139993,Phenylpropanolamine,21603408,8175 +R05DA20,COMBINATIONS,1140640,carbetapentane,21603408,20217 +R05DA20,COMBINATIONS,1141018,carbinoxamine,21603408,20220 +R05DA20,COMBINATIONS,1153013,Promethazine,21603408,8745 +R05DA20,COMBINATIONS,1154332,Pseudoephedrine,21603408,8896 +R05DA20,COMBINATIONS,1159811,Pyrilamine,21603408,9009 +R05DA20,COMBINATIONS,1163944,Guaifenesin,21603408,5032 +R05DA20,COMBINATIONS,1174888,Hydrocodone,21603408,5489 +R05DA20,COMBINATIONS,1188052,dexbrompheniramine,21603408,22696 +R05DA20,COMBINATIONS,1188114,dexchlorpheniramine,21603408,22697 +R05DA20,COMBINATIONS,1189220,guaiacolsulfonate,21603408,636827 +R05DA20,COMBINATIONS,1189596,dihydrocodeine,21603408,23088 +R05DA20,COMBINATIONS,1192710,Chlorpheniramine,21603408,2400 +R05DA20,COMBINATIONS,1200939,guaiacolsulfonic acid,21603408,26288 +R05DA20,COMBINATIONS,1201620,Codeine,21603408,2670 +R05DB01,BENZONATATE,1136601,benzonatate,21603410,18993 +R05DB05,PENTOXYVERINE,1140640,carbetapentane,21603414,20217 +R05DB20,COMBINATIONS,979096,Zinc Acetate,21603427,58295 +R05DB20,COMBINATIONS,1119510,Dextromethorphan,21603427,3289 +R05DB20,COMBINATIONS,1129625,Diphenhydramine,21603427,3498 +R05DB20,COMBINATIONS,1130863,Brompheniramine,21603427,1767 +R05DB20,COMBINATIONS,1135766,Phenylephrine,21603427,8163 +R05DB20,COMBINATIONS,1140640,carbetapentane,21603427,20217 +R05DB20,COMBINATIONS,1141018,carbinoxamine,21603427,20220 +R05DB20,COMBINATIONS,1143374,Ephedrine,21603427,3966 +R05DB20,COMBINATIONS,1154332,Pseudoephedrine,21603427,8896 +R05DB20,COMBINATIONS,1159811,Pyrilamine,21603427,9009 +R05DB20,COMBINATIONS,1192710,Chlorpheniramine,21603427,2400 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,976545,potassium citrate,21603439,54993 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,977968,sodium citrate,21603439,56466 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1119510,Dextromethorphan,21603439,3289 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1126658,Hydromorphone,21603439,3423 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1130863,Brompheniramine,21603439,1767 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1135766,Phenylephrine,21603439,8163 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1139993,Phenylpropanolamine,21603439,8175 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1154332,Pseudoephedrine,21603439,8896 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1158632,Methscopolamine,21603439,89785 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1159811,Pyrilamine,21603439,9009 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1163944,Guaifenesin,21603439,5032 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1174888,Hydrocodone,21603439,5489 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1188052,dexbrompheniramine,21603439,22696 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1188114,dexchlorpheniramine,21603439,22697 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1189220,guaiacolsulfonate,21603439,636827 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1189596,dihydrocodeine,21603439,23088 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1192710,Chlorpheniramine,21603439,2400 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1200939,guaiacolsulfonic acid,21603439,26288 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,1201620,Codeine,21603439,2670 +R05FA02,OPIUM DERIVATIVES AND EXPECTORANTS,19049909,Potassium Iodide,21603439,8597 +R05FB02,COUGH SUPPRESSANTS AND EXPECTORANTS,1135766,Phenylephrine,21603442,8163 +R05FB02,COUGH SUPPRESSANTS AND EXPECTORANTS,1140640,carbetapentane,21603442,20217 +R05FB02,COUGH SUPPRESSANTS AND EXPECTORANTS,1150886,clofedanol,21603442,21254 +R05FB02,COUGH SUPPRESSANTS AND EXPECTORANTS,1154332,Pseudoephedrine,21603442,8896 +R05FB02,COUGH SUPPRESSANTS AND EXPECTORANTS,1163944,Guaifenesin,21603442,5032 +R05X,OTHER COLD COMBINATION PREPARATIONS,901656,Menthol,21603443,6750 +R05X,OTHER COLD COMBINATION PREPARATIONS,912362,Ammonium Chloride,21603443,712 +R05X,OTHER COLD COMBINATION PREPARATIONS,922191,pectin,21603443,32987 +R05X,OTHER COLD COMBINATION PREPARATIONS,938205,Camphor,21603443,1952 +R05X,OTHER COLD COMBINATION PREPARATIONS,977968,sodium citrate,21603443,56466 +R05X,OTHER COLD COMBINATION PREPARATIONS,1129625,Diphenhydramine,21603443,3498 +R05X,OTHER COLD COMBINATION PREPARATIONS,1180412,Eucalyptus oil,21603443,59087 +R05X,OTHER COLD COMBINATION PREPARATIONS,19004430,SWEETLEAF Preparation,21603443,283740 +R05X,OTHER COLD COMBINATION PREPARATIONS,19044317,zinc chloride,21603443,39937 +R06AA02,DIPHENHYDRAMINE,928744,Dimenhydrinate,21603448,3444 +R06AA02,DIPHENHYDRAMINE,1129625,Diphenhydramine,21603448,3498 +R06AA07,DIPHENYLPYRALINE,19090000,diphenylpyraline,21603451,23386 +R06AA08,CARBINOXAMINE,1141018,carbinoxamine,21603452,20220 +R06AA09,DOXYLAMINE,738818,Doxylamine,21603453,3642 +R06AA09,DOXYLAMINE,1353228,Vitamin B6,21603453,42954 +R06AB01,BROMPHENIRAMINE,1130863,Brompheniramine,21603459,1767 +R06AB02,DEXCHLORPHENIRAMINE,1188114,dexchlorpheniramine,21603460,22697 +R06AB04,CHLORPHENAMINE,1192710,Chlorpheniramine,21603462,2400 +R06AB04,CHLORPHENAMINE,1343916,Epinephrine,21603462,3992 +R06AB06,DEXBROMPHENIRAMINE,1188052,dexbrompheniramine,21603464,22696 +R06AB54,"CHLORPHENAMINE, COMBINATIONS",965748,Scopolamine,21603468,9601 +R06AB54,"CHLORPHENAMINE, COMBINATIONS",1135766,Phenylephrine,21603468,8163 +R06AB54,"CHLORPHENAMINE, COMBINATIONS",1154332,Pseudoephedrine,21603468,8896 +R06AB54,"CHLORPHENAMINE, COMBINATIONS",1158632,Methscopolamine,21603468,89785 +R06AB54,"CHLORPHENAMINE, COMBINATIONS",1192710,Chlorpheniramine,21603468,2400 +R06AC01,MEPYRAMINE,1159811,Pyrilamine,21603471,9009 +R06AC04,TRIPELENNAMINE,1105853,Tripelennamine,21603474,10847 +R06AC05,METHAPYRILENE,19004158,Methapyrilene,21603475,6822 +R06AD01,ALIMEMAZINE,19005570,Trimeprazine,21603480,10825 +R06AD02,PROMETHAZINE,1153013,Promethazine,21603481,8745 +R06AD03,THIETHYLPERAZINE,1037358,Thiethylperazine,21603482,10471 +R06AD04,METHDILAZINE,19009250,methdilazine,21603483,29648 +R06AE01,BUCLIZINE,19081195,buclizine,21603492,59636 +R06AE03,CYCLIZINE,909358,Cyclizine,21603493,2977 +R06AE05,MECLOZINE,994341,Meclizine,21603495,6676 +R06AE07,CETIRIZINE,1149196,Cetirizine,21603497,20610 +R06AK,COMBINATIONS OF ANTIHISTAMINES,933952,Pheniramine,21603502,8132 +R06AK,COMBINATIONS OF ANTIHISTAMINES,1123904,phenyltoloxamine,21603502,33408 +R06AK,COMBINATIONS OF ANTIHISTAMINES,1129625,Diphenhydramine,21603502,3498 +R06AK,COMBINATIONS OF ANTIHISTAMINES,1130863,Brompheniramine,21603502,1767 +R06AK,COMBINATIONS OF ANTIHISTAMINES,1159811,Pyrilamine,21603502,9009 +R06AK,COMBINATIONS OF ANTIHISTAMINES,1188052,dexbrompheniramine,21603502,22696 +R06AX02,CYPROHEPTADINE,1110727,Cyproheptadine,21603505,3013 +R06AX04,PHENINDAMINE,1123534,phenindamine,21603507,33283 +R06AX05,ANTAZOLINE,951237,Antazoline,21603508,865 +R06AX07,TRIPROLIDINE,1105889,Triprolidine,21603509,10849 +R06AX09,AZATADINE,1133993,azatadine,21603511,18600 +R06AX11,ASTEMIZOLE,1150770,Astemizole,21603512,42328 +R06AX12,TERFENADINE,1150836,Terfenadine,21603513,42330 +R06AX13,LORATADINE,1107830,Loratadine,21603514,28889 +R06AX26,FEXOFENADINE,1153428,fexofenadine,21603525,87636 +R06AX27,DESLORATADINE,1103006,desloratadine,21603526,275635 +R07AA02,NATURAL PHOSPHOLIPIDS,19057932,beractant,21603534,46967 +R07AA02,NATURAL PHOSPHOLIPIDS,19089891,calfactant,21603534,232539 +R07AA02,NATURAL PHOSPHOLIPIDS,19091377,Poractant alfa,21603534,236381 +R07AB01,DOXAPRAM,738152,Doxapram,21603537,3637 +R07AB02,NIKETHAMIDE,19019088,Nikethamide,21603538,7424 +R07AX,OTHER RESPIRATORY SYSTEM PRODUCTS,967823,Sodium Chloride,21603548,9863 +S01AA01,CHLORAMPHENICOL,990069,Chloramphenicol,21603554,2348 +S01AA02,CHLORTETRACYCLINE,19095043,Chlortetracycline,21603555,2408 +S01AA09,TETRACYCLINE,1836948,Tetracycline,21603560,10395 +S01AA10,NATAMYCIN,915392,Natamycin,21603561,7268 +S01AA11,GENTAMICIN,919345,Gentamicin Sulfate (USP),21603562,142438 +S01AA12,TOBRAMYCIN,902722,Tobramycin,21603563,10627 +S01AA17,ERYTHROMYCIN,1746940,Erythromycin,21603568,4053 +S01AA20,ANTIBIOTICS IN COMBINATION WITH OTHER DRUGS,1036252,Sulfacetamide,21603571,10169 +S01AA20,ANTIBIOTICS IN COMBINATION WITH OTHER DRUGS,1135766,Phenylephrine,21603571,8163 +S01AA26,AZITHROMYCIN,1734104,Azithromycin,21603577,18631 +S01AA30,COMBINATIONS OF DIFFERENT ANTIBIOTICS,915175,Bacitracin,21603578,1291 +S01AA30,COMBINATIONS OF DIFFERENT ANTIBIOTICS,915981,Neomycin,21603578,7299 +S01AA30,COMBINATIONS OF DIFFERENT ANTIBIOTICS,948582,Polymyxin B,21603578,8536 +S01AA30,COMBINATIONS OF DIFFERENT ANTIBIOTICS,963742,Gramicidin,21603578,5011 +S01AA30,COMBINATIONS OF DIFFERENT ANTIBIOTICS,1705674,Trimethoprim,21603578,10829 +S01AB04,SULFACETAMIDE,1036252,Sulfacetamide,21603583,10169 +S01AD01,IDOXURIDINE,19078156,Idoxuridine,21603586,5653 +S01AD02,TRIFLURIDINE,905078,Trifluridine,21603587,10803 +S01AD06,VIDARABINE,908126,Vidarabine,21603590,11194 +S01AD08,FOMIVIRSEN,19048999,fomivirsen,21603592,85763 +S01AD09,GANCICLOVIR,1757803,Ganciclovir,21603593,4678 +S01AX,OTHER ANTIINFECTIVES,915175,Bacitracin,21603594,1291 +S01AX03,ZINC COMPOUNDS,19044522,Zinc Sulfate,21603597,39954 +S01AX11,OFLOXACIN,923081,Ofloxacin,21603605,7623 +S01AX12,NORFLOXACIN,1721543,Norfloxacin,21603606,7517 +S01AX13,CIPROFLOXACIN,1797513,Ciprofloxacin,21603607,2551 +S01AX18,POVIDONE-IODINE,1750087,Povidone-Iodine,21603612,8611 +S01AX19,LEVOFLOXACIN,1742253,Levofloxacin,21603613,82122 +S01AX21,GATIFLOXACIN,1789276,gatifloxacin,21603614,228476 +S01AX22,MOXIFLOXACIN,1716903,moxifloxacin,21603615,139462 +S01BA,"CORTICOSTEROIDS, PLAIN",19089579,difluprednate,21603617,23043 +S01BA01,DEXAMETHASONE,1518254,Dexamethasone,21603618,3264 +S01BA02,HYDROCORTISONE,975125,Hydrocortisone,21603619,5492 +S01BA04,PREDNISOLONE,1550557,prednisolone,21603621,8638 +S01BA05,TRIAMCINOLONE,903963,Triamcinolone,21603622,10759 +S01BA07,FLUOROMETHOLONE,955583,Fluorometholone,21603624,4491 +S01BA08,MEDRYSONE,909021,medrysone,21603625,29439 +S01BA13,RIMEXOLONE,977421,rimexolone,21603630,55681 +S01BA14,LOTEPREDNOL,967562,loteprednol etabonate,21603631,52177 +S01BC,"ANTIINFLAMMATORY AGENTS, NON-STEROIDS",1036636,Suprofen,21603638,10255 +S01BC04,FLURBIPROFEN,1156378,Flurbiprofen,21603642,4502 +S01BC05,KETOROLAC,1136980,Ketorolac,21603643,35827 +S01BC10,NEPAFENAC,909795,nepafenac,21603648,298665 +S01BC11,BROMFENAC,1139179,bromfenac,21603649,19737 +S01CA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,902722,Tobramycin,21603651,10627 +S01CA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,992127,Loteprednol,21603651,237027 +S01CA01,DEXAMETHASONE AND ANTIINFECTIVES,902722,Tobramycin,21603652,10627 +S01CA01,DEXAMETHASONE AND ANTIINFECTIVES,915981,Neomycin,21603652,7299 +S01CA01,DEXAMETHASONE AND ANTIINFECTIVES,948582,Polymyxin B,21603652,8536 +S01CA01,DEXAMETHASONE AND ANTIINFECTIVES,1518254,Dexamethasone,21603652,3264 +S01CA02,PREDNISOLONE AND ANTIINFECTIVES,915981,Neomycin,21603653,7299 +S01CA02,PREDNISOLONE AND ANTIINFECTIVES,919345,Gentamicin Sulfate (USP),21603653,142438 +S01CA02,PREDNISOLONE AND ANTIINFECTIVES,948582,Polymyxin B,21603653,8536 +S01CA02,PREDNISOLONE AND ANTIINFECTIVES,1036252,Sulfacetamide,21603653,10169 +S01CA02,PREDNISOLONE AND ANTIINFECTIVES,1550557,prednisolone,21603653,8638 +S01CA03,HYDROCORTISONE AND ANTIINFECTIVES,915981,Neomycin,21603654,7299 +S01CA03,HYDROCORTISONE AND ANTIINFECTIVES,948582,Polymyxin B,21603654,8536 +S01CA03,HYDROCORTISONE AND ANTIINFECTIVES,975125,Hydrocortisone,21603654,5492 +S01CA07,FLUOROMETHOLONE AND ANTIINFECTIVES,955583,Fluorometholone,21603658,4491 +S01CA07,FLUOROMETHOLONE AND ANTIINFECTIVES,1036252,Sulfacetamide,21603658,10169 +S01EA01,EPINEPHRINE,1343916,Epinephrine,21603673,3992 +S01EA02,DIPIVEFRINE,990009,Dipivefrin,21603674,23410 +S01EA03,APRACLONIDINE,919986,apraclonidine,21603675,14845 +S01EA05,BRIMONIDINE,915542,brimonidine,21603677,134615 +S01EB01,PILOCARPINE,945286,Pilocarpine,21603680,8328 +S01EB02,CARBACHOL,940183,Carbachol,21603681,1999 +S01EB03,ECOTHIOPATE,958368,Echothiophate,21603682,89778 +S01EB04,DEMECARIUM,19004718,Demecarium,21603683,107771 +S01EB05,PHYSOSTIGMINE,19044337,Physostigmine,21603684,8299 +S01EB07,FLUOSTIGMINE,19082111,Isoflurophate,21603686,6027 +S01EB09,ACETYLCHOLINE,19037624,Acetylcholine,21603688,194 +S01EB51,"PILOCARPINE, COMBINATIONS",945286,Pilocarpine,21603690,8328 +S01EB51,"PILOCARPINE, COMBINATIONS",1343916,Epinephrine,21603690,3992 +S01EB51,"PILOCARPINE, COMBINATIONS",19044337,Physostigmine,21603690,8299 +S01EC01,ACETAZOLAMIDE,929435,Acetazolamide,21603693,167 +S01EC02,DICLOFENAMIDE,924296,Dichlorphenamide,21603694,3353 +S01EC03,DORZOLAMIDE,981709,dorzolamide,21603695,60207 +S01EC04,BRINZOLAMIDE,938044,brinzolamide,21603696,194881 +S01EC05,METHAZOLAMIDE,904250,Methazolamide,21603697,6826 +S01ED01,TIMOLOL,902427,Timolol,21603699,10600 +S01ED02,BETAXOLOL,1322081,Betaxolol,21603700,1520 +S01ED03,LEVOBUNOLOL,932815,Levobunolol,21603701,1813 +S01ED04,METIPRANOLOL,905531,Metipranolol,21603702,10824 +S01ED05,CARTEOLOL,950370,Carteolol,21603703,2116 +S01ED51,"TIMOLOL, COMBINATIONS",902427,Timolol,21603705,10600 +S01ED51,"TIMOLOL, COMBINATIONS",915542,brimonidine,21603705,134615 +S01ED51,"TIMOLOL, COMBINATIONS",981709,dorzolamide,21603705,60207 +S01EE01,LATANOPROST,954688,latanoprost,21603710,43611 +S01EE02,UNOPROSTONE,915829,isopropyl unoprostone,21603711,135313 +S01EE03,BIMATOPROST,904525,bimatoprost,21603712,283810 +S01EE04,TRAVOPROST,904501,travoprost,21603713,283809 +S01EX,OTHER ANTIGLAUCOMA PREPARATIONS,961145,Glycerin,21603715,4910 +S01EX,OTHER ANTIGLAUCOMA PREPARATIONS,1383815,Isosorbide,21603715,6057 +S01EX02,DAPIPRAZOLE,19086622,dapiprazole,21603717,22298 +L01CB01,ETOPOSIDE,1350504,Etoposide,21603718,4179 +L01CB02,TENIPOSIDE,19136750,Teniposide,21603719,10362 +L01CD01,PACLITAXEL,1378382,Paclitaxel,21603723,56946 +L01CD02,DOCETAXEL,1315942,docetaxel,21603724,72962 +L01DA01,DACTINOMYCIN,1311443,Dactinomycin,21603730,3100 +L01DB01,DOXORUBICIN,1338512,Doxorubicin,21603732,3639 +L01DB01,DOXORUBICIN,19051649,Liposomal Doxorubicin,21603732,214525 +L01DB02,DAUNORUBICIN,1311799,Daunorubicin,21603733,3109 +L01DB02,DAUNORUBICIN,19051599,Daunorubicin Liposomal,21603733,214468 +L01DB03,EPIRUBICIN,1344354,Epirubicin,21603734,3995 +L01DB06,IDARUBICIN,19078097,Idarubicin,21603737,5650 +L01DB07,MITOXANTRONE,1309188,Mitoxantrone,21603738,7005 +L01DB09,VALRUBICIN,19012543,valrubicin,21603740,31435 +L01DC01,BLEOMYCIN,1329241,Bleomycin,21603742,1622 +L01DC02,PLICAMYCIN,19009165,Plicamycin,21603743,6995 +L01DC03,MITOMYCIN,1389036,Mitomycin,21603744,632 +L01DC04,IXABEPILONE,19025348,ixabepilone,21603745,337523 +L01XA01,CISPLATIN,1397599,Cisplatin,21603748,2555 +L01XA02,CARBOPLATIN,1344905,Carboplatin,21603749,40048 +L01XA03,OXALIPLATIN,1318011,oxaliplatin,21603750,32592 +L01XB01,PROCARBAZINE,1351779,Procarbazine,21603753,8702 +L01XC02,RITUXIMAB,1314273,rituximab,21603756,121191 +L01XC03,TRASTUZUMAB,1387104,trastuzumab,21603757,224905 +L01XC04,ALEMTUZUMAB,1312706,alemtuzumab,21603758,117055 +L01XC05,GEMTUZUMAB,19098566,gemtuzumab,21603759,259315 +L01XC06,CETUXIMAB,1315411,cetuximab,21603760,318341 +L01XC07,BEVACIZUMAB,1397141,bevacizumab,21603761,253337 +L01XC08,PANITUMUMAB,19100985,panitumumab,21603762,263034 +L01XD,SENSITIZERS USED IN PHOTODYNAMIC/RADIATION THERAPY,905223,Methoxsalen,21603765,6854 +L01XD01,PORFIMER SODIUM,19089602,Dihematoporphyrin Ether,21603766,23066 +L01XD04,AMINOLEVULINIC ACID,924120,Aminolevulinate,21603768,155002 +L01XE01,IMATINIB,1304107,imatinib,21603772,282388 +L01XE02,GEFITINIB,1319193,gefitinib,21603773,328134 +L01XE03,ERLOTINIB,1325363,erlotinib,21603774,337525 +L01XE04,SUNITINIB,1336539,sunitinib,21603775,357977 +L01XE05,SORAFENIB,1363387,sorafenib,21603776,495881 +L01XE06,DASATINIB,1358436,dasatinib,21603777,475342 +L01XE07,LAPATINIB,1359548,lapatinib,21603778,480167 +L01XE08,NILOTINIB,1394023,nilotinib,21603779,662281 +L01XE09,TEMSIROLIMUS,19092845,temsirolimus,21603780,657797 +L01XE10,EVEROLIMUS,19011440,everolimus,21603781,141704 +L01XX,OTHER ANTINEOPLASTIC AGENTS,1436776,Testolactone,21603783,10378 +L01XX02,ASPARAGINASE,19012585,ASPARAGINASE,21603785,1156 +L01XX03,ALTRETAMINE,1368823,Altretamine,21603786,5296 +L01XX05,HYDROXYCARBAMIDE,1377141,hydroxyurea,21603787,5552 +L01XX08,PENTOSTATIN,19031224,Pentostatin,21603789,8011 +L01XX10,MASOPROCOL,988447,Masoprocol,21603791,227239 +L01XX11,ESTRAMUSTINE,1349025,Estramustine,21603792,4089 +L01XX14,TRETINOIN,903643,Tretinoin,21603793,10753 +L01XX17,TOPOTECAN,1378509,Topotecan,21603795,57308 +L01XX19,IRINOTECAN,1367268,irinotecan,21603797,51499 +L01XX23,MITOTANE,1309161,Mitotane,21603799,7004 +L01XX24,PEGASPARGASE,1326481,pegaspargase,21603800,34132 +L01XX25,BEXAROTENE,1389888,bexarotene,21603801,233272 +L01XX27,ARSENIC TRIOXIDE,1333379,arsenic trioxide,21603802,18330 +L01XX29,DENILEUKIN DIFTITOX,19051642,denileukin diftitox,21603803,214470 +L01XX32,BORTEZOMIB,1336825,bortezomib,21603804,358258 +L01XX35,ANAGRELIDE,1381253,anagrelide,21603806,596724 +L01XX38,VORINOSTAT,1337651,Vorinostat,21603809,194337 +L02AA01,DIETHYLSTILBESTROL,1525866,Diethylstilbestrol,21603815,3390 +L02AA04,FOSFESTROL,1525866,Diethylstilbestrol,21603818,3390 +L02AB01,MEGESTROL,1300978,Megestrol,21603820,6703 +L02AB02,MEDROXYPROGESTERONE,1500211,Medroxyprogesterone,21603821,6691 +L02AE02,LEUPRORELIN,1351541,Leuprolide,21603825,42375 +L02AE03,GOSERELIN,1366310,Goserelin,21603826,50610 +L02AE04,TRIPTORELIN,1343039,Triptorelin,21603827,38782 +L02BA01,TAMOXIFEN,1436678,Tamoxifen,21603831,10324 +L02BA02,TOREMIFENE,1342346,Toremifene,21603832,38409 +L02BA03,FULVESTRANT,1304044,fulvestrant,21603833,282357 +L02BB01,FLUTAMIDE,1356461,Flutamide,21603835,4508 +L02BB02,NILUTAMIDE,1315286,nilutamide,21603836,31805 +L02BB03,BICALUTAMIDE,1344381,bicalutamide,21603837,83008 +L02BG01,AMINOGLUTHETIMIDE,1503057,Aminoglutethimide,21603839,677 +L02BG03,ANASTROZOLE,1348265,anastrozole,21603841,84857 +L02BG04,LETROZOLE,1315946,letrozole,21603842,72965 +L02BG06,EXEMESTANE,1398399,exemestane,21603844,258494 +L02BX01,ABARELIX,19010868,abarelix,21603846,301739 +L02BX02,DEGARELIX,19058410,degarelix,21603847,475230 +L03AA02,FILGRASTIM,1304850,Filgrastim,21603851,68442 +L03AA09,SARGRAMOSTIM,1308432,sargramostim,21603853,69634 +L03AA13,PEGFILGRASTIM,1325608,pegfilgrastim,21603856,338036 +L03AB01,INTERFERON ALFA NATURAL,1385645,Interferon Alfa-n3,21603858,612937 +L03AB03,INTERFERON GAMMA,1380191,Interferon gamma-1b,21603860,5882 +L03AB04,INTERFERON ALFA-2A,1379969,Interferon Alfa-2a,21603861,5879 +L03AB05,INTERFERON ALFA-2B,1380068,Interferon Alfa-2b,21603862,5880 +L03AB05,INTERFERON ALFA-2B,1762711,Ribavirin,21603862,9344 +L03AB07,INTERFERON BETA-1A,722424,Interferon beta-1a,21603864,75917 +L03AB07,INTERFERON BETA-1A,1379969,Interferon Alfa-2a,21603864,5879 +L03AB08,INTERFERON BETA-1B,713196,interferon beta-1b,21603865,72257 +L03AB09,INTERFERON ALFACON-1,1781314,interferon alfacon-1,21603866,59744 +L03AB10,PEGINTERFERON ALFA-2B,1797155,peginterferon alfa-2b,21603867,253453 +L03AB11,PEGINTERFERON ALFA-2A,1714165,peginterferon alfa-2a,21603868,120608 +L03AC01,ALDESLEUKIN,1309770,Aldesleukin,21603872,70223 +L03AC02,OPRELVEKIN,1318030,Oprelvekin,21603873,139994 +L03AX03,BCG VACCINE,19023835,"BCG, Live, Connaught Strain",21603877,76469 +L03AX04,PEGADEMASE,581480,pegademase bovine,21603878,59768 +L03AX16,PLERIXAFOR,19017581,Plerixafor,21603889,733003 +L04AA02,MUROMONAB-CD3,19051865,Muromonab-CD3,21603893,42405 +L04AA03,ANTILYMPHOCYTE IMMUNOGLOBULIN (HORSE),19061406,Lymphocyte immune globulin,21603894,91601 +L04AA06,MYCOPHENOLIC ACID,19003999,mycophenolate mofetil,21603896,68149 +L04AA06,MYCOPHENOLIC ACID,19012565,Mycophenolic Acid,21603896,7145 +L04AA10,SIROLIMUS,19034726,Sirolimus,21603897,35302 +L04AA13,LEFLUNOMIDE,1101898,leflunomide,21603898,27169 +L04AA15,ALEFACEPT,909959,alefacept,21603899,299635 +L04AA23,NATALIZUMAB,735843,natalizumab,21603904,354770 +L04AA24,ABATACEPT,1186087,abatacept,21603905,614391 +L04AA25,ECULIZUMAB,19080458,eculizumab,21603906,591781 +L04AB01,ETANERCEPT,1151789,Etanercept,21603908,214555 +L04AB02,INFLIXIMAB,937368,infliximab,21603909,191831 +L04AB04,ADALIMUMAB,1119119,adalimumab,21603911,327361 +L04AB05,CERTOLIZUMAB PEGOL,912263,certolizumab pegol,21603912,709271 +L04AB06,GOLIMUMAB,19041065,golimumab,21603913,819300 +L04AC01,DACLIZUMAB,19036892,Daclizumab,21603915,190353 +L04AC02,BASILIXIMAB,19038440,basiliximab,21603916,196102 +L04AC03,ANAKINRA,1114375,anakinra,21603917,72435 +L04AD01,CICLOSPORIN,19010482,Cyclosporine,21603924,3008 +L04AD02,TACROLIMUS,950637,Tacrolimus,21603925,42316 +L04AX01,AZATHIOPRINE,19014878,Azathioprine,21603927,1256 +L04AX02,THALIDOMIDE,19137042,Thalidomide,21603928,10432 +L04AX03,METHOTREXATE,1305058,Methotrexate,21603929,6851 +L04AX04,LENALIDOMIDE,19026972,lenalidomide,21603930,342369 +M01AA01,PHENYLBUTAZONE,1135710,Phenylbutazone,21603935,8160 +M01AA03,OXYPHENBUTAZONE,19025925,Oxyphenbutazone,21603937,7816 +M01AB01,INDOMETACIN,1178663,Indomethacin,21603941,5781 +M01AB02,SULINDAC,1236607,Sulindac,21603942,10237 +M01AB03,TOLMETIN,1102917,Tolmetin,21603943,10636 +M01AB04,ZOMEPIRAC,19102108,zomepirac,21603944,39994 +M01AB08,ETODOLAC,1195492,Etodolac,21603948,24605 +M01AB15,KETOROLAC,1136980,Ketorolac,21603955,35827 +M01AC01,PIROXICAM,1146810,Piroxicam,21603961,8356 +M01AC06,MELOXICAM,1150345,meloxicam,21603965,41493 +M01AE01,IBUPROFEN,1177480,Ibuprofen,21603967,5640 +M01AE02,NAPROXEN,929887,lansoprazole,21603968,17128 +M01AE02,NAPROXEN,1115008,Naproxen,21603968,7258 +M01AE02,NAPROXEN,1154332,Pseudoephedrine,21603968,8896 +M01AE03,KETOPROFEN,1185922,Ketoprofen,21603969,6142 +M01AE04,FENOPROFEN,1153928,Fenoprofen,21603970,4331 +M01AE07,SUPROFEN,1036636,Suprofen,21603973,10255 +M01AE09,FLURBIPROFEN,1156378,Flurbiprofen,21603975,4502 +M01AE12,OXAPROZIN,1118045,oxaprozin,21603978,32613 +M01AE51,"IBUPROFEN, COMBINATIONS",1129625,Diphenhydramine,21603984,3498 +M01AE51,"IBUPROFEN, COMBINATIONS",1154332,Pseudoephedrine,21603984,8896 +M01AE51,"IBUPROFEN, COMBINATIONS",1174888,Hydrocodone,21603984,5489 +M01AE51,"IBUPROFEN, COMBINATIONS",1177480,Ibuprofen,21603984,5640 +M01AE51,"IBUPROFEN, COMBINATIONS",1192710,Chlorpheniramine,21603984,2400 +M01AG01,MEFENAMIC ACID,1197736,Mefenamate,21603987,257844 +M01AG04,MECLOFENAMIC ACID,1180182,Meclofenamate,21603990,588003 +M01AH01,CELECOXIB,1118084,celecoxib,21603992,140587 +M01AH02,ROFECOXIB,1189754,rofecoxib,21603993,232158 +M01AH03,VALDECOXIB,1103374,valdecoxib,21603994,278567 +M01AX,"OTHER ANTIINFLAM & ANTIRHEUMATIC AGNTS,NON-STEROID",1360332,Glucosamine,21603998,4845 +M01AX,"OTHER ANTIINFLAM & ANTIRHEUMATIC AGNTS,NON-STEROID",1363981,S-Adenosylmethionine,21603998,9504 +M01AX,"OTHER ANTIINFLAM & ANTIRHEUMATIC AGNTS,NON-STEROID",1389780,methylsulfonylmethane,21603998,23247 +M01AX,"OTHER ANTIINFLAM & ANTIRHEUMATIC AGNTS,NON-STEROID",1395573,Chondroitin Sulfates,21603998,2473 +M01AX,"OTHER ANTIINFLAM & ANTIRHEUMATIC AGNTS,NON-STEROID",19011773,Ascorbic Acid,21603998,1151 +M01AX,"OTHER ANTIINFLAM & ANTIRHEUMATIC AGNTS,NON-STEROID",19095164,Cholecalciferol,21603998,2418 +M01AX01,NABUMETONE,1113648,nabumetone,21603999,31448 +M01AX05,GLUCOSAMINE,1360332,Glucosamine,21604002,4845 +M01AX25,CHONDROITIN SULFATE,1395573,Chondroitin Sulfates,21604013,2473 +M01BX,OTHER ANTIINFLAM/ANTIRHEUM AGNTS COMB W/OTHER DRUG,929887,lansoprazole,21604020,17128 +M01BX,OTHER ANTIINFLAM/ANTIRHEUM AGNTS COMB W/OTHER DRUG,1115008,Naproxen,21604020,7258 +M01CB01,SODIUM AUROTHIOMALATE,1152134,Aurothiomalate,21604025,42547 +M01CB03,AURANOFIN,1114771,Auranofin,21604027,1227 +M01CB04,AUROTHIOGLUCOSE,1163570,Aurothioglucose,21604028,4980 +M01CC01,PENICILLAMINE,19028050,Penicillamine,21604031,7975 +M02AB01,CAPSAICIN,901656,Menthol,21604062,6750 +M02AB01,CAPSAICIN,938205,Camphor,21604062,1952 +M02AB01,CAPSAICIN,939881,Capsaicin,21604062,1992 +M02AB01,CAPSAICIN,1106647,Turpentine,21604062,10938 +M02AB01,CAPSAICIN,19055492,CAPSICUM OLEORESIN,21604062,235787 +M02AC,PREPARATIONS WITH SALICYLIC ACID DERIVATIVES,901656,Menthol,21604064,6750 +M02AC,PREPARATIONS WITH SALICYLIC ACID DERIVATIVES,909440,methyl salicylate,21604064,29787 +M02AC,PREPARATIONS WITH SALICYLIC ACID DERIVATIVES,917006,Benzocaine,21604064,1399 +M02AC,PREPARATIONS WITH SALICYLIC ACID DERIVATIVES,938205,Camphor,21604064,1952 +M02AC,PREPARATIONS WITH SALICYLIC ACID DERIVATIVES,939881,Capsaicin,21604064,1992 +M02AC,PREPARATIONS WITH SALICYLIC ACID DERIVATIVES,943116,trolamine salicylate,21604064,38866 +M02AX10,VARIOUS,901656,Menthol,21604068,6750 +M02AX10,VARIOUS,938205,Camphor,21604068,1952 +M03AA02,TUBOCURARINE,706644,Tubocurarine,21604073,10917 +M03AA04,DIMETHYLTUBOCURARINE,19009961,metocurine,21604074,29950 +M03AB01,SUXAMETHONIUM,836208,Succinylcholine,21604076,10154 +M03AC01,PANCURONIUM,19026674,Pancuronium,21604078,7883 +M03AC02,GALLAMINE,19057690,Gallamine,21604079,4638 +M03AC03,VECURONIUM,19012598,Vecuronium,21604080,71535 +M03AC04,ATRACURIUM,19014341,Atracurium,21604081,1218 +M03AC05,HEXAFLURONIUM,19001540,hexafluorenium,21604082,26826 +M03AC06,PIPECURONIUM BROMIDE,19025281,Pipecuronium,21604083,33742 +M03AC07,DOXACURIUM CHLORIDE,19091486,doxacurium,21604084,23651 +M03AC09,ROCURONIUM BROMIDE,19003953,Rocuronium,21604086,68139 +M03AC10,MIVACURIUM CHLORIDE,19010459,mivacurium,21604087,30077 +M03AC11,CISATRACURIUM,19015726,Cisatracurium,21604088,319864 +M03AX01,BOTULINUM TOXIN,729855,Botulinum Toxin Type A,21604090,1712 +M03AX01,BOTULINUM TOXIN,729959,botulinum toxin type B,21604090,1713 +M03BA02,CARISOPRODOL,749910,Carisoprodol,21604094,2101 +M03BA03,METHOCARBAMOL,704943,Methocarbamol,21604095,6845 +M03BA53,"METHOCARBAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",704943,Methocarbamol,21604100,6845 +M03BA53,"METHOCARBAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1112807,Aspirin,21604100,1191 +M03BB02,CHLORMEZANONE,19092290,Chlormezanone,21604105,2373 +M03BB03,CHLORZOXAZONE,795113,Chlorzoxazone,21604106,2410 +M03BC01,ORPHENADRINE (CITRATE),724394,Orphenadrine,21604112,7715 +M03BC51,"ORPHENADRINE, COMBINATIONS",724394,Orphenadrine,21604113,7715 +M03BC51,"ORPHENADRINE, COMBINATIONS",1112807,Aspirin,21604113,1191 +M03BC51,"ORPHENADRINE, COMBINATIONS",1125315,Acetaminophen,21604113,161 +M03BC51,"ORPHENADRINE, COMBINATIONS",1134439,Caffeine,21604113,1886 +M03BX,OTHER CENTRALLY ACTING AGENTS,780369,metaxalone,21604114,59078 +M03BX01,BACLOFEN,715233,Baclofen,21604115,1292 +M03BX02,TIZANIDINE,778474,tizanidine,21604116,57258 +M03BX08,CYCLOBENZAPRINE,778711,cyclobenzaprine,21604122,21949 +M04AA01,ALLOPURINOL,1167322,Allopurinol,21604131,519 +M04AA03,FEBUXOSTAT,19017742,febuxostat,21604133,73689 +M04AB01,PROBENECID,1151422,Probenecid,21604136,8698 +M04AB02,SULFINPYRAZONE,1236493,Sulfinpyrazone,21604137,10205 +M04AC01,COLCHICINE,1101554,Colchicine,21604141,2683 +M04AX,OTHER ANTIGOUT PREPARATIONS,1101554,Colchicine,21604143,2683 +M04AX,OTHER ANTIGOUT PREPARATIONS,1151422,Probenecid,21604143,8698 +M05BA01,ETIDRONIC ACID,1552929,Etidronate,21604149,42682 +M05BA03,PAMIDRONIC ACID,1511646,pamidronate,21604151,11473 +M05BA04,ALENDRONIC ACID,1557272,Alendronate,21604152,46041 +M05BA05,TILUDRONIC ACID,1578445,Tiludronate,21604153,57230 +M05BA06,IBANDRONIC ACID,1512480,Ibandronate,21604154,115264 +M05BA07,RISEDRONIC ACID,1516800,Risedronate,21604155,73056 +M05BA07,RISEDRONIC ACID,19035704,Calcium Carbonate,21604155,1897 +M05BA08,ZOLEDRONIC ACID,1524674,zoledronic acid,21604156,77655 +M05BB03,ALENDRONIC ACID AND COLECALCIFEROL,1557272,Alendronate,21604160,46041 +M05BB03,ALENDRONIC ACID AND COLECALCIFEROL,19095164,Cholecalciferol,21604160,2418 +M09AX,OTHER DRUGS FOR DISORDERS OF MUSCULO-SKELETAL SYS,705219,HYLAN G-F 20,21604178,284637 +M09AX,OTHER DRUGS FOR DISORDERS OF MUSCULO-SKELETAL SYS,766337,Guanidine,21604178,50675 +M09AX01,HYALURONIC ACID,787787,hyaluronate,21604179,62372 +M09AX01,HYALURONIC ACID,1395573,Chondroitin Sulfates,21604179,2473 +N01AF01,METHOHEXITAL,19005015,Methohexital,21604195,6847 +N01AF03,THIOPENTAL,700253,Thiopental,21604197,10493 +N01AH01,FENTANYL,1154029,Fentanyl,21604201,4337 +N01AH02,ALFENTANIL,19059528,Alfentanil,21604202,480 +N01AH03,SUFENTANIL,19078219,Sufentanil,21604203,56795 +N01AH06,REMIFENTANIL,19016749,remifentanil,21604206,73032 +N01AH51,"FENTANYL, COMBINATIONS",732893,Bupivacaine,21604207,1815 +N01AH51,"FENTANYL, COMBINATIONS",739323,Droperidol,21604207,3648 +N01AH51,"FENTANYL, COMBINATIONS",1136487,ropivacaine,21604207,35780 +N01AH51,"FENTANYL, COMBINATIONS",1154029,Fentanyl,21604207,4337 +N01AX01,DROPERIDOL,739323,Droperidol,21604209,3648 +N01AX03,KETAMINE,785649,Ketamine,21604210,6130 +N01AX07,ETOMIDATE,19050488,Etomidate,21604213,4177 +N01AX10,PROPOFOL,753626,Propofol,21604214,8782 +N01BA02,PROCAINE,751698,Procaine,21604223,8701 +N01BA03,TETRACAINE,1036884,Tetracaine,21604224,10391 +N01BA04,CHLOROPROCAINE,19049410,chloroprocaine,21604225,20859 +N01BB01,BUPIVACAINE,732893,Bupivacaine,21604229,1815 +N01BB02,LIDOCAINE,989878,Lidocaine,21604230,6387 +N01BB03,MEPIVACAINE,702774,Mepivacaine,21604231,6759 +N01BB04,PRILOCAINE,951279,Prilocaine,21604232,8686 +N01BB06,CINCHOCAINE,923840,Dibucaine,21604234,3339 +N01BB07,ETIDOCAINE,19050484,Etidocaine,21604235,4171 +N01BB09,ROPIVACAINE,1136487,ropivacaine,21604237,35780 +N01BB10,LEVOBUPIVACAINE,19098741,Levobupivacaine,21604238,259453 +N01BB20,COMBINATIONS,732893,Bupivacaine,21604239,1815 +N01BB20,COMBINATIONS,989878,Lidocaine,21604239,6387 +N01BB51,"BUPIVACAINE, COMBINATIONS",732893,Bupivacaine,21604240,1815 +N01BB51,"BUPIVACAINE, COMBINATIONS",1343916,Epinephrine,21604240,3992 +N01BB52,"LIDOCAINE, COMBINATIONS",916460,Benzalkonium,21604241,1378 +N01BB52,"LIDOCAINE, COMBINATIONS",939881,Capsaicin,21604241,1992 +N01BB52,"LIDOCAINE, COMBINATIONS",989878,Lidocaine,21604241,6387 +N01BB52,"LIDOCAINE, COMBINATIONS",1036884,Tetracaine,21604241,10391 +N01BB52,"LIDOCAINE, COMBINATIONS",1343916,Epinephrine,21604241,3992 +N01BB54,"PRILOCAINE, COMBINATIONS",951279,Prilocaine,21604243,8686 +N01BB54,"PRILOCAINE, COMBINATIONS",989878,Lidocaine,21604243,6387 +N01BB54,"PRILOCAINE, COMBINATIONS",1343916,Epinephrine,21604243,3992 +N01BB57,"ETIDOCAINE, COMBINATIONS",1343916,Epinephrine,21604244,3992 +N01BB57,"ETIDOCAINE, COMBINATIONS",19050484,Etidocaine,21604244,4171 +N01BB58,"ARTICAINE, COMBINATIONS",1343916,Epinephrine,21604245,3992 +N01BB58,"ARTICAINE, COMBINATIONS",19080512,Articaine,21604245,592464 +N01BC01,COCAINE,1001419,Cocaine,21604247,2653 +N01BX,OTHER LOCAL ANESTHETICS,942659,trichlorofluoromethane,21604248,38578 +N01BX,OTHER LOCAL ANESTHETICS,963747,dichlorodifluoromethane,21604248,50110 +N01BX01,ETHYL CHLORIDE,950316,Ethyl Chloride,21604249,4141 +N01BX02,DYCLONINE,992308,dyclonine,21604250,23744 +N02AA01,MORPHINE,1110410,Morphine,21604256,7052 +N02AA01,MORPHINE,19112635,Morphine Liposomal,21604256,477468 +N02AA02,OPIUM,923829,Opium,21604257,7676 +N02AA03,HYDROMORPHONE,1126658,Hydromorphone,21604258,3423 +N02AA05,OXYCODONE,1124957,Oxycodone,21604260,7804 +N02AA55,"OXYCODONE, COMBINATIONS",1112807,Aspirin,21604265,1191 +N02AA55,"OXYCODONE, COMBINATIONS",1124957,Oxycodone,21604265,7804 +N02AA55,"OXYCODONE, COMBINATIONS",1125315,Acetaminophen,21604265,161 +N02AA55,"OXYCODONE, COMBINATIONS",1177480,Ibuprofen,21604265,5640 +N02AA58,"DIHYDROCODEINE, COMBINATIONS",1125315,Acetaminophen,21604266,161 +N02AA58,"DIHYDROCODEINE, COMBINATIONS",1134439,Caffeine,21604266,1886 +N02AA58,"DIHYDROCODEINE, COMBINATIONS",1189596,dihydrocodeine,21604266,23088 +N02AA59,"CODEINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1112807,Aspirin,21604267,1191 +N02AA59,"CODEINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1125315,Acetaminophen,21604267,161 +N02AA59,"CODEINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1134439,Caffeine,21604267,1886 +N02AA59,"CODEINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1135766,Phenylephrine,21604267,8163 +N02AA59,"CODEINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1139699,butalbital,21604267,19860 +N02AA59,"CODEINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1154332,Pseudoephedrine,21604267,8896 +N02AA59,"CODEINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1163944,Guaifenesin,21604267,5032 +N02AA59,"CODEINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1192710,Chlorpheniramine,21604267,2400 +N02AA59,"CODEINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1201620,Codeine,21604267,2670 +N02AB02,PETHIDINE,1102527,Meperidine,21604271,6754 +N02AB03,FENTANYL,1154029,Fentanyl,21604272,4337 +N02AB52,"PETHIDINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1102527,Meperidine,21604273,6754 +N02AB52,"PETHIDINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1125315,Acetaminophen,21604273,161 +N02AB52,"PETHIDINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1153013,Promethazine,21604273,8745 +N02AC04,DEXTROPROPOXYPHENE,1153664,Propoxyphene,21604278,8785 +N02AC54,"DEXTROPROPOXYPHENE, COMB. EXCL. PSYCHOLEPTICS",1112807,Aspirin,21604281,1191 +N02AC54,"DEXTROPROPOXYPHENE, COMB. EXCL. PSYCHOLEPTICS",1125315,Acetaminophen,21604281,161 +N02AC54,"DEXTROPROPOXYPHENE, COMB. EXCL. PSYCHOLEPTICS",1134439,Caffeine,21604281,1886 +N02AC54,"DEXTROPROPOXYPHENE, COMB. EXCL. PSYCHOLEPTICS",1153664,Propoxyphene,21604281,8785 +N02AD,BENZOMORPHAN DERIVATIVES,1114220,Naloxone,21604283,7242 +N02AD,BENZOMORPHAN DERIVATIVES,1125315,Acetaminophen,21604283,161 +N02AD,BENZOMORPHAN DERIVATIVES,1130585,Pentazocine,21604283,8001 +N02AD01,PENTAZOCINE,1130585,Pentazocine,21604284,8001 +N02AE01,BUPRENORPHINE,1133201,Buprenorphine,21604287,1819 +N02AF01,BUTORPHANOL,1133732,Butorphanol,21604289,1841 +N02AF02,NALBUFINE,1114122,Nalbuphine,21604290,7238 +N02AX,OTHER OPIOIDS,1125765,Oxymorphone,21604296,7814 +N02AX,OTHER OPIOIDS,1189766,Levorphanol,21604296,6378 +N02AX02,TRAMADOL,1103314,Tramadol,21604298,10689 +N02AX03,DEZOCINE,19088393,dezocine,21604299,22713 +N02AX06,TAPENTADOL,19026459,tapentadol,21604301,787390 +N02AX52,"TRAMADOL, COMBINATIONS",1103314,Tramadol,21604302,10689 +N02AX52,"TRAMADOL, COMBINATIONS",1125315,Acetaminophen,21604302,161 +N02BA,SALICYLIC ACID AND DERIVATIVES,901656,Menthol,21604304,6750 +N02BA,SALICYLIC ACID AND DERIVATIVES,909440,methyl salicylate,21604304,29787 +N02BA,SALICYLIC ACID AND DERIVATIVES,964407,Salicylic Acid,21604304,9525 +N02BA,SALICYLIC ACID AND DERIVATIVES,1123904,phenyltoloxamine,21604304,33408 +N02BA,SALICYLIC ACID AND DERIVATIVES,1129625,Diphenhydramine,21604304,3498 +N02BA,SALICYLIC ACID AND DERIVATIVES,1168079,Magnesium Salicylate,21604304,52364 +N02BA,SALICYLIC ACID AND DERIVATIVES,1195334,Choline,21604304,2449 +N02BA,SALICYLIC ACID AND DERIVATIVES,19060877,Thiosalicylate,21604304,91099 +N02BA01,ACETYLSALICYLIC ACID,1112807,Aspirin,21604305,1191 +N02BA01,ACETYLSALICYLIC ACID,1551860,Pravastatin,21604305,42463 +N02BA03,CHOLINE SALICYLATE,1195334,Choline,21604307,2449 +N02BA04,SODIUM SALICYLATE,964407,Salicylic Acid,21604308,9525 +N02BA05,SALICYLAMIDE,1164108,salicylamide,21604309,9518 +N02BA06,SALSALATE,1137460,Salsalate,21604310,36108 +N02BA11,DIFLUNISAL,1126128,Diflunisal,21604315,3393 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",749910,Carisoprodol,21604320,2101 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1112807,Aspirin,21604320,1191 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1129625,Diphenhydramine,21604320,3498 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1134439,Caffeine,21604320,1886 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1135766,Phenylephrine,21604320,8163 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1139993,Phenylpropanolamine,21604320,8175 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1164108,salicylamide,21604320,9518 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1189596,dihydrocodeine,21604320,23088 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1192710,Chlorpheniramine,21604320,2400 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1201620,Codeine,21604320,2670 +N02BA51,"ACETYLSALICYLIC ACID, COMB. EXCL. PSYCHOLEPTICS",1551860,Pravastatin,21604320,42463 +N02BA71,"ACETYLSALICYLIC ACID, COMB WITH PSYCHOLEPTICS",702865,Meprobamate,21604325,6760 +N02BA71,"ACETYLSALICYLIC ACID, COMB WITH PSYCHOLEPTICS",1112807,Aspirin,21604325,1191 +N02BA71,"ACETYLSALICYLIC ACID, COMB WITH PSYCHOLEPTICS",1134439,Caffeine,21604325,1886 +N02BA71,"ACETYLSALICYLIC ACID, COMB WITH PSYCHOLEPTICS",1139699,butalbital,21604325,19860 +N02BA71,"ACETYLSALICYLIC ACID, COMB WITH PSYCHOLEPTICS",1201620,Codeine,21604325,2670 +N02BE01,PARACETAMOL,1125315,Acetaminophen,21604344,161 +N02BE01,PARACETAMOL,1129625,Diphenhydramine,21604344,3498 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",738818,Doxylamine,21604348,3642 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",749910,Carisoprodol,21604348,2101 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1112807,Aspirin,21604348,1191 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1119510,Dextromethorphan,21604348,3289 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1123904,phenyltoloxamine,21604348,33408 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1125315,Acetaminophen,21604348,161 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1129625,Diphenhydramine,21604348,3498 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1130863,Brompheniramine,21604348,1767 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1134439,Caffeine,21604348,1886 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1135766,Phenylephrine,21604348,8163 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1139993,Phenylpropanolamine,21604348,8175 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1154332,Pseudoephedrine,21604348,8896 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1159811,Pyrilamine,21604348,9009 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1163944,Guaifenesin,21604348,5032 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1164108,salicylamide,21604348,9518 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1168079,Magnesium Salicylate,21604348,52364 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1172206,pamabrom,21604348,54365 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1174888,Hydrocodone,21604348,5489 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1188052,dexbrompheniramine,21604348,22696 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1188114,dexchlorpheniramine,21604348,22697 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1189596,dihydrocodeine,21604348,23088 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1192710,Chlorpheniramine,21604348,2400 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1201620,Codeine,21604348,2670 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",1301152,Melatonin,21604348,6711 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",19009540,Vitamin E,21604348,11256 +N02BE51,"PARACETAMOL, COMBINATIONS EXCL. PSYCHOLEPTICS",19035704,Calcium Carbonate,21604348,1897 +N02BE71,"PARACETAMOL, COMBINATIONS WITH PSYCHOLEPTICS",1125315,Acetaminophen,21604351,161 +N02BE71,"PARACETAMOL, COMBINATIONS WITH PSYCHOLEPTICS",1134439,Caffeine,21604351,1886 +N02BE71,"PARACETAMOL, COMBINATIONS WITH PSYCHOLEPTICS",1139699,butalbital,21604351,19860 +N02BG08,ZICONOTIDE,19005061,ziconotide,21604361,68503 +N02C,ANTIMIGRAINE PREPARATIONS,1115008,Naproxen,21604364,7258 +N02C,ANTIMIGRAINE PREPARATIONS,1140643,Sumatriptan,21604364,37418 +N02CA01,DIHYDROERGOTAMINE,1126557,Dihydroergotamine,21604366,3418 +N02CA02,ERGOTAMINE,1145379,Ergotamine,21604367,4025 +N02CA04,METHYSERGIDE,1106740,Methysergide,21604368,6911 +N02CA52,"ERGOTAMINE, COMBINATIONS EXCL. PSYCHOLEPTICS",734275,Phenobarbital,21604371,8134 +N02CA52,"ERGOTAMINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1116109,Belladonna Alkaloids,21604371,1359 +N02CA52,"ERGOTAMINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1134439,Caffeine,21604371,1886 +N02CA52,"ERGOTAMINE, COMBINATIONS EXCL. PSYCHOLEPTICS",1145379,Ergotamine,21604371,4025 +N02CC01,SUMATRIPTAN,1140643,Sumatriptan,21604376,37418 +N02CC02,NARATRIPTAN,1118117,naratriptan,21604377,141366 +N02CC03,ZOLMITRIPTAN,1116031,zolmitriptan,21604378,135775 +N02CC04,RIZATRIPTAN,1154077,rizatriptan,21604379,88014 +N02CC05,ALMOTRIPTAN,1103552,almotriptan,21604380,279645 +N02CC06,ELETRIPTAN,1189697,eletriptan,21604381,231049 +N02CC07,FROVATRIPTAN,1189458,frovatriptan,21604382,228783 +N02CX,OTHER ANTIMIGRAINE PREPARATIONS,1103518,isometheptene,21604383,27946 +N02CX,OTHER ANTIMIGRAINE PREPARATIONS,1125315,Acetaminophen,21604383,161 +N02CX,OTHER ANTIMIGRAINE PREPARATIONS,1134439,Caffeine,21604383,1886 +N02CX,OTHER ANTIMIGRAINE PREPARATIONS,1189490,dichloralphenazone,21604383,22892 +N02CX02,CLONIDINE,1398937,Clonidine,21604385,2599 +N03AA01,METHYLPHENOBARBITAL,702685,Mephobarbital,21604392,6758 +N03AA02,PHENOBARBITAL,734275,Phenobarbital,21604393,8134 +N03AA03,PRIMIDONE,751347,Primidone,21604394,8691 +N03AA30,METHARBITAL,19004254,metharbital,21604396,6825 +N03AB01,ETHOTOIN,750146,Ethotoin,21604398,4136 +N03AB04,MEPHENYTOIN,702661,Mephenytoin,21604401,6757 +N03AC01,PARAMETHADIONE,19021932,paramethadione,21604406,32894 +N03AC02,TRIMETHADIONE,19005629,Trimethadione,21604407,10827 +N03AD01,ETHOSUXIMIDE,750119,Ethosuximide,21604410,4135 +N03AD02,PHENSUXIMIDE,19023842,phensuximide,21604411,33309 +N03AD03,MESUXIMIDE,759401,methsuximide,21604412,47858 +N03AE01,CLONAZEPAM,798874,Clonazepam,21604415,2598 +N03AF01,CARBAMAZEPINE,740275,Carbamazepine,21604417,2002 +N03AF02,OXCARBAZEPINE,718122,oxcarbazepine,21604418,32624 +N03AF03,RUFINAMIDE,19006586,rufinamide,21604419,69036 +N03AG01,VALPROIC ACID,745466,Valproate,21604422,40254 +N03AG06,TIAGABINE,715458,tiagabine,21604427,31914 +N03AX07,PHENACEMIDE,19023286,phenacemide,21604430,33253 +N03AX09,LAMOTRIGINE,705103,lamotrigine,21604431,28439 +N03AX10,FELBAMATE,795661,felbamate,21604432,24812 +N03AX11,TOPIRAMATE,742267,topiramate,21604433,38404 +N03AX12,GABAPENTIN,797399,gabapentin,21604434,25480 +N03AX14,LEVETIRACETAM,711584,Levetiracetam,21604436,114477 +N03AX15,ZONISAMIDE,744798,zonisamide,21604437,39998 +N03AX16,PREGABALIN,734354,pregabalin,21604438,187832 +N03AX18,LACOSAMIDE,19087394,lacosamide,21604440,623400 +N04AA01,TRIHEXYPHENIDYL,705178,Trihexyphenidyl,21604446,10811 +N04AA04,PROCYCLIDINE,752276,Procyclidine,21604449,8718 +N04AA05,PROFENAMINE,19050123,ethopropazine,21604450,4134 +N04AB02,ORPHENADRINE (CHLORIDE),724394,Orphenadrine,21604458,7715 +N04AC01,BENZATROPINE,719174,Benztropine,21604460,1424 +N04BA01,LEVODOPA,789578,Levodopa,21604464,6375 +N04BA02,LEVODOPA AND DECARBOXYLASE INHIBITOR,740560,Carbidopa,21604465,2019 +N04BA02,LEVODOPA AND DECARBOXYLASE INHIBITOR,789578,Levodopa,21604465,6375 +N04BB01,AMANTADINE,19087090,Amantadine,21604471,620 +N04BC01,BROMOCRIPTINE,730548,Bromocriptine,21604473,1760 +N04BC02,PERGOLIDE,732309,Pergolide,21604474,8047 +N04BC04,ROPINIROLE,713823,ropinirole,21604476,72302 +N04BC05,PRAMIPEXOLE,720810,Pramipexole,21604477,746741 +N04BC07,APOMORPHINE,837027,Apomorphine,21604479,1043 +N04BC09,ROTIGOTINE,786426,Rotigotine,21604481,616739 +N04BD01,SELEGILINE,766209,Selegiline,21604483,9639 +N04BD02,RASAGILINE,715710,rasagiline,21604484,134748 +N04BX,OTHER DOPAMINERGIC AGENTS,740560,Carbidopa,21604485,2019 +N04BX,OTHER DOPAMINERGIC AGENTS,782211,entacapone,21604485,60307 +N04BX,OTHER DOPAMINERGIC AGENTS,789578,Levodopa,21604485,6375 +N04BX01,TOLCAPONE,715727,tolcapone,21604486,72937 +N04BX02,ENTACAPONE,782211,entacapone,21604487,60307 +N05AA01,CHLORPROMAZINE,794852,Chlorpromazine,21604492,2403 +N05AA02,LEVOMEPROMAZINE,19005147,Methotrimeprazine,21604493,6852 +N05AA03,PROMAZINE,19052903,Promazine,21604494,8742 +N05AA05,TRIFLUPROMAZINE,19005104,Triflupromazine,21604496,10805 +N05AB02,FLUPHENAZINE,756018,Fluphenazine,21604501,4496 +N05AB03,PERPHENAZINE,733008,Perphenazine,21604502,8076 +N05AB04,PROCHLORPERAZINE,752061,Prochlorperazine,21604503,8704 +N05AB06,TRIFLUOPERAZINE,704984,Trifluoperazine,21604505,10800 +N05AB07,ACETOPHENAZINE,19029555,acetophenazine,21604506,16735 +N05AC02,THIORIDAZINE,700299,Thioridazine,21604512,10502 +N05AC03,MESORIDAZINE,703083,Mesoridazine,21604513,6779 +N05AD01,HALOPERIDOL,766529,Haloperidol,21604516,5093 +N05AE02,MOLINDONE,709699,Molindone,21604527,7019 +N05AE04,ZIPRASIDONE,712615,ziprasidone,21604529,115698 +N05AF03,CHLORPROTHIXENE,19095002,Chlorprothixene,21604533,2406 +N05AF04,TIOTIXENE,700465,Thiothixene,21604534,10510 +N05AG02,PIMOZIDE,745790,Pimozide,21604538,8331 +N05AH01,LOXAPINE,792263,Loxapine,21604541,6475 +N05AH02,CLOZAPINE,800878,Clozapine,21604542,2626 +N05AH03,OLANZAPINE,785788,olanzapine,21604543,61381 +N05AH04,QUETIAPINE,766814,quetiapine,21604544,51272 +N05AN01,LITHIUM,751246,Lithium Carbonate,21604556,42351 +N05AN01,LITHIUM,767410,lithium citrate,21604556,52105 +N05AX08,RISPERIDONE,735979,Risperidone,21604559,35636 +N05AX12,ARIPIPRAZOLE,757688,aripiprazole,21604562,89013 +N05AX13,PALIPERIDONE,703244,paliperidone,21604563,679314 +N05BA01,DIAZEPAM,723013,Diazepam,21604566,3322 +N05BA02,CHLORDIAZEPOXIDE,990678,Chlordiazepoxide,21604567,2356 +N05BA04,OXAZEPAM,724816,Oxazepam,21604569,7781 +N05BA05,POTASSIUM CLORAZEPATE,790253,Chlorazepate,21604570,2353 +N05BA06,LORAZEPAM,791967,Lorazepam,21604571,6470 +N05BA11,PRAZEPAM,19050461,Prazepam,21604576,8627 +N05BA12,ALPRAZOLAM,781039,Alprazolam,21604577,596 +N05BA13,HALAZEPAM,801396,halazepam,21604578,26412 +N05BB01,HYDROXYZINE,777221,Hydroxyzine,21604590,5553 +N05BC01,MEPROBAMATE,702865,Meprobamate,21604594,6760 +N05BE01,BUSPIRONE,733301,Buspirone,21604601,1827 +N05CA01,PENTOBARBITAL,730729,Pentobarbital,21604608,8004 +N05CA02,AMOBARBITAL,712757,Amobarbital,21604609,719 +N05CA03,BUTOBARBITAL,959174,butabarbital,21604610,477631 +N05CA05,APROBARBITAL,19030299,aprobarbital,21604612,17381 +N05CA06,SECOBARBITAL,766067,Secobarbital,21604613,9624 +N05CA07,TALBUTAL,19059149,talbutal,21604614,89810 +N05CA16,HEXOBARBITAL,19068964,Hexobarbital,21604621,5302 +N05CB01,COMBINATIONS OF BARBITURATES,712757,Amobarbital,21604627,719 +N05CB01,COMBINATIONS OF BARBITURATES,766067,Secobarbital,21604627,9624 +N05CC01,CHLORAL HYDRATE,742594,trichloroacetaldehyde,21604630,38574 +N05CD01,FLURAZEPAM,756349,Flurazepam,21604636,4501 +N05CD04,ESTAZOLAM,748010,Estazolam,21604639,4077 +N05CD05,TRIAZOLAM,704599,Triazolam,21604640,10767 +N05CD07,TEMAZEPAM,836715,Temazepam,21604642,10355 +N05CD08,MIDAZOLAM,708298,Midazolam,21604643,6960 +N05CD10,QUAZEPAM,731188,quazepam,21604645,35185 +N05CE01,GLUTETHIMIDE,19061124,Glutethimide,21604650,4903 +N05CE02,METHYPRYLON,19006742,Methyprylon,21604651,6910 +N05CF03,ZALEPLON,720727,zaleplon,21604656,74667 +N05CF04,ESZOPICLONE,757352,Eszopiclone,21604657,461016 +N05CH01,MELATONIN,1301152,Melatonin,21604659,6711 +N05CH01,MELATONIN,1353228,Vitamin B6,21604659,42954 +N05CH01,MELATONIN,19037401,calcium phosphate,21604659,1919 +N05CH01,MELATONIN,19100575,theanine,21604659,38022 +N05CH02,RAMELTEON,781182,ramelteon,21604660,596205 +N05CM,OTHER HYPNOTICS AND SEDATIVES,19052620,CHAMOMILE FLOWERS,21604661,221916 +N05CM01,METHAQUALONE,19004160,Methaqualone,21604662,6823 +N05CM04,CARBROMAL,19033243,carbromal,21604665,2067 +N05CM05,SCOPOLAMINE,965748,Scopolamine,21604666,9601 +N05CM08,ETHCHLORVYNOL,749727,Ethchlorvynol,21604669,4118 +N05CM09,VALERIAN,1307353,Valerian extract,21604670,285250 +N05CM09,VALERIAN,1397059,VALERIAN ROOT,21604670,253206 +N05CM09,VALERIAN,1398499,Hops extract,21604670,259266 +N05CM18,DEXMEDETOMIDINE,19061088,Dexmedetomidine,21604677,48937 +N06A,ANTIDEPRESSANTS,766209,Selegiline,21604686,9639 +N06AA01,DESIPRAMINE,716968,Desipramine,21604688,3247 +N06AA02,IMIPRAMINE,778268,Imipramine,21604689,5691 +N06AA06,TRIMIPRAMINE,705755,Trimipramine,21604693,10834 +N06AA10,NORTRIPTYLINE,721724,Nortriptyline,21604697,7531 +N06AA11,PROTRIPTYLINE,754270,Protriptyline,21604698,8886 +N06AA12,DOXEPIN,738156,Doxepin,21604699,3638 +N06AA17,AMOXAPINE,713109,Amoxapine,21604704,722 +N06AA21,MAPROTILINE,794147,Maprotiline,21604707,6646 +N06AB03,FLUOXETINE,755695,Fluoxetine,21604711,4493 +N06AB04,CITALOPRAM,797617,Citalopram,21604712,2556 +N06AB05,PAROXETINE,722031,Paroxetine,21604713,32937 +N06AB06,SERTRALINE,739138,Sertraline,21604714,36437 +N06AB08,FLUVOXAMINE,751412,Fluvoxamine,21604716,42355 +N06AB10,ESCITALOPRAM,715939,Escitalopram,21604718,321988 +N06AF01,ISOCARBOXAZID,781705,Isocarboxazid,21604720,6011 +N06AF03,PHENELZINE,733896,Phenelzine,21604722,8123 +N06AF04,TRANYLCYPROMINE,703470,Tranylcypromine,21604723,10734 +N06AX,OTHER ANTIDEPRESSANTS,1363516,5-Hydroxytryptophan,21604729,94 +N06AX02,TRYPTOPHAN,19006186,Tryptophan,21604731,10898 +N06AX06,NEFAZODONE,714684,nefazodone,21604735,31565 +N06AX11,MIRTAZAPINE,725131,Mirtazapine,21604740,15996 +N06AX12,BUPROPION,750982,Bupropion,21604741,42347 +N06AX16,VENLAFAXINE,743670,venlafaxine,21604745,39786 +N06AX17,MILNACIPRAN,19080226,milnacipran,21604746,588250 +N06AX21,DULOXETINE,715259,duloxetine,21604749,72625 +N06AX23,DESVENLAFAXINE,717607,Desvenlafaxine,21604751,734064 +N06BA,CENTRALLY ACTING SYMPATHOMIMETICS,19090984,armodafinil,21604753,641465 +N06BA01,AMFETAMINE,714785,Amphetamine,21604754,725 +N06BA01,AMFETAMINE,719311,Dextroamphetamine,21604754,3288 +N06BA02,DEXAMFETAMINE,719311,Dextroamphetamine,21604755,3288 +N06BA03,METAMFETAMINE,704053,Methamphetamine,21604756,6816 +N06BA04,METHYLPHENIDATE,705944,Methylphenidate,21604757,6901 +N06BA05,PEMOLINE,727835,Pemoline,21604758,7966 +N06BA07,MODAFINIL,710650,modafinil,21604760,30125 +N06BA09,ATOMOXETINE,742185,atomoxetine,21604762,38400 +N06BA11,DEXMETHYLPHENIDATE,731533,dexmethylphenidate,21604764,352372 +N06BC01,CAFFEINE,1134439,Caffeine,21604766,1886 +N06BC01,CAFFEINE,1560524,Glucose,21604766,4850 +N06BX,OTHER PSYCHOSTIMULANTS AND NOOTROPICS,769935,Sodium Oxybate,21604768,9899 +N06BX04,DEANOL,1311826,Deanol,21604772,3116 +N06BX12,ACETYLCARNITINE,19037596,Acetylcarnitine,21604780,193 +N06CA,ANTIDEPRESSANTS IN COMBINATION WITH PSYCHOLEPTICS,755695,Fluoxetine,21604788,4493 +N06CA,ANTIDEPRESSANTS IN COMBINATION WITH PSYCHOLEPTICS,785788,olanzapine,21604788,61381 +N06DA01,TACRINE,836654,Tacrine,21604794,10318 +N06DA02,DONEPEZIL,715997,donepezil,21604795,135447 +N06DA03,RIVASTIGMINE,733523,rivastigmine,21604796,183379 +N06DA04,GALANTAMINE,757627,Galantamine,21604797,4637 +N06DX,OTHER ANTI-DEMENTIA DRUGS,1391889,Ginkgo biloba extract,21604798,236809 +N06DX,OTHER ANTI-DEMENTIA DRUGS,19008269,Vincamine,21604798,11201 +N06DX,OTHER ANTI-DEMENTIA DRUGS,19098505,GINKGO BILOBA LEAF,21604798,259265 +N06DX,OTHER ANTI-DEMENTIA DRUGS,19098769,Korean Ginseng Root Extract,21604798,259471 +N06DX01,MEMANTINE,701322,Memantine,21604799,6719 +N06DX02,GINKGO BILOBA,1391889,Ginkgo biloba extract,21604800,236809 +N06DX02,GINKGO BILOBA,1398560,GINKGO BILOBA LEAF EXTRACT,21604800,259316 +N07AA,ANTICHOLINESTERASES,740924,Edrophonium,21604803,3752 +N07AA01,NEOSTIGMINE,717136,Neostigmine,21604804,7315 +N07AA02,PYRIDOSTIGMINE,759740,Pyridostigmine,21604805,9000 +N07AA30,AMBENONIUM,787362,Ambenonium,21604807,623 +N07AX01,PILOCARPINE,945286,Pilocarpine,21604813,8328 +N07AX03,CEVIMELINE,954819,cevimeline,21604815,44281 +N07BA,DRUGS USED IN NICOTINE DEPENDENCE,19016725,silver acetate,21604817,137939 +N07BA01,NICOTINE,718583,Nicotine,21604818,7407 +N07BA03,VARENICLINE,780442,varenicline,21604819,591622 +N07BB,DRUGS USED IN ALCOHOL DEPENDENCE,19014158,nalmefene,21604820,31479 +N07BB01,DISULFIRAM,735850,Disulfiram,21604821,3554 +N07BB03,ACAMPROSATE,19043959,acamprosate,21604823,82819 +N07BB04,NALTREXONE,1714319,Naltrexone,21604824,7243 +N07BC01,BUPRENORPHINE,1133201,Buprenorphine,21604826,1819 +N07BC02,METHADONE,1103640,Methadone,21604827,6813 +N07BC03,LEVACETYLMETHADOL,19003959,Methadyl Acetate,21604828,6814 +N07BC51,"BUPRENORPHINE, COMBINATIONS",1114220,Naloxone,21604830,7242 +N07BC51,"BUPRENORPHINE, COMBINATIONS",1133201,Buprenorphine,21604830,1819 +N07XX02,RILUZOLE,735951,Riluzole,21604842,35623 +N07XX06,TETRABENAZINE,836877,Tetrabenazine,21604846,10390 +P01AA,HYDROXYQUINOLINE DERIVATIVES,928006,Iodoquinol,21604850,3435 +P01AB01,METRONIDAZOLE,937791,bismuth subsalicylate,21604857,19478 +P01AB01,METRONIDAZOLE,1707164,Metronidazole,21604857,6922 +P01AB01,METRONIDAZOLE,1836948,Tetracycline,21604857,10395 +P01AB02,TINIDAZOLE,1702559,Tinidazole,21604858,10612 +P01AX02,EMETINE,19041857,Emetine,21604876,3820 +P01AX05,MEPACRINE,19060400,Quinacrine,21604878,9061 +P01AX06,ATOVAQUONE,1781733,Atovaquone,21604879,60212 +P01AX07,TRIMETREXATE,1750928,Trimetrexate,21604880,42333 +P01AX11,NITAZOXAMIDE,1715315,nitazoxanide,21604884,31819 +P01BA01,CHLOROQUINE,1792515,Chloroquine,21604888,2393 +P01BA02,HYDROXYCHLOROQUINE,1777087,Hydroxychloroquine,21604889,5521 +P01BA03,PRIMAQUINE,1751310,Primaquine,21604890,8687 +P01BB51,"PROGUANIL, COMBINATIONS",1781733,Atovaquone,21604895,60212 +P01BB51,"PROGUANIL, COMBINATIONS",1792429,Chloroguanide,21604895,2382 +P01BC01,QUININE,1760616,Quinine,21604897,9071 +P01BC02,MEFLOQUINE,19000498,Mefloquine,21604898,6694 +P01BD01,PYRIMETHAMINE,1760039,Pyrimethamine,21604900,9010 +P01BD51,"PYRIMETHAMINE, COMBINATIONS",1760039,Pyrimethamine,21604901,9010 +P01BD51,"PYRIMETHAMINE, COMBINATIONS",1836410,Sulfadoxine,21604901,10173 +P01BE52,"ARTEMETHER, COMBINATIONS",19033634,artemether,0,18343 +P01BE52,"ARTEMETHER, COMBINATIONS",19048037,lumefantrine,0,847728 +P01BX01,HALOFANTRINE,1766340,halofantrine,21604910,50749 +P01CX01,PENTAMIDINE ISETHIONATE,1730370,Pentamidine,21604924,7994 +P02BA01,PRAZIQUANTEL,1750461,Praziquantel,21604930,8628 +P02BA02,OXAMNIQUINE,19024775,Oxamniquine,21604931,7778 +P02CA01,MEBENDAZOLE,1794280,Mebendazole,21604941,6672 +P02CA02,TIABENDAZOLE,1837289,Thiabendazole,21604942,10450 +P02CA03,ALBENDAZOLE,1753745,Albendazole,21604943,430 +P02CB01,PIPERAZINE,19046291,piperazine,21604949,8340 +P02CB02,DIETHYLCARBAMAZINE,19025698,Diethylcarbamazine,21604950,3384 +P02CC01,PYRANTEL,1759270,Pyrantel,21604952,8984 +P02CE01,LEVAMISOLE,1389464,Levamisole,21604955,6371 +P02CF01,IVERMECTIN,1784444,Ivermectin,21604957,6069 +P02DA01,NICLOSAMIDE,19018416,Niclosamide,21604963,7402 +P03AA,SULFUR CONTAINING PRODUCTS,917006,Benzocaine,21604969,1399 +P03AA,SULFUR CONTAINING PRODUCTS,1036525,Sulfur,21604969,10223 +P03AB02,LINDANE,916751,Lindane,21604978,1388 +P03AB02,LINDANE,989878,Lidocaine,21604978,6387 +P03AC01,PYRETHRUM,959665,Pyrethrins,21604981,8991 +P03AC03,PHENOTHRIN,19023819,phenothrin,21604983,33303 +P03AC04,PERMETHRIN,922868,Permethrin,21604984,33199 +P03AC51,"PYRETHRUM, COMBINATIONS",916460,Benzalkonium,21604985,1378 +P03AC51,"PYRETHRUM, COMBINATIONS",946340,Piperonyl Butoxide,21604985,8345 +P03AC51,"PYRETHRUM, COMBINATIONS",959665,Pyrethrins,21604985,8991 +P03AX,"OTHER ECTOPARASITICIDES, INCL. SCABICIDES",969276,crotamiton,21604989,21766 +P03AX03,MALATHION,993979,Malathion,21604992,6606 +P03BX01,DIETHYLTOLUAMIDE,19079469,Deet,21605001,3129 +R01AA03,EPHEDRINE,1143374,Ephedrine,21605012,3966 +R01AA03,EPHEDRINE,1343916,Epinephrine,21605012,3992 +R01AA04,PHENYLEPHRINE,1135766,Phenylephrine,21605013,8163 +R01AA05,OXYMETAZOLINE,925636,Oxymetazoline,21605014,7812 +R01AA06,TETRYZOLINE,941577,tetrahydrozoline,21605015,37935 +R01AA07,XYLOMETAZOLINE,943852,xylometazoline,21605016,39841 +R01AA08,NAPHAZOLINE,914533,Naphazoline,21605017,7247 +R01AA14,EPINEPHRINE,1343916,Epinephrine,21605023,3992 +R01AB01,PHENYLEPHRINE,933952,Pheniramine,21605025,8132 +R01AB01,PHENYLEPHRINE,1135766,Phenylephrine,21605025,8163 +R01AB07,OXYMETAZOLINE,925636,Oxymetazoline,21605030,7812 +R01AC01,CROMOGLICIC ACID,1152631,Cromolyn,21605033,42612 +R01AC03,AZELASTINE,934075,azelastine,21605035,18603 +R01AC08,OLOPATADINE,915855,olopatadine,21605040,135391 +R01AD01,BECLOMETASONE,1115572,Beclomethasone,21605043,1347 +R01AD04,FLUNISOLIDE,1196514,flunisolide,21605046,25120 +R01AD05,BUDESONIDE,939259,Budesonide,21605047,19831 +R01AD08,FLUTICASONE,1149380,fluticasone,21605050,41126 +R01AD09,MOMETASONE,905233,Mometasone,21605051,108118 +R01AD11,TRIAMCINOLONE,903963,Triamcinolone,21605052,10759 +R01AD12,FLUTICASONE FUROATE,1149380,fluticasone,21605053,41126 +S01FA01,ATROPINE,914335,Atropine,21605060,1223 +S01FA02,SCOPOLAMINE,965748,Scopolamine,21605061,9601 +S01FA02,SCOPOLAMINE,1135766,Phenylephrine,21605061,8163 +S01FA04,CYCLOPENTOLATE,910232,Cyclopentolate,21605063,3001 +S01FA04,CYCLOPENTOLATE,1135766,Phenylephrine,21605063,8163 +S01FA05,HOMATROPINE,1101703,homatropine,21605064,27084 +S01FA06,TROPICAMIDE,906072,Tropicamide,21605065,10869 +S01FA56,"TROPICAMIDE, COMBINATIONS",906072,Tropicamide,21605066,10869 +S01FA56,"TROPICAMIDE, COMBINATIONS",19026274,p-Hydroxyamphetamine,21605066,7839 +S01FB,SYMPATHOMIMETICS EXCL. ANTIGLAUCOMA PREPARATIONS,19026274,p-Hydroxyamphetamine,21605067,7839 +S01FB01,PHENYLEPHRINE,1135766,Phenylephrine,21605068,8163 +S01GA01,NAPHAZOLINE,914533,Naphazoline,21605073,7247 +S01GA02,TETRYZOLINE,941577,tetrahydrozoline,21605074,37935 +S01GA04,OXYMETAZOLINE,925636,Oxymetazoline,21605076,7812 +S01GA05,PHENYLEPHRINE,1135766,Phenylephrine,21605077,8163 +S01GA51,"NAPHAZOLINE, COMBINATIONS",902251,hypromellose,21605079,27334 +S01GA51,"NAPHAZOLINE, COMBINATIONS",914533,Naphazoline,21605079,7247 +S01GA51,"NAPHAZOLINE, COMBINATIONS",933952,Pheniramine,21605079,8132 +S01GA51,"NAPHAZOLINE, COMBINATIONS",948487,Polyethylene Glycol 300,21605079,8513 +S01GA51,"NAPHAZOLINE, COMBINATIONS",951237,Antazoline,21605079,865 +S01GA51,"NAPHAZOLINE, COMBINATIONS",961145,Glycerin,21605079,4910 +S01GA51,"NAPHAZOLINE, COMBINATIONS",19044522,Zinc Sulfate,21605079,39954 +S01GA52,"TETRYZOLINE, COMBINATIONS",941577,tetrahydrozoline,21605080,37935 +S01GA52,"TETRYZOLINE, COMBINATIONS",948515,Polyethylene Glycols,21605080,8516 +S01GA52,"TETRYZOLINE, COMBINATIONS",19044522,Zinc Sulfate,21605080,39954 +S01GA55,"PHENYLEPHRINE, COMBINATIONS",1036059,Antipyrine,21605082,1001 +S01GA55,"PHENYLEPHRINE, COMBINATIONS",1135766,Phenylephrine,21605082,8163 +S01GX01,CROMOGLICIC ACID,1152631,Cromolyn,21605085,42612 +S01GX02,LEVOCABASTINE,907553,levocabastine,21605086,28627 +S01GX04,NEDOCROMIL,1114620,Nedocromil,21605088,31563 +S01GX05,LODOXAMIDE,967496,Lodoxamide,21605089,52151 +S01GX06,EMEDASTINE,903893,emedastine,21605090,28144 +S01GX07,AZELASTINE,934075,azelastine,21605091,18603 +S01GX08,KETOTIFEN,986117,Ketotifen,21605092,6146 +S01GX09,OLOPATADINE,915855,olopatadine,21605093,135391 +S01GX10,EPINASTINE,943634,epinastine,21605094,39684 +S01HA03,TETRACAINE,1036884,Tetracaine,21605100,10391 +S01HA04,PROXYMETACAINE,929504,proxymetacaine,21605101,34905 +S01JA,COLOURING AGENTS,935529,Benoxinate,21605107,18889 +S01JA,COLOURING AGENTS,19132210,Oftasceine Disodium,21605107,806916 +S01JA01,FLUORESCEIN,996625,Fluorescein,21605108,25138 +S01JA02,ROSE BENGAL SODIUM,19063871,Rose Bengal,21605109,9471 +S01JA51,"FLUORESCEIN, COMBINATIONS",929504,proxymetacaine,21605110,34905 +S01JA51,"FLUORESCEIN, COMBINATIONS",935529,Benoxinate,21605110,18889 +S01JA51,"FLUORESCEIN, COMBINATIONS",996625,Fluorescein,21605110,25138 +S01KA01,HYALURONIC ACID,787787,hyaluronate,21605114,62372 +S01KA02,HYPROMELLOSE,902251,hypromellose,21605115,27334 +S01KA51,"HYALURONIC ACID, COMBINATIONS",787787,hyaluronate,21605116,62372 +S01KA51,"HYALURONIC ACID, COMBINATIONS",1395573,Chondroitin Sulfates,21605116,2473 +S01KX,OTHER SURGICAL AIDS,19006155,Trypan Blue,21605117,10878 +S01LA01,VERTEPORFIN,912803,Verteporfin,21605121,118886 +S01LA03,PEGAPTANIB,19063605,pegaptanib,21605123,498509 +S01LA04,RANIBIZUMAB,19080982,ranibizumab,21605124,595060 +S01XA03,"SODIUM CHLORIDE, HYPERTONIC",967823,Sodium Chloride,21605129,9863 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,902251,hypromellose,21605143,27334 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,905371,Methylcellulose,21605143,6873 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,908523,Mineral Oil,21605143,6972 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,929128,Propylene glycol,21605143,34693 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,942172,"Petrolatum, White",21605143,82074 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,943191,tyloxapol,21605143,38998 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,948490,Polyethylene Glycol 400,21605143,8514 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,948760,Polysorbate 80,21605143,8560 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,948856,Polyvinyl Alcohol,21605143,8570 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,949279,Carboxymethylcellulose,21605143,2062 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,950056,Povidone,21605143,8610 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,961145,Glycerin,21605143,4910 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,967823,Sodium Chloride,21605143,9863 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,978577,"Mineral Oil, Light",21605143,577312 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,1319156,Dextran 70,21605143,3274 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,1352890,Dextran,21605143,42635 +S01XA20,ARTIFICIAL TEARS & OTHER INDIFFERENT PREPARATIONS,19002257,hydroxypropylcellulose,21605143,27291 +S02AA,ANTIINFECTIVES,923081,Ofloxacin,21605146,7623 +S02AA01,CHLORAMPHENICOL,990069,Chloramphenicol,21605147,2348 +S02AA10,ACETIC ACID,929549,Acetic Acid,21605156,168 +S02AA15,CIPROFLOXACIN,1797513,Ciprofloxacin,21605161,2551 +S02AA30,"ANTIINFECTIVES, COMBINATIONS",927478,pramoxine,21605163,34347 +S02AA30,"ANTIINFECTIVES, COMBINATIONS",949459,chloroxylenol,21605163,20877 +S02AA30,"ANTIINFECTIVES, COMBINATIONS",979096,Zinc Acetate,21605163,58295 +S02BA08,FLUOCINOLONE ACETONIDE,996541,fluocinolone,21605170,25126 +S02CA03,HYDROCORTISONE AND ANTIINFECTIVES,915981,Neomycin,21605175,7299 +S02CA03,HYDROCORTISONE AND ANTIINFECTIVES,927478,pramoxine,21605175,34347 +S02CA03,HYDROCORTISONE AND ANTIINFECTIVES,929549,Acetic Acid,21605175,168 +S02CA03,HYDROCORTISONE AND ANTIINFECTIVES,948582,Polymyxin B,21605175,8536 +S02CA03,HYDROCORTISONE AND ANTIINFECTIVES,949459,chloroxylenol,21605175,20877 +S02CA03,HYDROCORTISONE AND ANTIINFECTIVES,975125,Hydrocortisone,21605175,5492 +S02CA03,HYDROCORTISONE AND ANTIINFECTIVES,1797513,Ciprofloxacin,21605175,2551 +S02CA06,DEXAMETHASONE AND ANTIINFECTIVES,1518254,Dexamethasone,21605178,3264 +S02CA06,DEXAMETHASONE AND ANTIINFECTIVES,1797513,Ciprofloxacin,21605178,2551 +S02DA,ANALGESICS AND ANESTHETICS,917006,Benzocaine,21605181,1399 +S02DA01,LIDOCAINE,989878,Lidocaine,21605182,6387 +S02DA30,COMBINATIONS,916460,Benzalkonium,21605185,1378 +S02DA30,COMBINATIONS,917006,Benzocaine,21605185,1399 +S02DA30,COMBINATIONS,927478,pramoxine,21605185,34347 +S02DA30,COMBINATIONS,949459,chloroxylenol,21605185,20877 +S02DA30,COMBINATIONS,979096,Zinc Acetate,21605185,58295 +S02DA30,COMBINATIONS,1036059,Antipyrine,21605185,1001 +S02DA30,COMBINATIONS,1135766,Phenylephrine,21605185,8163 +S02DC,INDIFFERENT PREPARATIONS,942765,TRIETHANOLAMINE POLYPEPTIDE OLEATE CONDENSATE,21605186,38624 +S02DC,INDIFFERENT PREPARATIONS,958999,carbamide peroxide,21605186,47686 +V01AA04,MOULD FUNGUS AND YEAST FUNGUS,590768,Mold Extract,21605219,235618 +V01AA04,MOULD FUNGUS AND YEAST FUNGUS,19057718,Trichophyton antigen,21605219,465118 +V01AA07,INSECTS,514834,Honey bee venom,21605221,124427 +V01AA07,INSECTS,19006951,Yellow Jacket Venom Protein,21605221,285170 +V01AA07,INSECTS,19014846,White faced hornet venom,21605221,124428 +V01AA07,INSECTS,19055259,HYMENOPTERA ALLERGENIC EXTRACT,21605221,235614 +V01AA07,INSECTS,19097029,Mixed vespid venom,21605221,253189 +V01AA07,INSECTS,19099126,WASP VENOM PROTEIN,21605221,260051 +V03AB,ANTIDOTES,740924,Edrophonium,21605229,3752 +V03AB,ANTIDOTES,910888,Cysteamine,21605229,3022 +V03AB,ANTIDOTES,914335,Atropine,21605229,1223 +V03AB,ANTIDOTES,979096,Zinc Acetate,21605229,58295 +V03AB,ANTIDOTES,1728909,Succimer,21605229,3446 +V03AB,ANTIDOTES,19004969,Trientine,21605229,10798 +V03AB,ANTIDOTES,19011565,Zinc-DTPA,21605229,11431 +V03AB,ANTIDOTES,19015348,pentetate calcium trisodium,21605229,132879 +V03AB01,IPECACUANHA,1781321,Ipecac,21605230,5975 +V03AB03,EDETATES,1741008,Edetic Acid,21605232,3755 +V03AB04,PRALIDOXIME,914335,Atropine,21605233,1223 +V03AB04,PRALIDOXIME,1727468,pralidoxime,21605233,34345 +V03AB06,THIOSULFATE,940004,sodium thiosulfate,21605235,36726 +V03AB08,SODIUM NITRITE,940004,sodium thiosulfate,21605236,36726 +V03AB08,SODIUM NITRITE,19069907,Sodium Nitrite,21605236,9894 +V03AB09,DIMERCAPROL,1728903,Dimercaprol,21605237,3445 +V03AB14,PROTAMINE,19054242,Protamine Sulfate (USP),21605239,8825 +V03AB15,NALOXONE,1114220,Naloxone,21605240,7242 +V03AB17,METHYLTHIONINIUM CHLORIDE,905518,Methylene blue,21605242,6878 +V03AB19,PHYSOSTIGMINE,19044337,Physostigmine,21605244,8299 +V03AB21,POTASSIUM IODIDE,19049909,Potassium Iodide,21605246,8597 +V03AB22,AMYL NITRITE,940004,sodium thiosulfate,21605247,36726 +V03AB22,AMYL NITRITE,1319051,Amyl Nitrite,21605247,742 +V03AB23,ACETYLCYSTEINE,1139042,Acetylcysteine,21605248,197 +V03AB24,DIGITALIS ANTITOXIN,19045317,digoxin antibodies Fab fragments,21605249,203223 +V03AB25,FLUMAZENIL,19055153,Flumazenil,21605250,4457 +V03AB26,METHIONINE,19004724,Methionine,21605251,6837 +V03AB31,PRUSSIAN BLUE,19011393,Insoluble berlin blue stain,21605254,705707 +V03AB32,GLUTATHIONE,19061083,Glutathione,21605255,4890 +V03AB33,HYDROXOCOBALAMIN,1377023,Hydroxocobalamin,21605256,5514 +V03AB34,FOMEPIZOLE,19022479,fomepizole,21605257,15226 +V03AC01,DEFEROXAMINE,1711947,Deferoxamine,21605260,3131 +V03AC03,DEFERASIROX,1786055,deferasirox,21605262,614373 +V03AE,DRUGS FOR TX OF HYPERKALEMIA &HYPERPHOSPOSPHATEMIA,908464,magnesium carbonate,21605263,29155 +V03AE,DRUGS FOR TX OF HYPERKALEMIA &HYPERPHOSPOSPHATEMIA,951469,calcium acetate,21605263,214342 +V03AE,DRUGS FOR TX OF HYPERKALEMIA &HYPERPHOSPOSPHATEMIA,1387426,Folate,21605263,62356 +V03AE,DRUGS FOR TX OF HYPERKALEMIA &HYPERPHOSPOSPHATEMIA,19035704,Calcium Carbonate,21605263,1897 +V03AE01,POLYSTYRENE SULFONATE,19078126,Sodium polystyrene sulfonate,21605264,56512 +V03AE02,SEVELAMER,993997,sevelamer carbonate,21605265,660890 +V03AE03,LANTHANUM CARBONATE,990028,lanthanum carbonate,21605266,234416 +V03AE04,CALCIUM ACETATE AND MAGNESIUM CARBONATE,908464,magnesium carbonate,21605267,29155 +V03AE04,CALCIUM ACETATE AND MAGNESIUM CARBONATE,951469,calcium acetate,21605267,214342 +V03AF01,MESNA,1354698,Mesna,21605269,44 +V03AF01,MESNA,19078187,Ifosfamide,21605269,5657 +V03AF02,DEXRAZOXANE,1353011,Dexrazoxane,21605270,42736 +V03AF03,CALCIUM FOLINATE,1388796,Leucovorin,21605271,6313 +V03AF04,CALCIUM LEVOFOLINATE,1388796,Leucovorin,21605272,6313 +V03AF05,AMIFOSTINE,1350040,Amifostine,21605273,4126 +V03AF07,RASBURICASE,1304565,Rasburicase,21605275,283821 +V03AF08,PALIFERMIN,19038562,Palifermin,21605276,196319 +V03AG,DRUGS FOR TREATMENT OF HYPERCALCEMIA,19097605,gallium nitrate,21605279,25544 +V03AH01,DIAZOXIDE,1523280,Diazoxide,21605282,3327 +V03AX,OTHER THERAPEUTIC PRODUCTS,711452,Benzoate,21605291,70589 +V03AX,OTHER THERAPEUTIC PRODUCTS,942494,chlorophyllin copper complex,21605291,82242 +V03AX,OTHER THERAPEUTIC PRODUCTS,1511856,phenylacetate,21605291,70619 +V03AX,OTHER THERAPEUTIC PRODUCTS,1741008,Edetic Acid,21605291,3755 +V03AX,OTHER THERAPEUTIC PRODUCTS,19027339,potassium perchlorate,21605291,34318 +V03AX,OTHER THERAPEUTIC PRODUCTS,19087067,4-Aminobenzoate,21605291,618974 +V03AZ01,ETHANOL,955372,Ethanol,21605294,448 +V04CA01,TOLBUTAMIDE,1502855,Tolbutamide,21605299,10635 +V04CA02,GLUCOSE,1560524,Glucose,21605300,4850 +V04CC03,SINCALIDE,19067803,Sincalide,21605306,9800 +V04CD,TESTS FOR PITUITARY FUNCTION,19006410,Arginine,21605308,1091 +V04CD01,METYRAPONE,19007490,Metyrapone,21605309,6923 +V04CE02,SULFOBROMOPHTALEIN,19000826,Sulfobromophthalein,21605315,10212 +V04CF01,TUBERCULIN,19058274,Purified Protein Derivative of Tuberculin,21605317,8948 +V04CG03,HISTAMINE PHOSPHATE,19069019,Histamine,21605321,5333 +V04CG04,PENTAGASTRIN,19030376,Pentagastrin,21605322,7993 +V04CH01,INULIN AND OTHER POLYFRUCTOSANS,980478,Inulin,21605326,5924 +V04CH02,INDIGO CARMINE,19017390,Indigotindisulfonate,21605327,325514 +V04CH30,AMINOHIPPURIC ACID,19053177,p-Aminohippurate,21605330,42837 +V04CJ01,THYROTROPIN,19063297,thyrotropin alfa (USP),21605332,4952 +V04CJ02,PROTIRELIN,19001701,Thyrotropin-Releasing Hormone,21605333,10580 +V04CK01,SECRETIN,19084212,Human Secretin,21605335,606396 +V04CK03,BENTIROMIDE,19035595,bentiromide,21605337,18896 +V04CL,TESTS FOR ALLERGIC DISEASES,514834,Honey bee venom,21605338,124427 +V04CL,TESTS FOR ALLERGIC DISEASES,19006951,Yellow Jacket Venom Protein,21605338,285170 +V04CL,TESTS FOR ALLERGIC DISEASES,19014846,White faced hornet venom,21605338,124428 +V04CL,TESTS FOR ALLERGIC DISEASES,19055259,HYMENOPTERA ALLERGENIC EXTRACT,21605338,235614 +V04CL,TESTS FOR ALLERGIC DISEASES,19097029,Mixed vespid venom,21605338,253189 +V04CL,TESTS FOR ALLERGIC DISEASES,19099126,WASP VENOM PROTEIN,21605338,260051 +V04CX,OTHER DIAGNOSTIC AGENTS,996625,Fluorescein,21605341,25138 +V04CX,OTHER DIAGNOSTIC AGENTS,19003412,iso-sulfan blue,21605341,27863 +V04CX,OTHER DIAGNOSTIC AGENTS,19024227,Methacholine,21605341,155080 +V04CX,OTHER DIAGNOSTIC AGENTS,19054337,[13C] urea,21605341,226724 +V04CX,OTHER DIAGNOSTIC AGENTS,19078612,Indocyanine Green,21605341,5775 +V04CX,OTHER DIAGNOSTIC AGENTS,19101568,Coccidioidin,21605341,2660 +V06A,DIET FORMULATIONS FOR TREATMENT OF OBESITY,917006,Benzocaine,21605343,1399 +V06A,DIET FORMULATIONS FOR TREATMENT OF OBESITY,964407,Salicylic Acid,21605343,9525 +V06A,DIET FORMULATIONS FOR TREATMENT OF OBESITY,1134439,Caffeine,21605343,1886 +V06A,DIET FORMULATIONS FOR TREATMENT OF OBESITY,1164108,salicylamide,21605343,9518 +V06DC01,GLUCOSE,1560524,Glucose,21605352,4850 +V06DC02,FRUCTOSE,956691,Fructose,21605353,4570 +V06DD,"AMINO ACIDS,INCL. COMBINATIONS WITH POLYPEPTIDES",19006410,Arginine,21605354,1091 +V06DD,"AMINO ACIDS,INCL. COMBINATIONS WITH POLYPEPTIDES",19006692,Tyrosine,21605354,10962 +V06DD,"AMINO ACIDS,INCL. COMBINATIONS WITH POLYPEPTIDES",19010955,Cysteine,21605354,3024 +V06DD,"AMINO ACIDS,INCL. COMBINATIONS WITH POLYPEPTIDES",19024365,Ornithine,21605354,7704 +V06DD,"AMINO ACIDS,INCL. COMBINATIONS WITH POLYPEPTIDES",19035577,Phenylalanine,21605354,8156 +V06DD,"AMINO ACIDS,INCL. COMBINATIONS WITH POLYPEPTIDES",19092377,Lysine,21605354,6536 +V06DD,"AMINO ACIDS,INCL. COMBINATIONS WITH POLYPEPTIDES",19097664,Citrulline,21605354,2567 +V06DE,"AMINO ACIDS/CARBOHYDRATES/MINERALS/VITAMINS, COMB",19006410,Arginine,21605355,1091 +V06DE,"AMINO ACIDS/CARBOHYDRATES/MINERALS/VITAMINS, COMB",19035704,Calcium Carbonate,21605355,1897 +V07AB,"SOLVENTS & DILUTING AGENTS,INCL. IRRIGATING SOLNS",967823,Sodium Chloride,21605361,9863 +V07AB,"SOLVENTS & DILUTING AGENTS,INCL. IRRIGATING SOLNS",1319156,Dextran 70,21605361,3274 +V07AB,"SOLVENTS & DILUTING AGENTS,INCL. IRRIGATING SOLNS",19010309,Water,21605361,11295 +V07AC,"BLOOD TRANSFUSION, AUXILIARY PRODUCTS",977968,sodium citrate,21605362,56466 +V07AV,TECHNICAL DISINFECTANTS,1790812,Chlorhexidine,21605368,2358 +V07AX,WASHING AGENTS ETC.,967823,Sodium Chloride,21605369,9863 +V07AX,WASHING AGENTS ETC.,19024665,Poloxamer,21605369,155156 +V07AY,OTHER NON-THERAPEUTIC AUXILIARY PRODUCTS,19058092,Gelatin,21605370,4716 +V07AY,OTHER NON-THERAPEUTIC AUXILIARY PRODUCTS,19087208,Lactose,21605370,6211 +V08AA01,DIATRIZOIC ACID,19022596,Diatrizoate,21605375,3319 +V08AA03,IODAMIDE,19080542,Iodamide,21605377,5928 +V08AB02,IOHEXOL,19080985,Iohexol,21605387,5956 +V08AB05,IOPROMIDE,19003206,iopromide,21605390,27781 +V08AB12,IOXILAN,19003249,ioxilan,21605397,27793 +V08AC06,IOPANOIC ACID,19081256,Iopanoic Acid,21605404,5967 +V08AC07,IOCETAMIC ACID,19033638,iocetamic acid,21605405,183830 +V08AC08,SODIUM IOPODATE,19081385,Ipodate,21605406,5976 +V08AC09,TYROPANOIC ACID,19006659,Tyropanoate,21605407,10960 +V08AC10,CALCIUM IOPODATE,19081385,Ipodate,21605408,5976 +V08AD01,ETHYL ESTERS OF IODISED FATTY ACIDS,19050016,Ethiodized Oil,21605410,4125 +V08AD03,PROPYLIODONE,19054048,Propyliodone,21605412,8793 +V08CA04,GADOTERIDOL,19097463,gadoteridol,21605423,25483 +V08CA05,MANGAFODIPIR,19092105,MANGAFODIPIR,21605424,236987 +V08CA06,GADOVERSETAMIDE,19089496,gadoversetamide,21605425,228833 +V08CA08,GADOBENIC ACID,19007652,Gadobenate,21605427,692620 +V08CA10,GADOXETIC ACID,19031583,gadoxetate,21605429,802624 +V08CB,SUPERPARAMAGNETIC CONTRAST MEDIA,19015703,ferumoxides,21605431,72901 +V08CB01,FERUMOXSIL,19024772,ferumoxsil,21605432,77754 +M03BA03,Methocarbamol,704943,Methocarbamol,21604095,6845 +M03BA53,"Methocarbamol, combinations excl. psycholeptics",704943,Methocarbamol,21604100,6845 +M03BA73,"Methocarbamol, combinations with psycholeptics",704943,Methocarbamol,21604103,6845 +N06BA05,Pemoline,727835,Pemoline,21604758,7966 +A08AA01,Phentermine,735340,Phentermine,21600682,8152 +C01CA11,Mephentermine,735340,Phentermine,21600291,8152 +N05CF02,Zolpidem,744740,zolpidem,21604655,39993 +N05CF04,eszopiclone�,757352,Eszopiclone,21604657,461016 +N05CH02,Ramelteon,781182,ramelteon,21604660,596205 +A02BC04,Rabeprazole,911735,rabeprazole,21600099,114979 +A03AA07 �,dicycloverine�,924724,Dicyclomine,0,3361 +G04BX13,Dimethyl sulfoxide,928980,Dimethyl Sulfoxide,21602664,3455 +M02AX03,Dimethyl sulfoxide,928980,Dimethyl Sulfoxide,21604067,3455 +D10AX01 ,Aluminium chloride ,957393,aluminum chloride,0,46241 +D11AX18,Diclofenac,1124300,Diclofenac,21602355,3355 +M01AB05,Diclofenac,1124300,Diclofenac,21603945,3355 +M01AB55,"Diclofenac, combinations",1124300,Diclofenac,21603959,3355 +M02AA15,Diclofenac,1124300,Diclofenac,21604051,3355 +S01BC03,Diclofenac,1124300,Diclofenac,21603641,3355 +S01CC01,Diclofenac and antiinfectives,1124300,Diclofenac,21603670,3355 +R05DB01,Benzonatate,1136601,benzonatate,21603410,18993 +N02BA06,Salsalate,1137460,Salsalate,21604310,36108 +S01BC11,bromfenac,1139179,bromfenac,21603649,19737 +L01AX04,Dacarbazine,1311409,Dacarbazine,21601420,3098 +B02BD08 �,eptacog alfa (activated)�,1352141,Factor VIIa,0,4256 +J01MA15,Gemifloxacin,1716721,gemifloxacin,21603022,138099 +J01MA16,Gatifloxacin,1789276,gatifloxacin,21603023,228476 +S01AX21,Gatifloxacin,1789276,gatifloxacin,21603614,228476 +D01AC06 �,tiabendazole�,1837289,Thiabendazole,0,10450 +P02CA02,tiabendazole�,1837289,Thiabendazole,21604942,10450 +J05AF07,Tenofovir disoproxil,19011093,Tenofovir,21603166,117466 +J05AR03,Tenofovir disoproxil and emtricitabine,19011093,Tenofovir,21603183,117466 +J05AR06,"Emtricitabine, tenofovir disoproxil and efavirenz",19011093,Tenofovir,21603186,117466 +J04AB30,Capreomycin,19026710,Capreomycin,21603101,78903 +G03DC05,Unknown,19041933,tibolone,0,38260 +L04AA01,Unknown,19010482,Cyclosporine,0,3008 +V03AB49,Unknown,987245,Lactulose,0,6218 +G04BX49,Unknown,1363053,Doxazosin,0,49276 +M01AX49,Unknown,1102917,Tolmetin,0,10636 +B03AB49,Unknown,1399177,Sodium ferric gluconate complex,0,261435 +M05BX99,Unknown,19058572,Calcium Citrate,0,47613 +M05BX99,Unknown,19037038,Calcium Gluconate,0,1908 +C02CA49,Unknown,1341238,Terazosin,0,37798 +M05BA49,Unknown,1557272,Alendronate,0,46041 +S01EX03,Unknown,954688,latanoprost,0,43611 +M04AX49,Unknown,19046291,piperazine,0,8340 +A05AA49,Unknown,988095,Ursodeoxycholate,0,62427 +L04AA05,Unknown,950637,Tacrolimus,0,42316 +D03AX08,Unknown,1383925,Isosorbide Dinitrate,0,6058 +G03FB49,Unknown,1549080,"Estrogens, Conjugated (USP)",0,4099 +N02AA99,Unknown,1112807,Aspirin,0,1191 +N02AA99,Unknown,1124957,Oxycodone,0,7804 +N02AA99,Unknown,1125315,Acetaminophen,0,161 +N02AA99,Unknown,1177480,Ibuprofen,0,5640 +R05DA49,Unknown,1189596,dihydrocodeine,0,23088 +J01DA06,Unknown,1778162,Cefuroxime,0,2194 +B03AC49,Unknown,1395773,"ferric oxide, saccharated",0,24909 +J01DA13,Unknown,1777806,Ceftriaxone,0,2193 +J01DA08,Unknown,1768849,Cefaclor,0,2176 +A02EA01,Unknown,908464,magnesium carbonate,0,29155 +A02EA01,Unknown,985247,Aluminum Hydroxide,0,612 +S01CA49,Unknown,919345,Gentamicin Sulfate (USP),0,142438 +A04AD49,Unknown,928744,Dimenhydrinate,0,3444 +J01DA41,Unknown,1738366,cefprozil,0,19552 +N04BC49,Unknown,19091472,Lisuride,0,6446 +G04AC01,Unknown,920293,Nitrofurantoin,0,7454 +J01DA31,Unknown,1786842,Cephradine,0,2239 +N05CM17,Unknown,1301152,Melatonin,0,6711 +N05CM17,Unknown,1353228,Vitamin B6,0,42954 +N05CM17,Unknown,19037401,calcium phosphate,0,1919 +N05CM17,Unknown,19100575,theanine,0,38022 +N05AK01,Unknown,836877,Tetrabenazine,0,10390 +L04AA11,Unknown,1151789,Etanercept,0,214555 +B03AA49,Unknown,1300751,Polysaccharide iron complex,0,105669 +R06AE08,Unknown,1136422,levocetirizine,0,356887 +J01DA39,Unknown,1749083,ceftibuten,0,20492 +J01DA01,Unknown,1786621,Cephalexin,0,2231 +J01DA11,Unknown,1776684,Ceftazidime,0,2191 +C10AA51,Unknown,1539403,Simvastatin,0,36567 +N02AC02,Unknown,1103640,Methadone,0,6813 +J01DA23,Unknown,1796435,Cefixime,0,25033 +N06AE02,Unknown,751412,Fluvoxamine,0,42355 +V03AZ49,Unknown,19012660,Magnesium Pidolate,0,116240 +A02DA01,Unknown,966991,Simethicone,0,9796 +L01XX28,Unknown,1304107,imatinib,0,282388 +J01DA38,Unknown,1708100,loracarbef,0,28981 +J01DA17,Unknown,19072857,Cefonicid,0,2183 +V03AF49,Unknown,1388796,Leucovorin,0,6313 +L04AA14,Unknown,1114375,anakinra,0,72435 +N07AA05,Unknown,715997,donepezil,0,135447 +L04AA17,Unknown,1119119,adalimumab,0,327361 +R03DA49,Unknown,19088167,Ambroxol,0,625 +J01DA04,Unknown,1771162,Cefazolin,0,2180 +A01AC99,Unknown,19026096,Diflucortolone,0,3392 +A03FA99,Unknown,906780,Metoclopramide,0,6915 +J01DA10,Unknown,1774470,Cefotaxime,0,2186 +J01DA33,Unknown,1749008,cefpodoxime,0,20489 +S02AA49,Unknown,902722,Tobramycin,0,10627 +P01BA05,Unknown,19000498,Mefloquine,0,6694 +G04AA01,Unknown,904356,Methenamine,0,6832 +G04AA01,Unknown,939871,sodium phosphate,0,36709 +G04AA01,Unknown,986389,"SODIUM PHOSPHATE,MONOBASIC,MONOHYDRATE",0,221125 +G04AA01,Unknown,990499,"Sodium Phosphate, Monobasic",0,235496 +L01XX34,Unknown,1325363,erlotinib,0,337525 +L04AA12,Unknown,937368,infliximab,0,191831 +J01DA24,Unknown,1748975,cefepime,0,20481 +S01BB49,Unknown,915981,Neomycin,0,7299 +S01BB49,Unknown,1518254,Dexamethasone,0,3264 +S01BB49,Unknown,948582,Polymyxin B,0,8536 +S01BB49,Unknown,902722,Tobramycin,0,10627 +J01DA03,Unknown,19086759,Cephalothin,0,2236 +V03AB30,Unknown,1714319,Naltrexone,0,7243 +V03AA01,Unknown,735850,Disulfiram,0,3554 +L01BB01,Unknown,19014878,Azathioprine,0,1256 +N06AA22,Unknown,743670,venlafaxine,0,39786 +J01DA22,Unknown,1777254,Ceftizoxime,0,2192 +N02CX04,Unknown,1140643,Sumatriptan,0,37418 +N06BX19,Unknown,1391889,Ginkgo biloba extract,0,236809 +N06BX19,Unknown,1398560,GINKGO BILOBA LEAF EXTRACT,0,259316 +L03AA04,Unknown,1385645,Interferon Alfa-n3,0,612937 +G04BX05,Unknown,1381504,Alprostadil,0,598 +B01AC14,Unknown,1381253,anagrelide,0,596724 +J01DA07,Unknown,19070174,Cefamandole,0,2178 +J05AB10,Unknown,1704183,Lamivudine,0,68244 +R03CA01,Unknown,1343916,Epinephrine,0,3992 +R03CA01,Unknown,1192710,Chlorpheniramine,0,2400 +V03AB07,Unknown,837027,Apomorphine,0,1043 +B04AD01,Unknown,19095309,Cholestyramine,0,2447 +H02AB16,Unknown,939259,Budesonide,0,19831 +V03AA03,Unknown,19043959,acamprosate,0,82819 +D11AX15,Pimecrolimus,915935,Pimecrolimus,0,321952 +A11CC07,Paricalcitol,1517740,paricalcitol,0,73710 +D11AX14,Tacrolimus,950637,Tacrolimus,0,42316 +C10AX04,Benfluorex,19035533,benfluorex,0,18880 +N07BA02,Bupropion,750982,Bupropion,0,42347 diff --git a/src/org/ohdsi/whiteRabbit/etls/ars/Fields.xlsx b/src/org/ohdsi/whiteRabbit/etls/ars/Fields.xlsx new file mode 100644 index 00000000..0c801c28 Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/etls/ars/Fields.xlsx differ diff --git a/src/org/ohdsi/whiteRabbit/etls/ars/proc_OUTPAT.csv b/src/org/ohdsi/whiteRabbit/etls/ars/proc_OUTPAT.csv new file mode 100644 index 00000000..b68b4be7 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/etls/ars/proc_OUTPAT.csv @@ -0,0 +1,1728 @@ +PROC_COD,TYPE_OUTPAT +91.90.2,CLIN +91.90.3,CLIN +91.90.4,CLIN +91.90.5,CLIN +91.90.6,CLIN +91.90.7,CLIN +91.90.8,CLIN +92.29.9,CLIN +99.82,CLIN +99.82.1,CLIN +C.02,CLIN +C.03,CLIN +C.04,CLIN +C.05,CLIN +C.06,CLIN +T.01,CLIN +T.02,CLIN +T.03,CLIN +89.01,CLIN +89.03,CLIN +89.07,CLIN +89.13,CLIN +89.26,CLIN +38.22,CLIN +38.22.1,CLIN +89.39.1,CLIN +89.39.2,CLIN +89.39.3,CLIN +89.39.4,CLIN +89.7,CLIN +86.19.1,CLIN +86.19.2,CLIN +86.19.3,CLIN +86.19.4,CLIN +93.01.5,CLIN +93.07.1,CLIN +93.18.1,CLIN +93.18.2,CLIN +93.29,CLIN +93.36,CLIN +93.37,CLIN +93.39.2,CLIN +93.39.5,CLIN +93.46,CLIN +93.49.2,CLIN +90.70.3,CLIN +90.78.1,CLIN +93.59.1,CLIN +93.82.1,CLIN +93.82.2,CLIN +93.89.5,CLIN +93.89.6,CLIN +93.94,CLIN +93.99,CLIN +93.99.1,CLIN +94.01.1,CLIN +94.01.2,CLIN +94.02.1,CLIN +94.02.2,CLIN +94.08.1,CLIN +94.08.2,CLIN +94.08.3,CLIN +94.08.4,CLIN +94.08.5,CLIN +94.08.6,CLIN +94.09,CLIN +94.12.1,CLIN +94.19.1,CLIN +94.3,CLIN +94.32,CLIN +94.42,CLIN +94.44,CLIN +95.01,CLIN +95.02,CLIN +96.61,CLIN +97.1,CLIN +97.88,CLIN +99.12,CLIN +99.13,CLIN +99.15.1,CLIN +99.29.7,CLIN +91.90.1,CLIN +92.18.2,IMAG +92.18.3,IMAG +92.18.4,IMAG +92.18.5,IMAG +92.18.6,IMAG +92.19.1,IMAG +92.19.2,IMAG +92.19.3,IMAG +92.19.5,IMAG +92.19.6,IMAG +92.19.7,IMAG +92.19.8,IMAG +87.99.1,IMAG +87.99.2,IMAG +88.01.1,IMAG +88.01.2,IMAG +88.01.3,IMAG +88.01.4,IMAG +88.01.5,IMAG +88.01.6,IMAG +88.03.1,IMAG +88.04,IMAG +88.19,IMAG +88.21,IMAG +88.22,IMAG +88.23,IMAG +88.25,IMAG +88.26,IMAG +92.01.1,IMAG +92.01.2,IMAG +92.01.3,IMAG +92.01.4,IMAG +92.02.1,IMAG +92.02.2,IMAG +92.02.3,IMAG +92.02.4,IMAG +92.02.5,IMAG +92.03.1,IMAG +92.03.2,IMAG +92.03.3,IMAG +92.03.4,IMAG +92.03.5,IMAG +92.04.1,IMAG +92.04.2,IMAG +92.04.3,IMAG +92.04.4,IMAG +92.04.5,IMAG +92.05.1,IMAG +92.05.2,IMAG +92.05.3,IMAG +92.05.4,IMAG +92.05.5,IMAG +92.05.6,IMAG +92.09.1,IMAG +92.09.2,IMAG +92.09.3,IMAG +92.09.4,IMAG +92.09.5,IMAG +92.09.6,IMAG +92.09.7,IMAG +92.11.1,IMAG +92.11.2,IMAG +92.11.5,IMAG +92.11.6,IMAG +92.11.7,IMAG +92.13,IMAG +92.14.1,IMAG +92.14.2,IMAG +92.14.3,IMAG +92.15.1,IMAG +92.15.2,IMAG +92.15.3,IMAG +92.15.4,IMAG +92.15.5,IMAG +92.16.1,IMAG +92.18.1,IMAG +87.07,IMAG +87.09.1,IMAG +87.09.2,IMAG +87.11.1,IMAG +87.11.2,IMAG +87.11.3,IMAG +87.11.4,IMAG +87.12.1,IMAG +87.12.2,IMAG +87.13.1,IMAG +87.13.2,IMAG +87.16.1,IMAG +87.16.2,IMAG +87.16.3,IMAG +87.16.4,IMAG +87.17.1,IMAG +87.17.2,IMAG +87.17.3,IMAG +87.22,IMAG +87.23,IMAG +87.24,IMAG +87.29,IMAG +87.35,IMAG +87.37.1,IMAG +87.37.2,IMAG +87.37.3,IMAG +87.38,IMAG +87.41,IMAG +87.41.1,IMAG +87.42.1,IMAG +87.42.2,IMAG +87.42.3,IMAG +87.43.1,IMAG +87.43.2,IMAG +87.44.1,IMAG +87.44.2,IMAG +87.49.1,IMAG +87.52,IMAG +87.54.1,IMAG +87.59.1,IMAG +87.61,IMAG +87.62,IMAG +87.62.1,IMAG +87.62.2,IMAG +87.62.3,IMAG +87.63,IMAG +87.64,IMAG +87.65.1,IMAG +87.65.2,IMAG +87.65.3,IMAG +87.66,IMAG +87.69.1,IMAG +87.72,IMAG +87.73,IMAG +87.74.1,IMAG +87.74.2,IMAG +87.75.1,IMAG +87.76,IMAG +87.76.1,IMAG +87.77,IMAG +87.77.1,IMAG +87.79.1,IMAG +87.83,IMAG +87.89.1,IMAG +88.90.3,IMAG +88.90.4,IMAG +88.91.1,IMAG +88.91.2,IMAG +88.91.3,IMAG +88.91.4,IMAG +88.91.5,IMAG +88.91.6,IMAG +88.91.7,IMAG +88.91.8,IMAG +88.91.A,IMAG +88.91.B,IMAG +88.91.C,IMAG +88.92,IMAG +88.92.1,IMAG +88.92.2,IMAG +88.92.3,IMAG +88.92.4,IMAG +88.92.5,IMAG +88.92.6,IMAG +88.92.7,IMAG +88.92.8,IMAG +88.92.9,IMAG +88.93,IMAG +88.93.1,IMAG +88.94.1,IMAG +88.94.2,IMAG +88.94.3,IMAG +88.95.1,IMAG +88.95.2,IMAG +88.95.3,IMAG +88.95.4,IMAG +88.95.5,IMAG +88.95.6,IMAG +88.97.1,IMAG +88.97.2,IMAG +88.97.3,IMAG +88.99.1,IMAG +88.99.2,IMAG +88.99.3,IMAG +88.99.4,IMAG +88.99.5,IMAG +89.58.1,IMAG +89.58.2,IMAG +89.58.3,IMAG +89.58.4,IMAG +89.58.5,IMAG +89.58.6,IMAG +89.58.7,IMAG +89.58.8,IMAG +87.03,IMAG +87.03.1,IMAG +87.03.2,IMAG +87.03.3,IMAG +87.03.4,IMAG +87.03.5,IMAG +87.03.6,IMAG +87.03.7,IMAG +87.03.8,IMAG +87.03.9,IMAG +87.04.1,IMAG +87.05,IMAG +87.06,IMAG +87.06.1,IMAG +88.27,IMAG +88.28,IMAG +88.29.1,IMAG +88.29.2,IMAG +88.31,IMAG +88.31.1,IMAG +88.32,IMAG +88.33.1,IMAG +88.33.2,IMAG +88.35.1,IMAG +88.37.1,IMAG +88.38.1,IMAG +88.38.2,IMAG +88.38.3,IMAG +88.38.4,IMAG +88.38.5,IMAG +88.38.6,IMAG +88.38.7,IMAG +88.38.8,IMAG +88.39.1,IMAG +88.39.5,IMAG +88.42.1,IMAG +88.42.2,IMAG +88.48,IMAG +88.60.1,IMAG +88.61.1,IMAG +88.61.2,IMAG +88.63.1,IMAG +88.63.2,IMAG +88.65.1,IMAG +88.65.2,IMAG +88.65.3,IMAG +88.66.1,IMAG +88.66.2,IMAG +88.71.1,IMAG +88.71.2,IMAG +88.71.3,IMAG +88.71.4,IMAG +88.73.1,IMAG +88.73.2,IMAG +88.73.3,IMAG +88.73.4,IMAG +88.73.5,IMAG +88.74.1,IMAG +88.75.1,IMAG +88.76.1,IMAG +88.77.1,IMAG +88.77.2,IMAG +88.77.3,IMAG +88.78,IMAG +88.78.1,IMAG +88.78.2,IMAG +88.79.1,IMAG +88.79.2,IMAG +88.79.3,IMAG +88.79.5,IMAG +88.79.6,IMAG +88.79.7,IMAG +88.79.8,IMAG +88.83.1,IMAG +88.85,IMAG +88.89,IMAG +88.90.1,IMAG +88.90.2,IMAG +89.04.1,LAB +45.29.1,LAB +45.29.2,LAB +45.29.3,LAB +64.19.2,LAB +44.19.2,LAB +90.47.4,LAB +90.47.5,LAB +90.47.6,LAB +90.47.7,LAB +90.48.1,LAB +90.48.2,LAB +90.48.3,LAB +90.48.4,LAB +90.48.5,LAB +90.49.1,LAB +90.49.2,LAB +90.49.3,LAB +90.49.4,LAB +90.49.5,LAB +90.49.6,LAB +89.65.1,LAB +89.66,LAB +90.01.1,LAB +90.01.2,LAB +90.01.3,LAB +90.01.4,LAB +90.01.5,LAB +90.02.1,LAB +90.02.2,LAB +90.02.3,LAB +90.02.4,LAB +90.02.5,LAB +90.03.1,LAB +90.03.2,LAB +90.03.3,LAB +90.03.4,LAB +90.03.5,LAB +90.04.1,LAB +90.04.2,LAB +90.04.3,LAB +90.04.4,LAB +90.04.5,LAB +90.05.1,LAB +90.05.2,LAB +90.05.3,LAB +90.05.4,LAB +90.05.5,LAB +90.06.1,LAB +90.06.2,LAB +90.06.3,LAB +90.06.4,LAB +90.06.5,LAB +90.06.7,LAB +90.07.1,LAB +90.07.2,LAB +90.07.3,LAB +90.07.4,LAB +90.07.5,LAB +90.07.6,LAB +90.08.1,LAB +90.08.2,LAB +90.08.3,LAB +90.08.4,LAB +90.08.5,LAB +90.08.6,LAB +90.09.1,LAB +90.09.2,LAB +90.09.3,LAB +90.09.4,LAB +90.09.5,LAB +90.10.1,LAB +90.10.2,LAB +90.10.3,LAB +90.10.4,LAB +90.10.5,LAB +90.10.6,LAB +90.11.1,LAB +90.11.2,LAB +90.11.3,LAB +90.11.4,LAB +90.11.5,LAB +90.11.6,LAB +90.12.1,LAB +90.12.2,LAB +90.12.3,LAB +90.12.4,LAB +90.12.5,LAB +90.13.1,LAB +90.13.2,LAB +90.86.3,LAB +90.86.4,LAB +90.86.8,LAB +90.87.1,LAB +90.87.3,LAB +90.88.5,LAB +90.88.6,LAB +90.89.3,LAB +90.89.5,LAB +90.90.3,LAB +90.91.4,LAB +90.92.4,LAB +90.93.3,LAB +90.93.4,LAB +90.93.5,LAB +90.93.6,LAB +90.94.1,LAB +90.94.2,LAB +90.94.3,LAB +90.94.5,LAB +90.94.6,LAB +90.95.1,LAB +90.95.3,LAB +90.96.5,LAB +90.97.2,LAB +90.97.3,LAB +90.98.4,LAB +90.98.5,LAB +91.01.1,LAB +91.01.2,LAB +91.02.2,LAB +91.02.4,LAB +91.03.5,LAB +91.04.1,LAB +91.04.5,LAB +91.05.2,LAB +91.05.6,LAB +91.05.7,LAB +91.05.8,LAB +91.05.9,LAB +91.06.7,LAB +91.06.8,LAB +91.08.1,LAB +91.08.4,LAB +91.08.5,LAB +91.09.1,LAB +91.09.2,LAB +91.09.3,LAB +91.10.3,LAB +91.10.6,LAB +91.11.1,LAB +91.11.2,LAB +91.11.3,LAB +91.11.5,LAB +91.12.1,LAB +91.12.2,LAB +91.13.2,LAB +91.13.3,LAB +91.13.7,LAB +91.14.5,LAB +91.14.6,LAB +91.14.7,LAB +91.14.8,LAB +91.14.9,LAB +91.15.6,LAB +91.15.7,LAB +91.15.8,LAB +91.15.9,LAB +91.16.6,LAB +91.16.7,LAB +69.92.1,LAB +90.49.7,LAB +90.50.1,LAB +90.50.2,LAB +90.50.3,LAB +90.50.4,LAB +90.50.5,LAB +90.51.1,LAB +90.51.2,LAB +90.51.3,LAB +90.51.4,LAB +90.51.5,LAB +90.52.1,LAB +90.52.2,LAB +90.52.3,LAB +90.52.4,LAB +90.52.5,LAB +90.53.1,LAB +90.53.2,LAB +90.53.3,LAB +90.53.4,LAB +90.53.5,LAB +90.53.6,LAB +90.54.1,LAB +90.54.2,LAB +90.54.3,LAB +90.54.4,LAB +90.54.5,LAB +90.55.1,LAB +90.55.2,LAB +90.55.3,LAB +90.55.4,LAB +90.55.5,LAB +90.56.1,LAB +90.56.2,LAB +90.56.3,LAB +90.56.4,LAB +90.56.5,LAB +90.57.1,LAB +90.57.2,LAB +90.57.3,LAB +90.57.4,LAB +90.57.5,LAB +90.57.6,LAB +90.58.1,LAB +90.58.2,LAB +90.58.3,LAB +90.58.4,LAB +90.58.5,LAB +90.59.1,LAB +90.59.2,LAB +90.59.3,LAB +90.59.4,LAB +90.60.1,LAB +90.60.2,LAB +90.60.3,LAB +90.60.4,LAB +90.60.5,LAB +90.61.1,LAB +90.61.2,LAB +90.61.3,LAB +90.61.4,LAB +90.61.5,LAB +90.62.1,LAB +90.62.2,LAB +90.62.3,LAB +90.62.4,LAB +90.62.5,LAB +90.63.1,LAB +90.63.2,LAB +90.63.3,LAB +90.63.4,LAB +90.63.5,LAB +90.64.1,LAB +90.64.2,LAB +90.64.3,LAB +90.64.4,LAB +90.64.5,LAB +90.65.1,LAB +90.65.2,LAB +90.65.3,LAB +90.65.4,LAB +90.66.1,LAB +90.66.2,LAB +90.66.3,LAB +90.66.4,LAB +90.66.5,LAB +90.67.1,LAB +90.67.2,LAB +90.67.3,LAB +90.67.4,LAB +90.67.5,LAB +90.67.6,LAB +90.68.1,LAB +90.13.3,LAB +90.13.4,LAB +90.13.5,LAB +90.14.1,LAB +90.14.2,LAB +90.14.3,LAB +90.14.4,LAB +90.14.5,LAB +90.15.1,LAB +90.15.2,LAB +90.15.3,LAB +90.15.4,LAB +90.15.5,LAB +90.15.6,LAB +90.16.1,LAB +90.16.2,LAB +90.16.3,LAB +90.16.4,LAB +90.16.5,LAB +90.17.1,LAB +90.17.2,LAB +90.17.3,LAB +90.17.4,LAB +90.17.5,LAB +90.17.6,LAB +90.18.1,LAB +90.18.2,LAB +90.18.3,LAB +90.18.4,LAB +90.18.5,LAB +90.18.6,LAB +90.18.7,LAB +90.18.8,LAB +90.19.1,LAB +90.19.2,LAB +90.19.3,LAB +90.19.4,LAB +90.19.5,LAB +90.20.1,LAB +90.20.2,LAB +90.20.3,LAB +90.20.4,LAB +90.20.5,LAB +90.21.1,LAB +90.21.2,LAB +90.21.3,LAB +90.21.4,LAB +90.21.5,LAB +90.21.6,LAB +90.21.7,LAB +90.22.1,LAB +90.22.2,LAB +90.22.3,LAB +90.22.4,LAB +90.22.5,LAB +90.23.1,LAB +90.23.2,LAB +90.23.3,LAB +90.23.4,LAB +90.23.5,LAB +90.24.1,LAB +90.24.2,LAB +90.24.3,LAB +90.24.4,LAB +90.24.5,LAB +90.25.1,LAB +90.25.2,LAB +90.25.3,LAB +90.25.4,LAB +90.25.5,LAB +90.26.1,LAB +90.26.2,LAB +90.26.3,LAB +90.26.4,LAB +90.27.1,LAB +90.27.2,LAB +90.27.3,LAB +90.27.4,LAB +90.27.5,LAB +90.28.1,LAB +90.28.2,LAB +90.28.3,LAB +90.28.4,LAB +90.28.5,LAB +90.29.1,LAB +90.29.2,LAB +90.29.3,LAB +90.29.4,LAB +90.29.5,LAB +90.29.6,LAB +90.30.1,LAB +90.30.2,LAB +90.30.3,LAB +90.30.4,LAB +90.30.5,LAB +90.31.1,LAB +90.31.2,LAB +90.31.3,LAB +90.31.4,LAB +90.31.5,LAB +90.32.1,LAB +90.32.2,LAB +90.32.3,LAB +90.32.4,LAB +90.32.5,LAB +90.33.1,LAB +90.33.2,LAB +90.33.3,LAB +90.33.4,LAB +91.16.8,LAB +91.16.9,LAB +91.17.1,LAB +91.17.2,LAB +91.17.3,LAB +91.17.4,LAB +91.17.5,LAB +91.18.1,LAB +91.18.2,LAB +91.18.3,LAB +91.19.2,LAB +91.19.3,LAB +91.19.4,LAB +91.19.5,LAB +91.20.1,LAB +91.20.2,LAB +91.20.3,LAB +91.20.4,LAB +91.20.5,LAB +91.21.3,LAB +91.21.4,LAB +91.22.1,LAB +91.22.2,LAB +91.22.3,LAB +91.22.4,LAB +91.22.5,LAB +91.22.6,LAB +91.23.1,LAB +91.23.2,LAB +91.23.3,LAB +91.23.4,LAB +91.23.5,LAB +91.24.1,LAB +91.24.2,LAB +91.26.3,LAB +91.27.5,LAB +91.27.6,LAB +91.27.7,LAB +91.28.1,LAB +91.28.2,LAB +91.28.3,LAB +91.28.4,LAB +91.28.5,LAB +91.29.1,LAB +91.29.2,LAB +91.29.3,LAB +90.68.2,LAB +90.68.3,LAB +90.68.4,LAB +90.68.5,LAB +90.68.6,LAB +90.68.7,LAB +90.68.8,LAB +90.69.1,LAB +90.69.2,LAB +90.69.3,LAB +90.69.4,LAB +90.69.5,LAB +90.70.1,LAB +90.70.2,LAB +90.70.4,LAB +90.70.5,LAB +90.71.1,LAB +90.71.2,LAB +90.71.3,LAB +90.71.4,LAB +90.71.5,LAB +90.72.1,LAB +90.72.2,LAB +90.72.3,LAB +90.72.4,LAB +90.72.5,LAB +90.73.1,LAB +90.73.2,LAB +90.73.3,LAB +90.73.4,LAB +90.73.5,LAB +90.74.1,LAB +90.74.2,LAB +90.74.3,LAB +90.74.4,LAB +90.74.5,LAB +90.75.1,LAB +90.75.2,LAB +90.75.3,LAB +90.75.4,LAB +90.75.5,LAB +90.76.1,LAB +90.76.2,LAB +90.76.3,LAB +90.76.4,LAB +90.76.5,LAB +90.76.6,LAB +90.77.1,LAB +90.77.2,LAB +90.77.3,LAB +90.77.4,LAB +90.77.5,LAB +90.78.2,LAB +90.78.3,LAB +90.78.4,LAB +90.78.5,LAB +90.78.6,LAB +90.79.1,LAB +90.79.2,LAB +90.79.3,LAB +90.79.4,LAB +90.79.5,LAB +90.80.1,LAB +90.80.2,LAB +90.80.3,LAB +90.80.4,LAB +90.80.5,LAB +90.33.5,LAB +90.33.6,LAB +90.34.1,LAB +90.34.2,LAB +90.34.3,LAB +90.34.4,LAB +90.34.5,LAB +90.35.1,LAB +90.35.2,LAB +90.35.3,LAB +90.35.4,LAB +90.35.5,LAB +90.36.1,LAB +90.36.2,LAB +90.36.3,LAB +90.36.4,LAB +90.36.5,LAB +90.36.6,LAB +90.37.1,LAB +90.37.2,LAB +90.37.3,LAB +90.37.4,LAB +90.37.5,LAB +90.38.1,LAB +90.38.2,LAB +90.38.3,LAB +90.38.4,LAB +90.38.5,LAB +90.39.1,LAB +90.39.2,LAB +90.39.3,LAB +90.39.4,LAB +90.39.5,LAB +90.40.1,LAB +90.40.2,LAB +90.40.3,LAB +90.40.4,LAB +90.40.5,LAB +90.40.6,LAB +90.40.7,LAB +90.41.1,LAB +90.41.2,LAB +90.41.3,LAB +90.41.4,LAB +90.41.5,LAB +90.41.6,LAB +90.42.1,LAB +90.42.2,LAB +90.42.3,LAB +90.42.4,LAB +90.42.5,LAB +90.42.6,LAB +90.43.1,LAB +90.43.2,LAB +90.43.3,LAB +90.43.4,LAB +90.43.5,LAB +90.43.6,LAB +90.44.1,LAB +90.44.2,LAB +90.44.3,LAB +90.44.4,LAB +90.44.5,LAB +90.45.1,LAB +90.45.2,LAB +90.45.3,LAB +90.45.4,LAB +90.45.5,LAB +90.46.3,LAB +90.46.4,LAB +90.46.5,LAB +90.47.1,LAB +90.47.2,LAB +90.47.3,LAB +90.81.1,LAB +90.81.2,LAB +90.81.3,LAB +90.81.4,LAB +90.81.5,LAB +90.82.1,LAB +90.82.2,LAB +90.82.3,LAB +90.82.4,LAB +90.82.5,LAB +90.83.1,LAB +90.83.2,LAB +90.83.4,LAB +90.83.5,LAB +90.84.1,LAB +90.84.3,LAB +90.85.2,LAB +90.85.4,LAB +90.85.5,LAB +90.85.6,LAB +90.85.7,LAB +90.85.8,LAB +90.86.2,LAB +91.29.4,LAB +91.29.5,LAB +91.30.1,LAB +91.30.2,LAB +91.30.3,LAB +91.30.4,LAB +91.30.5,LAB +91.31.1,LAB +91.31.2,LAB +91.31.3,LAB +91.31.4,LAB +91.31.5,LAB +91.32.1,LAB +91.32.2,LAB +91.32.3,LAB +91.32.4,LAB +91.32.5,LAB +91.33.1,LAB +91.33.2,LAB +91.33.3,LAB +91.33.4,LAB +91.33.5,LAB +91.34.1,LAB +91.34.2,LAB +91.34.3,LAB +91.34.4,LAB +91.34.5,LAB +91.35.1,LAB +91.35.2,LAB +91.35.3,LAB +91.35.4,LAB +91.35.5,LAB +91.36.1,LAB +91.36.2,LAB +91.36.3,LAB +91.36.4,LAB +91.36.5,LAB +91.37.1,LAB +91.37.2,LAB +91.37.3,LAB +91.37.4,LAB +91.37.5,LAB +91.38.1,LAB +91.38.2,LAB +91.38.3,LAB +91.38.4,LAB +91.38.5,LAB +91.39.1,LAB +91.39.2,LAB +91.39.3,LAB +91.39.4,LAB +91.39.5,LAB +91.40.1,LAB +91.40.2,LAB +91.40.3,LAB +91.40.4,LAB +91.40.5,LAB +91.41.1,LAB +91.41.2,LAB +91.41.3,LAB +91.41.4,LAB +91.41.5,LAB +91.42.1,LAB +91.42.2,LAB +91.42.3,LAB +91.42.4,LAB +91.42.5,LAB +91.43.1,LAB +91.43.2,LAB +91.43.3,LAB +91.43.4,LAB +91.43.5,LAB +91.44.1,LAB +91.44.2,LAB +91.44.3,LAB +91.44.4,LAB +91.44.5,LAB +91.45.1,LAB +91.45.2,LAB +91.45.3,LAB +91.45.4,LAB +91.45.5,LAB +91.46.1,LAB +91.46.2,LAB +91.46.3,LAB +91.46.4,LAB +91.46.5,LAB +91.47.1,LAB +91.47.2,LAB +91.47.3,LAB +91.47.4,LAB +91.47.5,LAB +91.48.1,LAB +91.48.2,LAB +91.48.3,LAB +91.48.4,LAB +91.48.5,LAB +91.49.1,LAB +91.49.2,LAB +91.49.3,LAB +91.50.1,LAB +91.50.2,LAB +91.50.3,LAB +91.50.4,LAB +91.50.5,LAB +91.50.6,LAB +91.50.7,LAB +91.50.8,LAB +91.50.9,LAB +91.51.1,LAB +91.51.2,LAB +91.51.3,LAB +91.51.4,LAB +91.51.5,LAB +91.51.6,LAB +91.51.7,LAB +91.51.8,LAB +91.51.9,LAB +91.52.1,LAB +91.52.2,LAB +91.52.3,LAB +91.52.4,LAB +91.52.5,LAB +91.52.6,LAB +91.52.7,LAB +91.52.8,LAB +91.52.9,LAB +91.53.1,LAB +91.53.2,LAB +91.53.3,LAB +91.53.4,LAB +91.53.5,LAB +91.53.6,LAB +91.53.7,LAB +91.53.8,LAB +91.53.9,LAB +91.54.1,LAB +91.54.2,LAB +91.54.3,LAB +91.54.4,LAB +91.54.5,LAB +99.88,LAB +89.15.2,INSTR +89.15.3,INSTR +89.15.4,INSTR +89.15.5,INSTR +89.15.6,INSTR +89.15.7,INSTR +89.15.8,INSTR +89.15.9,INSTR +89.17,INSTR +89.18.1,INSTR +89.18.2,INSTR +89.19.1,INSTR +89.19.2,INSTR +89.22,INSTR +89.24,INSTR +89.25,INSTR +89.32,INSTR +89.32.1,INSTR +89.37.1,INSTR +89.37.2,INSTR +89.37.3,INSTR +89.37.4,INSTR +89.37.5,INSTR +89.37.6,INSTR +89.38.1,INSTR +89.38.2,INSTR +89.38.3,INSTR +89.38.4,INSTR +89.38.5,INSTR +89.38.6,INSTR +89.38.7,INSTR +45.24.1,INSTR +45.25,INSTR +45.25.1,INSTR +45.29.4,INSTR +45.42,INSTR +45.42.1,INSTR +45.43.1,INSTR +46.85,INSTR +48.23,INSTR +48.24,INSTR +48.29.1,INSTR +48.35,INSTR +43.41.1,INSTR +43.41.2,INSTR +44.19.1,INSTR +45.13,INSTR +45.16,INSTR +45.23,INSTR +45.23.1,INSTR +45.23.2,INSTR +45.23.3,INSTR +45.24,INSTR +89.38.8,INSTR +89.38.9,INSTR +89.39.5,INSTR +89.41,INSTR +89.42,INSTR +89.43,INSTR +89.44,INSTR +89.44.1,INSTR +89.44.2,INSTR +89.48.1,INSTR +89.5,INSTR +89.52,INSTR +89.54,INSTR +89.59.1,INSTR +89.61.1,INSTR +89.65.2,INSTR +89.65.3,INSTR +89.65.4,INSTR +89.65.5,INSTR +89.65.6,INSTR +75.34.1,INSTR +68.12.1,INSTR +31.42,INSTR +31.42.1,INSTR +31.42.2,INSTR +31.43,INSTR +31.48.1,INSTR +31.48.2,INSTR +33.22,INSTR +33.24,INSTR +49.21,INSTR +49.31,INSTR +56.31,INSTR +57.32,INSTR +57.33,INSTR +57.39.1,INSTR +57.39.2,INSTR +58.22,INSTR +64.19.1,INSTR +88.72.1,INSTR +88.72.2,INSTR +88.72.3,INSTR +88.72.4,INSTR +88.72.5,INSTR +88.79.4,INSTR +89.11,INSTR +89.12,INSTR +89.14,INSTR +89.14.1,INSTR +89.14.2,INSTR +89.14.3,INSTR +89.14.4,INSTR +89.14.5,INSTR +89.15.1,INSTR +98.03,INSTR +98.05,INSTR +98.15,INSTR +98.18,INSTR +20.31,INSTR +20.39.1,INSTR +95.13.2,INSTR +95.14,INSTR +95.15,INSTR +95.17,INSTR +95.2,INSTR +95.21,INSTR +95.22,INSTR +95.23,INSTR +95.23.1,INSTR +95.24.1,INSTR +95.24.2,INSTR +95.25,INSTR +95.26,INSTR +95.35,INSTR +95.41.1,INSTR +95.41.2,INSTR +95.41.3,INSTR +95.41.4,INSTR +95.42,INSTR +95.43,INSTR +95.44.1,INSTR +95.44.2,INSTR +95.45,INSTR +95.46,INSTR +95.47,INSTR +95.48.1,INSTR +95.48.2,INSTR +95.48.3,INSTR +95.48.4,INSTR +95.49,INSTR +9.19,INSTR +95.03.1,INSTR +95.05,INSTR +95.06,INSTR +95.07,INSTR +95.07.1,INSTR +95.09.1,INSTR +95.09.2,INSTR +95.09.3,INSTR +95.11,INSTR +95.11.1,INSTR +95.12,INSTR +95.12.1,INSTR +95.13,INSTR +95.13.1,INSTR +93.02,INSTR +93.08.1,INSTR +93.08.2,INSTR +93.08.3,INSTR +93.08.4,INSTR +93.08.5,INSTR +93.08.6,INSTR +93.08.7,INSTR +93.08.8,INSTR +93.09.1,INSTR +93.09.2,INSTR +42.29.2,INSTR +42.33.2,INSTR +92.27.5,PROC +92.28.1,PROC +92.28.2,PROC +92.28.3,PROC +92.28.4,PROC +92.28.5,PROC +92.28.6,PROC +92.29.1,PROC +92.29.2,PROC +92.29.3,PROC +92.29.4,PROC +92.29.5,PROC +92.29.6,PROC +92.29.7,PROC +92.29.8,PROC +99.79.2,PROC +99.85,PROC +99.91,PROC +99.94,PROC +99.95,PROC +99.97.1,PROC +99.97.2,PROC +24.70.1,PROC +97.82,PROC +98.01,PROC +98.11,PROC +98.12,PROC +98.13,PROC +98.14,PROC +98.16,PROC +98.17,PROC +98.19,PROC +98.2,PROC +98.21,PROC +98.22,PROC +98.23,PROC +98.24,PROC +98.25,PROC +98.26,PROC +98.27,PROC +98.28,PROC +98.29,PROC +98.5,PROC +99.06.1,PROC +99.07.1,PROC +99.14.1,PROC +99.23,PROC +99.24.1,PROC +99.24.2,PROC +99.25,PROC +99.29.1,PROC +99.29.2,PROC +99.29.3,PROC +99.29.4,PROC +99.29.5,PROC +99.29.6,PROC +99.29.8,PROC +99.29.9,PROC +99.71,PROC +99.72,PROC +99.73,PROC +99.73.1,PROC +99.74,PROC +99.79.1,PROC +92.11.3,PROC +92.11.4,PROC +92.21.1,PROC +92.23.1,PROC +92.23.2,PROC +92.23.3,PROC +92.24.1,PROC +92.24.2,PROC +92.24.3,PROC +92.24.4,PROC +92.24.5,PROC +92.24.6,PROC +92.25.1,PROC +92.25.2,PROC +92.27.1,PROC +92.27.2,PROC +92.27.3,PROC +92.27.4,PROC +15,PROC +15.1,PROC +15.2,PROC +15.3,PROC +15.4,PROC +15.5,PROC +15.6,PROC +15.7,PROC +15.9,PROC +16.22,PROC +16.91,PROC +18.02,PROC +18.12,PROC +18.21,PROC +18.29,PROC +18.31,PROC +20,PROC +20.32.1,PROC +20.8,PROC +21.01,PROC +21.02,PROC +21.03,PROC +21.22,PROC +21.31,PROC +21.71,PROC +21.88,PROC +21.91,PROC +22.01,PROC +22.71,PROC +23.01,PROC +23.09,PROC +23.11,PROC +23.19,PROC +23.2,PROC +23.20.1,PROC +23.20.2,PROC +23.20.3,PROC +23.3,PROC +23.41,PROC +23.41.1,PROC +23.41.2,PROC +23.41.3,PROC +23.41.4,PROC +23.42,PROC +23.43.1,PROC +23.43.2,PROC +23.43.3,PROC +23.49.1,PROC +23.5,PROC +23.6,PROC +23.71.1,PROC +23.71.2,PROC +23.73,PROC +24.00.1,PROC +24.11,PROC +24.12,PROC +24.19.1,PROC +24.20.1,PROC +24.31,PROC +24.39.1,PROC +24.39.2,PROC +24.4,PROC +96.17,PROC +96.18,PROC +96.22,PROC +96.26,PROC +96.27,PROC +96.49,PROC +96.51,PROC +96.52,PROC +96.54.1,PROC +96.54.2,PROC +96.54.3,PROC +96.57,PROC +96.59,PROC +97.29.1,PROC +97.35,PROC +97.71,PROC +13.1,PROC +13.64,PROC +13.7,PROC +13.71,PROC +13.72,PROC +13.72.1,PROC +14.22,PROC +14.24.1,PROC +14.24.2,PROC +14.24.3,PROC +14.29.1,PROC +14.31,PROC +14.32,PROC +14.33,PROC +14.34,PROC +14.4,PROC +14.59.1,PROC +14.79.1,PROC +8.82,PROC +8.83,PROC +8.84,PROC +8.91,PROC +8.92,PROC +08.99.1,PROC +9,PROC +9.11,PROC +9.12,PROC +9.21,PROC +9.41,PROC +9.42,PROC +9.43,PROC +9.51,PROC +9.52,PROC +9.53,PROC +9.59,PROC +12.64.1,PROC +12.64.2,PROC +12.66,PROC +12.69,PROC +12.7,PROC +12.89.1,PROC +12.89.2,PROC +12.91,PROC +86.30.3,PROC +86.30.4,PROC +86.4,PROC +86.59.1,PROC +86.59.2,PROC +86.59.3,PROC +86.6,PROC +86.61,PROC +86.62,PROC +86.71,PROC +86.72,PROC +86.73,PROC +86.74,PROC +86.75,PROC +86.81,PROC +86.84,PROC +93.56.3,PROC +93.56.4,PROC +93.56.5,PROC +93.56.6,PROC +93.56.7,PROC +93.57.1,PROC +93.91,PROC +93.95,PROC +93.54.2,PROC +93.54.3,PROC +93.54.4,PROC +93.54.5,PROC +93.54.6,PROC +93.54.7,PROC +93.54.8,PROC +93.56.1,PROC +93.56.2,PROC +10.33,PROC +10.4,PROC +10.6,PROC +10.91,PROC +11.31,PROC +11.32,PROC +11.39,PROC +11.42,PROC +11.43,PROC +11.6,PROC +11.62.1,PROC +11.62.2,PROC +11.75.1,PROC +11.91,PROC +11.99.1,PROC +11.99.2,PROC +11.99.3,PROC +11.99.4,PROC +11.99.5,PROC +12.14,PROC +12.4,PROC +12.41,PROC +12.5,PROC +12.59,PROC +3.8,PROC +3.91,PROC +3.92,PROC +04.07.1,PROC +04.11.1,PROC +4.43,PROC +4.44,PROC +04.81.1,PROC +04.81.2,PROC +5.31,PROC +5.32,PROC +6.01,PROC +06.11.1,PROC +06.11.2,PROC +6.13,PROC +8.01,PROC +8.02,PROC +8.09,PROC +8.11,PROC +8.21,PROC +8.22,PROC +8.23,PROC +8.24,PROC +8.25,PROC +8.41,PROC +8.42,PROC +8.43,PROC +8.44,PROC +8.52,PROC +8.6,PROC +8.81,PROC +79.03,PROC +79.04,PROC +79.07,PROC +79.08,PROC +79.7,PROC +79.71,PROC +79.72,PROC +79.73,PROC +79.74,PROC +80.3,PROC +81.91,PROC +81.92,PROC +82.91,PROC +83.02,PROC +83.03,PROC +83.09,PROC +83.21,PROC +83.21.1,PROC +83.31,PROC +83.98,PROC +85,PROC +85.11,PROC +85.11.1,PROC +85.2,PROC +85.21,PROC +85.21.1,PROC +85.53,PROC +85.94,PROC +86.01,PROC +86.02.1,PROC +86.02.2,PROC +86.03,PROC +86.04,PROC +86.05.1,PROC +86.11,PROC +86.22,PROC +86.23,PROC +86.24,PROC +86.25,PROC +86.27,PROC +86.28,PROC +86.30.1,PROC +86.30.2,PROC +9.6,PROC +9.71,PROC +9.73,PROC +10.21,PROC +10.31,PROC +10.32,PROC +93.51,PROC +93.52,PROC +93.53,PROC +93.54.1,PROC +41.31,PROC +42.29.1,PROC +89.62,PROC +69.92.2,PROC +69.92.3,PROC +69.92.4,PROC +70.11.1,PROC +70.21,PROC +70.24,PROC +70.29.1,PROC +70.33.1,PROC +71.11,PROC +71.22,PROC +71.30.1,PROC +71.90.1,PROC +75.10.1,PROC +75.10.2,PROC +75.10.3,PROC +75.33.1,PROC +75.8,PROC +76.01,PROC +76.2,PROC +76.77,PROC +76.92.1,PROC +76.93,PROC +76.96,PROC +77.56,PROC +78.7,PROC +79,PROC +79.01,PROC +79.02,PROC +68.16.1,PROC +68.2,PROC +68.29.1,PROC +69.09,PROC +69.7,PROC +69.92,PROC +24.70.3,PROC +24.70.4,PROC +24.80.1,PROC +25.01,PROC +25.91,PROC +25.92,PROC +26,PROC +26.11,PROC +26.91,PROC +27.21,PROC +27.23,PROC +27.24,PROC +27.41,PROC +27.49.1,PROC +27.51,PROC +27.52,PROC +27.71,PROC +27.91,PROC +28.00.1,PROC +29.12,PROC +34.24,PROC +34.91,PROC +34.91.1,PROC +34.92,PROC +38.59.1,PROC +38.89,PROC +38.93,PROC +38.94,PROC +38.95,PROC +38.98,PROC +38.99.1,PROC +38.99.2,PROC +39.27.1,PROC +39.4,PROC +39.43,PROC +39.92,PROC +39.95.1,PROC +39.95.2,PROC +39.95.3,PROC +39.95.4,PROC +39.95.5,PROC +39.95.6,PROC +39.95.7,PROC +39.95.8,PROC +39.95.9,PROC +39.99.1,PROC +40.11,PROC +40.19.1,PROC +40.19.2,PROC +49.11,PROC +49.23,PROC +49.39,PROC +49.42,PROC +49.45,PROC +49.46,PROC +49.47,PROC +49.59,PROC +50.11,PROC +50.19.1,PROC +50.91,PROC +51.12,PROC +54.21,PROC +54.22,PROC +54.24,PROC +54.24.1,PROC +54.91,PROC +54.91.1,PROC +54.93,PROC +54.97,PROC +54.98.1,PROC +54.98.2,PROC +55.92,PROC +57.17,PROC +57.49.1,PROC +57.94,PROC +58.23,PROC +58.31,PROC +58.47,PROC +58.5,PROC +58.60.1,PROC +58.60.2,PROC +58.60.3,PROC +59.8,PROC +60,PROC +60.11,PROC +60.11.1,PROC +60.13,PROC +60.91,PROC +61,PROC +61.91,PROC +62.11,PROC +63.52,PROC +63.71,PROC +64,PROC +64.11,PROC +64.2,PROC +64.92.1,PROC +64.93,PROC +65.91,PROC +66.8,PROC +67.12,PROC +67.19.1,PROC +67.32,PROC +67.33,PROC +88.73.6,PROC +88.73.7,PROC +24.70.2,PROC +89.23,PROC +49.01,PROC +49.02,PROC diff --git a/src/org/ohdsi/whiteRabbit/etls/ars/specialty_italian.csv b/src/org/ohdsi/whiteRabbit/etls/ars/specialty_italian.csv new file mode 100644 index 00000000..7663abf4 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/etls/ars/specialty_italian.csv @@ -0,0 +1,56 @@ +COD,DESCRIZIONE,CONCEPT_CODE,CONCEPT_ID,CONCEPT_NAME +001,Allergologia,3,38004448,Allergy/Immunology +003,Anatomia ed istologia patologica,246RM2200X,38004144,"Technologists, Technicians & Other Technical Service Providers, Technician, Pathology, Medical Laboratory" +006,Cardiochirurgia pediatrica,78,38004497,Cardiac Surgery +007,Cardiochirurgia,78,38004497,Cardiac Surgery +008,Cardiologia,6,38004451,Cardiology +009,Chirurgia generale,2,38004447,General Surgery +010,Chirurgia maxillo facciale,85,38004504,Maxillofacial Surgery +012,Chirurgia plastica,24,38004467,Plastic And Reconstructive Surgery +013,Chirurgia toracica,33,38004473,Thoracic Surgery +014,Chirurgia vascolare,77,38004496,Vascular Surgery +018,Ematologia,246QH0000X,38004134,"Technologists, Technicians & Other Technical Service Providers, Spec/Tech, Pathology, Hematology" +020,Immunologia,3,38004448,Allergy/Immunology +021,Geriatria,38,38004478,Geriatric Medicine +024,Malattie infettive e tropicali,44,38004484,Infectious Disease +025,Medicina del lavoro,67,38004492,Occupational Therapy +026,Medicina generale,1,38004446,General Practice +027,Medicina legale,173000000X,38003790,"Other Service Providers, Legal Medicine" +029,Nefrologia,39,38004479,Nephrology +030,Neurochirurgia,14,38004459,Neurosurgery +032,Neurologia,13,38004458,Neurology +033,Neuropsichiatria infantile,86,38004505,Neuropsychiatry +034,Oculistica,18,38004463,Ophthalmology +035,Odontoiatria e stomatologia,1223G0001X,38003675,"Dental Providers, Dentist, General Practice" +036,Ortopedia e traumatologia,20,38004465,Orthopedic Surgery +037,Ostetricia e ginecologia,16,38004461,Obstetrics/Gynecology +038,Otorinolaringoiatria,4,38004449,Otolaryngology +039,Pediatria,37,38004477,Pediatric Medicine +040,Psichiatria,26,38004469,Psychiatry +043,Urologia,34,38004474,Urology +048,Nefrologia (abilitazione trapianto rene),39,38004479,Nephrology +049,Terapia intensiva,81,38004500,Critical care (intensivist) +052,Dermatologia,7,38004452,Dermatology +058,Gastroenterologia,10,38004455,Gastroenterology +061,Medicina nucleare,36,38004476,Nuclear Medicine +064,Oncologia,90,38004507,Medical Oncology +065,Oncologia pediatrica,90,38004507,Medical Oncology +066,Oncoematologia,83,38004502,Hematology/Oncology +068,Pneumologia,29,38004472,Pulmonary Disease +069,Radiologia,30,38004675, Physician/Diagnostic Radiology +070,Radioterapia,94,38004511,Interventional Radiology +071,Reumatologia,66,38004491,Rheumatology +074,Radioterapia oncologica,92,38004509,Radiation Oncology +076,Neurochirurgia pediatrica,14,38004459,Neurosurgery +078,Urologia pediatrica,39,38004479,Nephrology +502,Cardiologia pediatrica,6,38004451,Cardiology +503,Chirurgia ricostruttiva della mano,24,38004467,Plastic And Reconstructive Surgery +509,Genetica medica,170100000X,38003775,"Other Service Providers, Medical Genetics, Ph.D. Medical Genetics" +510,Genetica medica pediatrica,170100000X,38003775,"Other Service Providers, Medical Genetics, Ph.D. Medical Genetics" +513,Malattie infettive pediatriche,44,38004484,Infectious Disease +514,Neuroradiologia,30,38004675, Physician/Diagnostic Radiology +515,Psicologia,68,38004493,Clinical Psychology +521,Laboratorio di immunologia e allergologia,3,38004448,Allergy/Immunology +522,Medicina e chirurgia di accettazione e d'urgenza,93,38004510,Emergency Medicine +523,Microbiologia,246QM0900X,38004141,"Technologists, Technicians & Other Technical Service Providers, Spec/Tech, Pathology, Microbiology" +526,Anestesia,5,38004450,Anesthesiology \ No newline at end of file diff --git a/src/org/ohdsi/whiteRabbit/etls/hcup/HCUPETL.java b/src/org/ohdsi/whiteRabbit/etls/hcup/HCUPETL.java new file mode 100644 index 00000000..9cae0aa4 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/etls/hcup/HCUPETL.java @@ -0,0 +1,455 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.etls.hcup; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.ohdsi.databases.DbType; +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.collections.OneToManyList; +import org.ohdsi.utilities.files.ReadCSVFileWithHeader; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.whiteRabbit.DbSettings; +import org.ohdsi.whiteRabbit.EtlReport; +import org.ohdsi.whiteRabbit.cdm.CDMV4NullableChecker; +import org.ohdsi.whiteRabbit.cdm.CdmV4; +import org.ohdsi.whiteRabbit.utilities.CodeToConceptMap; +import org.ohdsi.whiteRabbit.utilities.ETLUtils; +import org.ohdsi.whiteRabbit.utilities.QCSampleConstructor; + +public class HCUPETL { + + public static int BATCH_SIZE = 10000; + public static String[] diagnoseFields = new String[] { "DX1", "DX2", "DX3", "DX4", "DX5", "DX6", "DX7", "DX8", "DX9", "DX10", + "DX11", "DX12", "DX13", "DX14", "DX15", "DX16", "DX17", "DX18", "DX19", "DX20", "DX21", "DX22", "DX23", "DX24", "DX25", "ECODE1", "ECODE2" }; + public static String[] procedureFields = new String[] { "PR1", "PR2", "PR3", "PR4", "PR5", "PR6", "PR7", "PR8", "PR9", "PR10", + "PR11", "PR12", "PR13", "PR14", "PR15" }; + public static String[] procedureDayFields = new String[] { "PRDAY1", "PRDAY2", "PRDAY3", "PRDAY4", "PRDAY5", "PRDAY6", "PRDAY7", + "PRDAY8", "PRDAY9", "PRDAY10", "PRDAY11", "PRDAY12", "PRDAY13", "PRDAY14", "PRDAY15" }; + public static int[] diagnoseFieldConceptIds = new int[] { 38000184, 38000185, 38000186, 38000187, 38000188, 38000189, 38000190, + 38000191, 38000192, 38000193, 38000194, 38000195, 38000196, 38000197, 38000198, 38000198, 380001980, 38000198, 38000198, 38000198, 38000198, + 38000198, 38000198, 38000198, 38000198, 38000184, 38000185 }; + + public static int[] procedureFieldConceptIds = new int[] { 38000251, 38000252, 38000253, 38000254, 38000255, 38000256, 38000257, + 38000258, 38000259, 38000260, 38000261, 38000262, 38000263, 38000264, 38000265 }; + + private RichConnection sourceConnection; + private RichConnection targetConnection; + private QCSampleConstructor qcSampleConstructor; + private EtlReport etlReport; + private CDMV4NullableChecker cdmv4NullableChecker = new CDMV4NullableChecker(); + private OneToManyList tableToRows; + private long personCount; + private long observationPeriodId; + private Integer locationId; + private long drugExposureId; + private long conditionOccurrenceId; + private long visitOccurrenceId; + private long procedureOccurrenceId; + private long procedureCostId; + private long visitStartDate; + private long visitEndDate; + private long primaryProcedureOccurrenceId; + + private Map stateCountyToLocationId; + private Set careSiteIds; + + private Map codeToCounty; + private CodeToConceptMap icd9ToConcept; + private CodeToConceptMap icd9ToRxNorm; + private CodeToConceptMap icd9ProcToConcept; + private CodeToConceptMap drgToConcept; + + public void process(String folder, DbSettings sourceDbSettings, DbSettings targetDbSettings, int maxPersons) { + // Hardcode vocab server for now: + DbSettings vocabDbSettings = new DbSettings(); + vocabDbSettings.database = "vocabulary"; + vocabDbSettings.dataType = DbSettings.DATABASE; + vocabDbSettings.server = "127.0.0.1"; + vocabDbSettings.dbType = DbType.MYSQL; + vocabDbSettings.user = "root"; + vocabDbSettings.password = "F1r3starter"; + + if (ETLUtils.databaseAlreadyExists(targetDbSettings)) + return; + CdmV4.createStructure(targetDbSettings); + + sourceConnection = new RichConnection(sourceDbSettings.server, sourceDbSettings.domain, sourceDbSettings.user, sourceDbSettings.password, + sourceDbSettings.dbType); + sourceConnection.setContext(this.getClass()); + sourceConnection.use(sourceDbSettings.database); + + targetConnection = new RichConnection(targetDbSettings.server, targetDbSettings.domain, targetDbSettings.user, targetDbSettings.password, + targetDbSettings.dbType); + targetConnection.setContext(this.getClass()); + targetConnection.use(targetDbSettings.database); + + loadMappings(vocabDbSettings); + + QCSampleConstructor.sampleProbability = 0.000001; + qcSampleConstructor = new QCSampleConstructor(folder + "/sample"); + tableToRows = new OneToManyList(); + etlReport = new EtlReport(folder); + stateCountyToLocationId = new HashMap(); + careSiteIds = new HashSet(); + personCount = 0; + drugExposureId = 0; + conditionOccurrenceId = 0; + visitOccurrenceId = 0; + procedureOccurrenceId = 0; + procedureCostId = 0; + observationPeriodId = 0; + + StringUtilities.outputWithTime("Processing persons"); + for (Row row : sourceConnection.query("SELECT * FROM core")) { + processPerson(row); + if (personCount == maxPersons) { + System.out.println("Reached limit of " + maxPersons + " persons, terminating"); + break; + } + if (personCount % BATCH_SIZE == 0) { + insertBatch(); + System.out.println("Processed " + personCount + " persons"); + } + } + insertBatch(); + System.out.println("Processed " + personCount + " persons"); + CdmV4.createIndices(targetDbSettings); + qcSampleConstructor.addCdmData(targetDbSettings, vocabDbSettings); + String etlReportName = etlReport.generate(drgToConcept, icd9ProcToConcept, icd9ToConcept, icd9ToRxNorm); + System.out.println("An ETL report was generated and written to :" + etlReportName); + if (etlReport.getTotalProblemCount() > 0) { + String etlProblemListname = etlReport.generateProblemList(); + System.out.println("An ETL problem list was generated and written to :" + etlProblemListname); + } + StringUtilities.outputWithTime("Finished ETL"); + } + + private void processPerson(Row row) { + etlReport.registerIncomingData("core", row); + + personCount++; + visitOccurrenceId++; + observationPeriodId++; + primaryProcedureOccurrenceId = -1; + visitStartDate = computeVisitStartDate(row.get("YEAR"), row.get("AMONTH"), row.get("AWEEKEND")); + visitEndDate = computeVisitEndDate(visitStartDate, row.get("LOS")); + + qcSampleConstructor.registerPersonData("core", row, row.getLong("KEY")); + + addToLocation(row); + addToCareSite(row); + addToVisitOccurrence(row); + addToObservationPeriod(row); + addToPerson(row); + addToConditionOccurrence(row); + addToDeath(row); + addToDrugExposure(row); + addToProcedureOccurrence(row); + addToProcedureCost(row); + } + + private void addToLocation(Row row) { + String stateCounty = row.get("HOSPST") + "\t" + (row.get("HOSPSTCO").equals("-9999") ? "" : row.get("HOSPSTCO")); + locationId = stateCountyToLocationId.get(stateCounty); + if (locationId == null) { + locationId = stateCountyToLocationId.size() + 1; + stateCountyToLocationId.put(stateCounty, locationId); + + Row location = new Row(); + location.add("location_id", locationId); + location.add("state", row.get("HOSPST")); + String county = codeToCounty.get(row.get("HOSPSTCO")); + if (county == null) + county = ""; + if (county.length() > 20) + county = county.substring(0, 20); // County field in CDM limited to 20 chars + location.add("county", county); + location.add("location_source_value", row.get("HOSPSTCO")); + tableToRows.put("location", location); + } + } + + private void addToCareSite(Row row) { + if (careSiteIds.add(row.getInt("HOSPID"))) { + Row careSite = new Row(); + careSite.add("care_site_id", row.get("HOSPID")); + careSite.add("care_site_source_value", row.get("HOSPID")); + careSite.add("location_id", locationId); + tableToRows.put("care_site", careSite); + } + } + + private void addToVisitOccurrence(Row row) { + Row visitOccurrence = new Row(); + visitOccurrence.add("person_id", row.get("KEY")); + visitOccurrence.add("visit_occurrence_id", visitOccurrenceId); + visitOccurrence.add("visit_start_date", StringUtilities.daysToDatabaseDateString(visitStartDate)); + visitOccurrence.add("visit_end_date", StringUtilities.daysToDatabaseDateString(visitEndDate)); + visitOccurrence.add("care_site_id", row.get("HOSPID")); + visitOccurrence.add("place_of_service_concept_id", 9201); // Inpatient visit + tableToRows.put("visit_occurrence", visitOccurrence); + } + + private void addToObservationPeriod(Row row) { + Row observationPeriod = new Row(); + observationPeriod.add("observation_period_id", observationPeriodId); + observationPeriod.add("person_id", row.get("KEY")); + observationPeriod.add("observation_period_start_date", StringUtilities.daysToDatabaseDateString(visitStartDate)); + observationPeriod.add("observation_period_end_date", StringUtilities.daysToDatabaseDateString(visitEndDate)); + tableToRows.put("observation_period", observationPeriod); + } + + private void addToPerson(Row row) { + if (row.getInt("AGE") < 0 || (row.getInt("AGE") == 0 && row.getInt("AGEDAY") < 0)) { // No age specified. Cannot create person, since birth year is + // required field + etlReport.reportProblem("Person", "No age specified so cannot create row", row.get("KEY")); + return; + } + + Row person = new Row(); + person.add("person_id", row.get("KEY")); + person.add("person_source_value", row.get("KEY")); + person.add("gender_source_value", row.get("FEMALE")); + person.add("gender_concept_id", row.get("FEMALE").equals("1") ? "8532" : row.get("FEMALE").equals("0") ? "8507" : "8551"); + + if (row.getInt("AGE") > 0) { + int yearOfBirth = Integer.parseInt(StringUtilities.daysToCalendarYear(visitStartDate)) - row.getInt("AGE"); + person.add("year_of_birth", yearOfBirth); + person.add("month_of_birth", ""); + person.add("day_of_birth", ""); + + } else if (row.getInt("AGEDAY") >= 0) { + long dateOfBirth = visitStartDate - row.getInt("AGEDAY"); + person.add("year_of_birth", StringUtilities.daysToCalendarYear(dateOfBirth)); + person.add("month_of_birth", StringUtilities.daysToCalendarMonth(dateOfBirth)); + person.add("day_of_birth", StringUtilities.daysToCalendarDayOfMonth(dateOfBirth)); + } else { + person.add("year_of_birth", ""); + person.add("month_of_birth", ""); + person.add("day_of_birth", ""); + } + + person.add("race_source_value", row.get("RACE")); + if (row.get("RACE").equals("1")) // White + person.add("race_concept_id", "8527"); + else if (row.get("RACE").equals("2")) // Black + person.add("race_concept_id", "8516"); + else if (row.get("RACE").equals("4")) // Pacific islander + person.add("race_concept_id", "8557"); + else if (row.get("RACE").equals("5")) // Native American + person.add("race_concept_id", "8657"); + else if (row.get("RACE").equals("3")) // Hispanic, should be coded as 'other' + person.add("race_concept_id", "8522"); + else if (row.get("RACE").equals("6")) // Other + person.add("race_concept_id", "8522"); + else + person.add("race_concept_id", ""); + + if (row.get("RACE").equals("3")) {// Hispanic + person.add("ethnicity_source_value", "3"); + person.add("ethnicity_concept_id", "38003563"); + } else { + person.add("ethnicity_source_value", ""); + person.add("ethnicity_concept_id", ""); + } + + tableToRows.put("person", person); + } + + private void addToConditionOccurrence(Row row) { + for (int i = 0; i < diagnoseFields.length; i++) + if (row.get(diagnoseFields[i]).trim().length() != 0) { + Row conditionOccurrence = new Row(); + conditionOccurrence.add("person_id", row.get("KEY")); + conditionOccurrence.add("condition_occurrence_id", ++conditionOccurrenceId); + conditionOccurrence.add("condition_source_value", row.get(diagnoseFields[i])); + conditionOccurrence.add("condition_concept_id", icd9ToConcept.getConceptId(row.get(diagnoseFields[i]).trim())); + conditionOccurrence.add("condition_type_concept_id", diagnoseFieldConceptIds[i]); + conditionOccurrence.add("condition_start_date", StringUtilities.daysToDatabaseDateString(visitStartDate)); + conditionOccurrence.add("visit_occurrence_id", visitOccurrenceId); + tableToRows.put("condition_occurrence", conditionOccurrence); + } + } + + private void addToDeath(Row row) { + if (row.get("DIED").equals("1")) { + Row death = new Row(); + death.add("person_id", row.get("KEY")); + death.add("death_date", StringUtilities.daysToDatabaseDateString(visitEndDate)); + death.add("death_type_concept_id", 38003566); // EHR record patient status "Deceased" + tableToRows.put("death", death); + } + } + + private void addToDrugExposure(Row row) { + for (int i = 0; i < procedureFields.length; i++) + if (row.get(procedureFields[i]).trim().length() != 0) { + int conceptId = icd9ToRxNorm.getConceptId(row.get(procedureFields[i]).trim()); + if (conceptId != 0) { + Row drugExposure = new Row(); + drugExposure.add("drug_exposure_id", ++drugExposureId); + drugExposure.add("person_id", row.get("KEY")); + int day = row.getInt(procedureDayFields[i]); + if (day < 0) + day = 0; + drugExposure.add("drug_exposure_start_date", StringUtilities.daysToDatabaseDateString(visitStartDate + day)); + drugExposure.add("drug_source_value", row.get(procedureFields[i])); + drugExposure.add("drug_concept_id", conceptId); + drugExposure.add("drug_type_concept_id", 38000179); // Physician administered drug (identified as procedure) + drugExposure.add("visit_occurrence_id", visitOccurrenceId); + tableToRows.put("drug_exposure", drugExposure); + } + } + } + + private void addToProcedureOccurrence(Row row) { + for (int i = 0; i < procedureFields.length; i++) + if (row.get(procedureFields[i]).trim().length() != 0) { + Row procedureOccurrence = new Row(); + procedureOccurrence.add("procedure_occurrence_id", ++procedureOccurrenceId); + procedureOccurrence.add("person_id", row.get("KEY")); + int day = row.getInt(procedureDayFields[i]); + if (day < 0) + day = 0; + procedureOccurrence.add("procedure_date", StringUtilities.daysToDatabaseDateString(visitStartDate + day)); + procedureOccurrence.add("procedure_source_value", row.get(procedureFields[i])); + procedureOccurrence.add("procedure_concept_id", icd9ProcToConcept.getConceptId(row.get(procedureFields[i]).trim())); + procedureOccurrence.add("procedure_type_concept_id", procedureFieldConceptIds[i]); + procedureOccurrence.add("visit_occurrence_id", visitOccurrenceId); + tableToRows.put("procedure_occurrence", procedureOccurrence); + + if (procedureFields[i].equals("PR1")) + primaryProcedureOccurrenceId = procedureOccurrenceId; + } + } + + private void addToProcedureCost(Row row) { + if (primaryProcedureOccurrenceId != -1) { + Row procedureCost = new Row(); + procedureCost.add("procedure_occurrence_id", primaryProcedureOccurrenceId); + procedureCost.add("procedure_cost_id", ++procedureCostId); + procedureCost.add("disease_class_source_value", row.get("DRG")); + procedureCost.add("disease_class_concept_id", drgToConcept.getConceptId(row.get("DRG").trim())); + tableToRows.put("procedure_cost", procedureCost); + } + } + + private long computeVisitStartDate(String year, String amonth, String aweekend) { + if (Integer.parseInt(amonth) < 1) + amonth = "1"; + boolean isWeekend = aweekend.equals("1"); + Calendar calendar = Calendar.getInstance(); + calendar.set(Integer.parseInt(year), Integer.parseInt(amonth) - 1, 1); + while (isWeekend(calendar) != isWeekend) + calendar.add(Calendar.DATE, 1); + long time = calendar.getTimeInMillis(); + time += calendar.getTimeZone().getOffset(time); + return (((StringUtilities.MILLENIUM + time) / StringUtilities.DAY) - (1000 * 365)); + } + + private long computeVisitEndDate(long visitStartDate, String los) { + int lengthOfStay = Integer.parseInt(los); + if (lengthOfStay < 0) + lengthOfStay = 0; + return visitStartDate + lengthOfStay; + } + + private boolean isWeekend(Calendar calendar) { + int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); + return (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY); + } + + private void insertBatch() { + // addToDrugEra(); + // addToConditionEra(); + removeRowsWithNonNullableNulls(); + + etlReport.registerOutgoingData(tableToRows); + for (String table : tableToRows.keySet()) + targetConnection.insertIntoTable(tableToRows.get(table).iterator(), table, false); + tableToRows.clear(); + } + + private void loadMappings(DbSettings dbSettings) { + StringUtilities.outputWithTime("Loading mappings from server"); + RichConnection connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + + connection.use("vocabulary"); + + System.out.println("- Loading ICD-9 to SNOMED concept_id mapping"); + icd9ToConcept = new CodeToConceptMap("ICD-9 to SNOMED concept_id mapping"); + String query = "SELECT source_code,source_code_description,target_concept_id,concept_code,concept_name FROM source_to_concept_map INNER JOIN concept ON target_concept_id = concept_id WHERE source_vocabulary_id = 2 AND target_vocabulary_id = 1 AND concept_class='Clinical finding'"; + for (Row row : connection.query(query)) + icd9ToConcept.add(row.get("SOURCE_CODE").replace(".", ""), row.get("SOURCE_CODE_DESCRIPTION"), row.getInt("TARGET_CONCEPT_ID"), + row.get("CONCEPT_CODE"), row.get("CONCEPT_NAME")); + + System.out.println("- Loading ICD-9 to RxNorm concept_id mapping"); + icd9ToRxNorm = new CodeToConceptMap("ICD-9 to RxNorm concept_id mapping"); + query = "SELECT DISTINCT source_code,source_code_description,target_concept_id,concept_code,concept_name FROM source_to_concept_map INNER JOIN concept ON target_concept_id = concept_id WHERE target_vocabulary_id = 8 AND source_vocabulary_id in (3,4,5) AND primary_map = 'Y' AND source_to_concept_map.invalid_reason != 'D'"; + for (Row row : connection.query(query)) + icd9ToRxNorm.add(row.get("SOURCE_CODE").replace(".", ""), row.get("SOURCE_CODE_DESCRIPTION"), row.getInt("TARGET_CONCEPT_ID"), + row.get("CONCEPT_CODE"), row.get("CONCEPT_NAME")); + + System.out.println("- Loading ICD-9 Procedure to concept_id mapping"); + icd9ProcToConcept = new CodeToConceptMap("ICD-9 Procedure to concept_id mapping"); + query = "SELECT concept_id,concept_name,concept_code FROM concept WHERE vocabulary_id = 3"; + for (Row row : connection.query(query)) + icd9ProcToConcept.add(row.get("CONCEPT_CODE").replace(".", ""), row.get("CONCEPT_NAME"), row.getInt("CONCEPT_ID"), row.get("CONCEPT_CODE"), + row.get("CONCEPT_NAME")); + + System.out.println("- Loading DRG to concept_id mapping"); + drgToConcept = new CodeToConceptMap("DRG to concept_id mapping"); + query = "SELECT concept_id,concept_name,concept_code FROM concept WHERE vocabulary_id = 40 AND concept_class = 'DRG'"; + for (Row row : connection.query(query)) + drgToConcept.add(row.get("CONCEPT_CODE"), row.get("CONCEPT_NAME"), row.getInt("CONCEPT_ID"), row.get("CONCEPT_CODE"), row.get("CONCEPT_NAME")); + + System.out.println("- Loading county code to name mapping"); + codeToCounty = new HashMap(); + for (Row row : new ReadCSVFileWithHeader(this.getClass().getResourceAsStream("national_county.txt"))) + codeToCounty.put(row.get("State ANSI") + row.get("County ANSI"), row.get("County Name")); + + StringUtilities.outputWithTime("Finished loading mappings"); + } + + private void removeRowsWithNonNullableNulls() { + for (String table : tableToRows.keySet()) { + Iterator iterator = tableToRows.get(table).iterator(); + while (iterator.hasNext()) { + Row row = iterator.next(); + String nonAllowedNullField = cdmv4NullableChecker.findNonAllowedNull(table, row); + if (nonAllowedNullField != null) { + if (row.getFieldNames().contains("person_id")) + etlReport.reportProblem(table, "Column " + nonAllowedNullField + " is null, could not create row", row.get("person_id")); + else + etlReport.reportProblem(table, "Column " + nonAllowedNullField + " is null, could not create row", ""); + iterator.remove(); + } + } + } + } +} diff --git a/src/org/ohdsi/whiteRabbit/etls/hcup/national_county.txt b/src/org/ohdsi/whiteRabbit/etls/hcup/national_county.txt new file mode 100644 index 00000000..530f8b25 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/etls/hcup/national_county.txt @@ -0,0 +1,3236 @@ +State,State ANSI,County ANSI,County Name,ANSI Cl +AL,01,001,Autauga County,H1 +AL,01,003,Baldwin County,H1 +AL,01,005,Barbour County,H1 +AL,01,007,Bibb County,H1 +AL,01,009,Blount County,H1 +AL,01,011,Bullock County,H1 +AL,01,013,Butler County,H1 +AL,01,015,Calhoun County,H1 +AL,01,017,Chambers County,H1 +AL,01,019,Cherokee County,H1 +AL,01,021,Chilton County,H1 +AL,01,023,Choctaw County,H1 +AL,01,025,Clarke County,H1 +AL,01,027,Clay County,H1 +AL,01,029,Cleburne County,H1 +AL,01,031,Coffee County,H1 +AL,01,033,Colbert County,H1 +AL,01,035,Conecuh County,H1 +AL,01,037,Coosa County,H1 +AL,01,039,Covington County,H1 +AL,01,041,Crenshaw County,H1 +AL,01,043,Cullman County,H1 +AL,01,045,Dale County,H1 +AL,01,047,Dallas County,H1 +AL,01,049,DeKalb County,H1 +AL,01,051,Elmore County,H1 +AL,01,053,Escambia County,H1 +AL,01,055,Etowah County,H1 +AL,01,057,Fayette County,H1 +AL,01,059,Franklin County,H1 +AL,01,061,Geneva County,H1 +AL,01,063,Greene County,H1 +AL,01,065,Hale County,H1 +AL,01,067,Henry County,H1 +AL,01,069,Houston County,H1 +AL,01,071,Jackson County,H1 +AL,01,073,Jefferson County,H1 +AL,01,075,Lamar County,H1 +AL,01,077,Lauderdale County,H1 +AL,01,079,Lawrence County,H1 +AL,01,081,Lee County,H1 +AL,01,083,Limestone County,H1 +AL,01,085,Lowndes County,H1 +AL,01,087,Macon County,H1 +AL,01,089,Madison County,H1 +AL,01,091,Marengo County,H1 +AL,01,093,Marion County,H1 +AL,01,095,Marshall County,H1 +AL,01,097,Mobile County,H1 +AL,01,099,Monroe County,H1 +AL,01,101,Montgomery County,H1 +AL,01,103,Morgan County,H1 +AL,01,105,Perry County,H1 +AL,01,107,Pickens County,H1 +AL,01,109,Pike County,H1 +AL,01,111,Randolph County,H1 +AL,01,113,Russell County,H1 +AL,01,115,St. Clair County,H1 +AL,01,117,Shelby County,H1 +AL,01,119,Sumter County,H1 +AL,01,121,Talladega County,H1 +AL,01,123,Tallapoosa County,H1 +AL,01,125,Tuscaloosa County,H1 +AL,01,127,Walker County,H1 +AL,01,129,Washington County,H1 +AL,01,131,Wilcox County,H1 +AL,01,133,Winston County,H1 +AK,02,013,Aleutians East Borough,H1 +AK,02,016,Aleutians West Census Area,H5 +AK,02,020,Anchorage Municipality,H6 +AK,02,050,Bethel Census Area,H5 +AK,02,060,Bristol Bay Borough,H1 +AK,02,068,Denali Borough,H1 +AK,02,070,Dillingham Census Area,H5 +AK,02,090,Fairbanks North Star Borough,H1 +AK,02,100,Haines Borough,H1 +AK,02,105,Hoonah-Angoon Census Area,H5 +AK,02,110,Juneau City and Borough,H6 +AK,02,122,Kenai Peninsula Borough,H1 +AK,02,130,Ketchikan Gateway Borough,H1 +AK,02,150,Kodiak Island Borough,H1 +AK,02,164,Lake and Peninsula Borough,H1 +AK,02,170,Matanuska-Susitna Borough,H1 +AK,02,180,Nome Census Area,H5 +AK,02,185,North Slope Borough,H1 +AK,02,188,Northwest Arctic Borough,H1 +AK,02,195,Petersburg Census Area,H5 +AK,02,198,Prince of Wales-Hyder Census Area,H5 +AK,02,220,Sitka City and Borough,H6 +AK,02,230,Skagway Municipality,H1 +AK,02,240,Southeast Fairbanks Census Area,H5 +AK,02,261,Valdez-Cordova Census Area,H5 +AK,02,270,Wade Hampton Census Area,H5 +AK,02,275,Wrangell City and Borough,H1 +AK,02,282,Yakutat City and Borough,H1 +AK,02,290,Yukon-Koyukuk Census Area,H5 +AZ,04,001,Apache County,H1 +AZ,04,003,Cochise County,H1 +AZ,04,005,Coconino County,H1 +AZ,04,007,Gila County,H1 +AZ,04,009,Graham County,H1 +AZ,04,011,Greenlee County,H1 +AZ,04,012,La Paz County,H1 +AZ,04,013,Maricopa County,H1 +AZ,04,015,Mohave County,H1 +AZ,04,017,Navajo County,H1 +AZ,04,019,Pima County,H1 +AZ,04,021,Pinal County,H1 +AZ,04,023,Santa Cruz County,H1 +AZ,04,025,Yavapai County,H1 +AZ,04,027,Yuma County,H1 +AR,05,001,Arkansas County,H1 +AR,05,003,Ashley County,H1 +AR,05,005,Baxter County,H1 +AR,05,007,Benton County,H1 +AR,05,009,Boone County,H1 +AR,05,011,Bradley County,H1 +AR,05,013,Calhoun County,H1 +AR,05,015,Carroll County,H1 +AR,05,017,Chicot County,H1 +AR,05,019,Clark County,H1 +AR,05,021,Clay County,H1 +AR,05,023,Cleburne County,H1 +AR,05,025,Cleveland County,H1 +AR,05,027,Columbia County,H1 +AR,05,029,Conway County,H1 +AR,05,031,Craighead County,H1 +AR,05,033,Crawford County,H1 +AR,05,035,Crittenden County,H1 +AR,05,037,Cross County,H1 +AR,05,039,Dallas County,H1 +AR,05,041,Desha County,H1 +AR,05,043,Drew County,H1 +AR,05,045,Faulkner County,H1 +AR,05,047,Franklin County,H1 +AR,05,049,Fulton County,H1 +AR,05,051,Garland County,H1 +AR,05,053,Grant County,H1 +AR,05,055,Greene County,H1 +AR,05,057,Hempstead County,H1 +AR,05,059,Hot Spring County,H1 +AR,05,061,Howard County,H1 +AR,05,063,Independence County,H1 +AR,05,065,Izard County,H1 +AR,05,067,Jackson County,H1 +AR,05,069,Jefferson County,H1 +AR,05,071,Johnson County,H1 +AR,05,073,Lafayette County,H1 +AR,05,075,Lawrence County,H1 +AR,05,077,Lee County,H1 +AR,05,079,Lincoln County,H1 +AR,05,081,Little River County,H1 +AR,05,083,Logan County,H1 +AR,05,085,Lonoke County,H1 +AR,05,087,Madison County,H1 +AR,05,089,Marion County,H1 +AR,05,091,Miller County,H1 +AR,05,093,Mississippi County,H1 +AR,05,095,Monroe County,H1 +AR,05,097,Montgomery County,H1 +AR,05,099,Nevada County,H1 +AR,05,101,Newton County,H1 +AR,05,103,Ouachita County,H1 +AR,05,105,Perry County,H1 +AR,05,107,Phillips County,H1 +AR,05,109,Pike County,H1 +AR,05,111,Poinsett County,H1 +AR,05,113,Polk County,H1 +AR,05,115,Pope County,H1 +AR,05,117,Prairie County,H1 +AR,05,119,Pulaski County,H1 +AR,05,121,Randolph County,H1 +AR,05,123,St. Francis County,H1 +AR,05,125,Saline County,H1 +AR,05,127,Scott County,H1 +AR,05,129,Searcy County,H1 +AR,05,131,Sebastian County,H1 +AR,05,133,Sevier County,H1 +AR,05,135,Sharp County,H1 +AR,05,137,Stone County,H1 +AR,05,139,Union County,H1 +AR,05,141,Van Buren County,H1 +AR,05,143,Washington County,H1 +AR,05,145,White County,H1 +AR,05,147,Woodruff County,H1 +AR,05,149,Yell County,H1 +CA,06,001,Alameda County,H1 +CA,06,003,Alpine County,H1 +CA,06,005,Amador County,H1 +CA,06,007,Butte County,H1 +CA,06,009,Calaveras County,H1 +CA,06,011,Colusa County,H1 +CA,06,013,Contra Costa County,H1 +CA,06,015,Del Norte County,H1 +CA,06,017,El Dorado County,H1 +CA,06,019,Fresno County,H1 +CA,06,021,Glenn County,H1 +CA,06,023,Humboldt County,H1 +CA,06,025,Imperial County,H1 +CA,06,027,Inyo County,H1 +CA,06,029,Kern County,H1 +CA,06,031,Kings County,H1 +CA,06,033,Lake County,H1 +CA,06,035,Lassen County,H1 +CA,06,037,Los Angeles County,H1 +CA,06,039,Madera County,H1 +CA,06,041,Marin County,H1 +CA,06,043,Mariposa County,H1 +CA,06,045,Mendocino County,H1 +CA,06,047,Merced County,H1 +CA,06,049,Modoc County,H1 +CA,06,051,Mono County,H1 +CA,06,053,Monterey County,H1 +CA,06,055,Napa County,H1 +CA,06,057,Nevada County,H1 +CA,06,059,Orange County,H1 +CA,06,061,Placer County,H1 +CA,06,063,Plumas County,H1 +CA,06,065,Riverside County,H1 +CA,06,067,Sacramento County,H1 +CA,06,069,San Benito County,H1 +CA,06,071,San Bernardino County,H1 +CA,06,073,San Diego County,H1 +CA,06,075,San Francisco County,H6 +CA,06,077,San Joaquin County,H1 +CA,06,079,San Luis Obispo County,H1 +CA,06,081,San Mateo County,H1 +CA,06,083,Santa Barbara County,H1 +CA,06,085,Santa Clara County,H1 +CA,06,087,Santa Cruz County,H1 +CA,06,089,Shasta County,H1 +CA,06,091,Sierra County,H1 +CA,06,093,Siskiyou County,H1 +CA,06,095,Solano County,H1 +CA,06,097,Sonoma County,H1 +CA,06,099,Stanislaus County,H1 +CA,06,101,Sutter County,H1 +CA,06,103,Tehama County,H1 +CA,06,105,Trinity County,H1 +CA,06,107,Tulare County,H1 +CA,06,109,Tuolumne County,H1 +CA,06,111,Ventura County,H1 +CA,06,113,Yolo County,H1 +CA,06,115,Yuba County,H1 +CO,08,001,Adams County,H1 +CO,08,003,Alamosa County,H1 +CO,08,005,Arapahoe County,H1 +CO,08,007,Archuleta County,H1 +CO,08,009,Baca County,H1 +CO,08,011,Bent County,H1 +CO,08,013,Boulder County,H1 +CO,08,014,Broomfield County,H6 +CO,08,015,Chaffee County,H1 +CO,08,017,Cheyenne County,H1 +CO,08,019,Clear Creek County,H1 +CO,08,021,Conejos County,H1 +CO,08,023,Costilla County,H1 +CO,08,025,Crowley County,H1 +CO,08,027,Custer County,H1 +CO,08,029,Delta County,H1 +CO,08,031,Denver County,H6 +CO,08,033,Dolores County,H1 +CO,08,035,Douglas County,H1 +CO,08,037,Eagle County,H1 +CO,08,039,Elbert County,H1 +CO,08,041,El Paso County,H1 +CO,08,043,Fremont County,H1 +CO,08,045,Garfield County,H1 +CO,08,047,Gilpin County,H1 +CO,08,049,Grand County,H1 +CO,08,051,Gunnison County,H1 +CO,08,053,Hinsdale County,H1 +CO,08,055,Huerfano County,H1 +CO,08,057,Jackson County,H1 +CO,08,059,Jefferson County,H1 +CO,08,061,Kiowa County,H1 +CO,08,063,Kit Carson County,H1 +CO,08,065,Lake County,H1 +CO,08,067,La Plata County,H1 +CO,08,069,Larimer County,H1 +CO,08,071,Las Animas County,H1 +CO,08,073,Lincoln County,H1 +CO,08,075,Logan County,H1 +CO,08,077,Mesa County,H1 +CO,08,079,Mineral County,H1 +CO,08,081,Moffat County,H1 +CO,08,083,Montezuma County,H1 +CO,08,085,Montrose County,H1 +CO,08,087,Morgan County,H1 +CO,08,089,Otero County,H1 +CO,08,091,Ouray County,H1 +CO,08,093,Park County,H1 +CO,08,095,Phillips County,H1 +CO,08,097,Pitkin County,H1 +CO,08,099,Prowers County,H1 +CO,08,101,Pueblo County,H1 +CO,08,103,Rio Blanco County,H1 +CO,08,105,Rio Grande County,H1 +CO,08,107,Routt County,H1 +CO,08,109,Saguache County,H1 +CO,08,111,San Juan County,H1 +CO,08,113,San Miguel County,H1 +CO,08,115,Sedgwick County,H1 +CO,08,117,Summit County,H1 +CO,08,119,Teller County,H1 +CO,08,121,Washington County,H1 +CO,08,123,Weld County,H1 +CO,08,125,Yuma County,H1 +CT,09,001,Fairfield County,H4 +CT,09,003,Hartford County,H4 +CT,09,005,Litchfield County,H4 +CT,09,007,Middlesex County,H4 +CT,09,009,New Haven County,H4 +CT,09,011,New London County,H4 +CT,09,013,Tolland County,H4 +CT,09,015,Windham County,H4 +DE,10,001,Kent County,H1 +DE,10,003,New Castle County,H1 +DE,10,005,Sussex County,H1 +DC,11,001,District of Columbia,H6 +FL,12,001,Alachua County,H1 +FL,12,003,Baker County,H1 +FL,12,005,Bay County,H1 +FL,12,007,Bradford County,H1 +FL,12,009,Brevard County,H1 +FL,12,011,Broward County,H1 +FL,12,013,Calhoun County,H1 +FL,12,015,Charlotte County,H1 +FL,12,017,Citrus County,H1 +FL,12,019,Clay County,H1 +FL,12,021,Collier County,H1 +FL,12,023,Columbia County,H1 +FL,12,027,DeSoto County,H1 +FL,12,029,Dixie County,H1 +FL,12,031,Duval County,H6 +FL,12,033,Escambia County,H1 +FL,12,035,Flagler County,H1 +FL,12,037,Franklin County,H1 +FL,12,039,Gadsden County,H1 +FL,12,041,Gilchrist County,H1 +FL,12,043,Glades County,H1 +FL,12,045,Gulf County,H1 +FL,12,047,Hamilton County,H1 +FL,12,049,Hardee County,H1 +FL,12,051,Hendry County,H1 +FL,12,053,Hernando County,H1 +FL,12,055,Highlands County,H1 +FL,12,057,Hillsborough County,H1 +FL,12,059,Holmes County,H1 +FL,12,061,Indian River County,H1 +FL,12,063,Jackson County,H1 +FL,12,065,Jefferson County,H1 +FL,12,067,Lafayette County,H1 +FL,12,069,Lake County,H1 +FL,12,071,Lee County,H1 +FL,12,073,Leon County,H1 +FL,12,075,Levy County,H1 +FL,12,077,Liberty County,H1 +FL,12,079,Madison County,H1 +FL,12,081,Manatee County,H1 +FL,12,083,Marion County,H1 +FL,12,085,Martin County,H1 +FL,12,086,Miami-Dade County,H1 +FL,12,087,Monroe County,H1 +FL,12,089,Nassau County,H1 +FL,12,091,Okaloosa County,H1 +FL,12,093,Okeechobee County,H1 +FL,12,095,Orange County,H1 +FL,12,097,Osceola County,H1 +FL,12,099,Palm Beach County,H1 +FL,12,101,Pasco County,H1 +FL,12,103,Pinellas County,H1 +FL,12,105,Polk County,H1 +FL,12,107,Putnam County,H1 +FL,12,109,St. Johns County,H1 +FL,12,111,St. Lucie County,H1 +FL,12,113,Santa Rosa County,H1 +FL,12,115,Sarasota County,H1 +FL,12,117,Seminole County,H1 +FL,12,119,Sumter County,H1 +FL,12,121,Suwannee County,H1 +FL,12,123,Taylor County,H1 +FL,12,125,Union County,H1 +FL,12,127,Volusia County,H1 +FL,12,129,Wakulla County,H1 +FL,12,131,Walton County,H1 +FL,12,133,Washington County,H1 +GA,13,001,Appling County,H1 +GA,13,003,Atkinson County,H1 +GA,13,005,Bacon County,H1 +GA,13,007,Baker County,H1 +GA,13,009,Baldwin County,H1 +GA,13,011,Banks County,H1 +GA,13,013,Barrow County,H1 +GA,13,015,Bartow County,H1 +GA,13,017,Ben Hill County,H1 +GA,13,019,Berrien County,H1 +GA,13,021,Bibb County,H1 +GA,13,023,Bleckley County,H1 +GA,13,025,Brantley County,H1 +GA,13,027,Brooks County,H1 +GA,13,029,Bryan County,H1 +GA,13,031,Bulloch County,H1 +GA,13,033,Burke County,H1 +GA,13,035,Butts County,H1 +GA,13,037,Calhoun County,H1 +GA,13,039,Camden County,H1 +GA,13,043,Candler County,H1 +GA,13,045,Carroll County,H1 +GA,13,047,Catoosa County,H1 +GA,13,049,Charlton County,H1 +GA,13,051,Chatham County,H1 +GA,13,053,Chattahoochee County,H1 +GA,13,055,Chattooga County,H1 +GA,13,057,Cherokee County,H1 +GA,13,059,Clarke County,H6 +GA,13,061,Clay County,H1 +GA,13,063,Clayton County,H1 +GA,13,065,Clinch County,H1 +GA,13,067,Cobb County,H1 +GA,13,069,Coffee County,H1 +GA,13,071,Colquitt County,H1 +GA,13,073,Columbia County,H1 +GA,13,075,Cook County,H1 +GA,13,077,Coweta County,H1 +GA,13,079,Crawford County,H1 +GA,13,081,Crisp County,H1 +GA,13,083,Dade County,H1 +GA,13,085,Dawson County,H1 +GA,13,087,Decatur County,H1 +GA,13,089,DeKalb County,H1 +GA,13,091,Dodge County,H1 +GA,13,093,Dooly County,H1 +GA,13,095,Dougherty County,H1 +GA,13,097,Douglas County,H1 +GA,13,099,Early County,H1 +GA,13,101,Echols County,H1 +GA,13,103,Effingham County,H1 +GA,13,105,Elbert County,H1 +GA,13,107,Emanuel County,H1 +GA,13,109,Evans County,H1 +GA,13,111,Fannin County,H1 +GA,13,113,Fayette County,H1 +GA,13,115,Floyd County,H1 +GA,13,117,Forsyth County,H1 +GA,13,119,Franklin County,H1 +GA,13,121,Fulton County,H1 +GA,13,123,Gilmer County,H1 +GA,13,125,Glascock County,H1 +GA,13,127,Glynn County,H1 +GA,13,129,Gordon County,H1 +GA,13,131,Grady County,H1 +GA,13,133,Greene County,H1 +GA,13,135,Gwinnett County,H1 +GA,13,137,Habersham County,H1 +GA,13,139,Hall County,H1 +GA,13,141,Hancock County,H1 +GA,13,143,Haralson County,H1 +GA,13,145,Harris County,H1 +GA,13,147,Hart County,H1 +GA,13,149,Heard County,H1 +GA,13,151,Henry County,H1 +GA,13,153,Houston County,H1 +GA,13,155,Irwin County,H1 +GA,13,157,Jackson County,H1 +GA,13,159,Jasper County,H1 +GA,13,161,Jeff Davis County,H1 +GA,13,163,Jefferson County,H1 +GA,13,165,Jenkins County,H1 +GA,13,167,Johnson County,H1 +GA,13,169,Jones County,H1 +GA,13,171,Lamar County,H1 +GA,13,173,Lanier County,H1 +GA,13,175,Laurens County,H1 +GA,13,177,Lee County,H1 +GA,13,179,Liberty County,H1 +GA,13,181,Lincoln County,H1 +GA,13,183,Long County,H1 +GA,13,185,Lowndes County,H1 +GA,13,187,Lumpkin County,H1 +GA,13,189,McDuffie County,H1 +GA,13,191,McIntosh County,H1 +GA,13,193,Macon County,H1 +GA,13,195,Madison County,H1 +GA,13,197,Marion County,H1 +GA,13,199,Meriwether County,H1 +GA,13,201,Miller County,H1 +GA,13,205,Mitchell County,H1 +GA,13,207,Monroe County,H1 +GA,13,209,Montgomery County,H1 +GA,13,211,Morgan County,H1 +GA,13,213,Murray County,H1 +GA,13,215,Muscogee County,H6 +GA,13,217,Newton County,H1 +GA,13,219,Oconee County,H1 +GA,13,221,Oglethorpe County,H1 +GA,13,223,Paulding County,H1 +GA,13,225,Peach County,H1 +GA,13,227,Pickens County,H1 +GA,13,229,Pierce County,H1 +GA,13,231,Pike County,H1 +GA,13,233,Polk County,H1 +GA,13,235,Pulaski County,H1 +GA,13,237,Putnam County,H1 +GA,13,239,Quitman County,H1 +GA,13,241,Rabun County,H1 +GA,13,243,Randolph County,H1 +GA,13,245,Richmond County,H6 +GA,13,247,Rockdale County,H1 +GA,13,249,Schley County,H1 +GA,13,251,Screven County,H1 +GA,13,253,Seminole County,H1 +GA,13,255,Spalding County,H1 +GA,13,257,Stephens County,H1 +GA,13,259,Stewart County,H1 +GA,13,261,Sumter County,H1 +GA,13,263,Talbot County,H1 +GA,13,265,Taliaferro County,H1 +GA,13,267,Tattnall County,H1 +GA,13,269,Taylor County,H1 +GA,13,271,Telfair County,H1 +GA,13,273,Terrell County,H1 +GA,13,275,Thomas County,H1 +GA,13,277,Tift County,H1 +GA,13,279,Toombs County,H1 +GA,13,281,Towns County,H1 +GA,13,283,Treutlen County,H1 +GA,13,285,Troup County,H1 +GA,13,287,Turner County,H1 +GA,13,289,Twiggs County,H1 +GA,13,291,Union County,H1 +GA,13,293,Upson County,H1 +GA,13,295,Walker County,H1 +GA,13,297,Walton County,H1 +GA,13,299,Ware County,H1 +GA,13,301,Warren County,H1 +GA,13,303,Washington County,H1 +GA,13,305,Wayne County,H1 +GA,13,307,Webster County,H1 +GA,13,309,Wheeler County,H1 +GA,13,311,White County,H1 +GA,13,313,Whitfield County,H1 +GA,13,315,Wilcox County,H1 +GA,13,317,Wilkes County,H1 +GA,13,319,Wilkinson County,H1 +GA,13,321,Worth County,H1 +HI,15,001,Hawaii County,H1 +HI,15,003,Honolulu County,H1 +HI,15,005,Kalawao County,H4 +HI,15,007,Kauai County,H1 +HI,15,009,Maui County,H1 +ID,16,001,Ada County,H1 +ID,16,003,Adams County,H1 +ID,16,005,Bannock County,H1 +ID,16,007,Bear Lake County,H1 +ID,16,009,Benewah County,H1 +ID,16,011,Bingham County,H1 +ID,16,013,Blaine County,H1 +ID,16,015,Boise County,H1 +ID,16,017,Bonner County,H1 +ID,16,019,Bonneville County,H1 +ID,16,021,Boundary County,H1 +ID,16,023,Butte County,H1 +ID,16,025,Camas County,H1 +ID,16,027,Canyon County,H1 +ID,16,029,Caribou County,H1 +ID,16,031,Cassia County,H1 +ID,16,033,Clark County,H1 +ID,16,035,Clearwater County,H1 +ID,16,037,Custer County,H1 +ID,16,039,Elmore County,H1 +ID,16,041,Franklin County,H1 +ID,16,043,Fremont County,H1 +ID,16,045,Gem County,H1 +ID,16,047,Gooding County,H1 +ID,16,049,Idaho County,H1 +ID,16,051,Jefferson County,H1 +ID,16,053,Jerome County,H1 +ID,16,055,Kootenai County,H1 +ID,16,057,Latah County,H1 +ID,16,059,Lemhi County,H1 +ID,16,061,Lewis County,H1 +ID,16,063,Lincoln County,H1 +ID,16,065,Madison County,H1 +ID,16,067,Minidoka County,H1 +ID,16,069,Nez Perce County,H1 +ID,16,071,Oneida County,H1 +ID,16,073,Owyhee County,H1 +ID,16,075,Payette County,H1 +ID,16,077,Power County,H1 +ID,16,079,Shoshone County,H1 +ID,16,081,Teton County,H1 +ID,16,083,Twin Falls County,H1 +ID,16,085,Valley County,H1 +ID,16,087,Washington County,H1 +IL,17,001,Adams County,H1 +IL,17,003,Alexander County,H1 +IL,17,005,Bond County,H1 +IL,17,007,Boone County,H1 +IL,17,009,Brown County,H1 +IL,17,011,Bureau County,H1 +IL,17,013,Calhoun County,H1 +IL,17,015,Carroll County,H1 +IL,17,017,Cass County,H1 +IL,17,019,Champaign County,H1 +IL,17,021,Christian County,H1 +IL,17,023,Clark County,H1 +IL,17,025,Clay County,H1 +IL,17,027,Clinton County,H1 +IL,17,029,Coles County,H1 +IL,17,031,Cook County,H1 +IL,17,033,Crawford County,H1 +IL,17,035,Cumberland County,H1 +IL,17,037,DeKalb County,H1 +IL,17,039,De Witt County,H1 +IL,17,041,Douglas County,H1 +IL,17,043,DuPage County,H1 +IL,17,045,Edgar County,H1 +IL,17,047,Edwards County,H1 +IL,17,049,Effingham County,H1 +IL,17,051,Fayette County,H1 +IL,17,053,Ford County,H1 +IL,17,055,Franklin County,H1 +IL,17,057,Fulton County,H1 +IL,17,059,Gallatin County,H1 +IL,17,061,Greene County,H1 +IL,17,063,Grundy County,H1 +IL,17,065,Hamilton County,H1 +IL,17,067,Hancock County,H1 +IL,17,069,Hardin County,H1 +IL,17,071,Henderson County,H1 +IL,17,073,Henry County,H1 +IL,17,075,Iroquois County,H1 +IL,17,077,Jackson County,H1 +IL,17,079,Jasper County,H1 +IL,17,081,Jefferson County,H1 +IL,17,083,Jersey County,H1 +IL,17,085,Jo Daviess County,H1 +IL,17,087,Johnson County,H1 +IL,17,089,Kane County,H1 +IL,17,091,Kankakee County,H1 +IL,17,093,Kendall County,H1 +IL,17,095,Knox County,H1 +IL,17,097,Lake County,H1 +IL,17,099,LaSalle County,H1 +IL,17,101,Lawrence County,H1 +IL,17,103,Lee County,H1 +IL,17,105,Livingston County,H1 +IL,17,107,Logan County,H1 +IL,17,109,McDonough County,H1 +IL,17,111,McHenry County,H1 +IL,17,113,McLean County,H1 +IL,17,115,Macon County,H1 +IL,17,117,Macoupin County,H1 +IL,17,119,Madison County,H1 +IL,17,121,Marion County,H1 +IL,17,123,Marshall County,H1 +IL,17,125,Mason County,H1 +IL,17,127,Massac County,H1 +IL,17,129,Menard County,H1 +IL,17,131,Mercer County,H1 +IL,17,133,Monroe County,H1 +IL,17,135,Montgomery County,H1 +IL,17,137,Morgan County,H1 +IL,17,139,Moultrie County,H1 +IL,17,141,Ogle County,H1 +IL,17,143,Peoria County,H1 +IL,17,145,Perry County,H1 +IL,17,147,Piatt County,H1 +IL,17,149,Pike County,H1 +IL,17,151,Pope County,H1 +IL,17,153,Pulaski County,H1 +IL,17,155,Putnam County,H1 +IL,17,157,Randolph County,H1 +IL,17,159,Richland County,H1 +IL,17,161,Rock Island County,H1 +IL,17,163,St. Clair County,H1 +IL,17,165,Saline County,H1 +IL,17,167,Sangamon County,H1 +IL,17,169,Schuyler County,H1 +IL,17,171,Scott County,H1 +IL,17,173,Shelby County,H1 +IL,17,175,Stark County,H1 +IL,17,177,Stephenson County,H1 +IL,17,179,Tazewell County,H1 +IL,17,181,Union County,H1 +IL,17,183,Vermilion County,H1 +IL,17,185,Wabash County,H1 +IL,17,187,Warren County,H1 +IL,17,189,Washington County,H1 +IL,17,191,Wayne County,H1 +IL,17,193,White County,H1 +IL,17,195,Whiteside County,H1 +IL,17,197,Will County,H1 +IL,17,199,Williamson County,H1 +IL,17,201,Winnebago County,H1 +IL,17,203,Woodford County,H1 +IN,18,001,Adams County,H1 +IN,18,003,Allen County,H1 +IN,18,005,Bartholomew County,H1 +IN,18,007,Benton County,H1 +IN,18,009,Blackford County,H1 +IN,18,011,Boone County,H1 +IN,18,013,Brown County,H1 +IN,18,015,Carroll County,H1 +IN,18,017,Cass County,H1 +IN,18,019,Clark County,H1 +IN,18,021,Clay County,H1 +IN,18,023,Clinton County,H1 +IN,18,025,Crawford County,H1 +IN,18,027,Daviess County,H1 +IN,18,029,Dearborn County,H1 +IN,18,031,Decatur County,H1 +IN,18,033,DeKalb County,H1 +IN,18,035,Delaware County,H1 +IN,18,037,Dubois County,H1 +IN,18,039,Elkhart County,H1 +IN,18,041,Fayette County,H1 +IN,18,043,Floyd County,H1 +IN,18,045,Fountain County,H1 +IN,18,047,Franklin County,H1 +IN,18,049,Fulton County,H1 +IN,18,051,Gibson County,H1 +IN,18,053,Grant County,H1 +IN,18,055,Greene County,H1 +IN,18,057,Hamilton County,H1 +IN,18,059,Hancock County,H1 +IN,18,061,Harrison County,H1 +IN,18,063,Hendricks County,H1 +IN,18,065,Henry County,H1 +IN,18,067,Howard County,H1 +IN,18,069,Huntington County,H1 +IN,18,071,Jackson County,H1 +IN,18,073,Jasper County,H1 +IN,18,075,Jay County,H1 +IN,18,077,Jefferson County,H1 +IN,18,079,Jennings County,H1 +IN,18,081,Johnson County,H1 +IN,18,083,Knox County,H1 +IN,18,085,Kosciusko County,H1 +IN,18,087,LaGrange County,H1 +IN,18,089,Lake County,H1 +IN,18,091,LaPorte County,H1 +IN,18,093,Lawrence County,H1 +IN,18,095,Madison County,H1 +IN,18,097,Marion County,H6 +IN,18,099,Marshall County,H1 +IN,18,101,Martin County,H1 +IN,18,103,Miami County,H1 +IN,18,105,Monroe County,H1 +IN,18,107,Montgomery County,H1 +IN,18,109,Morgan County,H1 +IN,18,111,Newton County,H1 +IN,18,113,Noble County,H1 +IN,18,115,Ohio County,H1 +IN,18,117,Orange County,H1 +IN,18,119,Owen County,H1 +IN,18,121,Parke County,H1 +IN,18,123,Perry County,H1 +IN,18,125,Pike County,H1 +IN,18,127,Porter County,H1 +IN,18,129,Posey County,H1 +IN,18,131,Pulaski County,H1 +IN,18,133,Putnam County,H1 +IN,18,135,Randolph County,H1 +IN,18,137,Ripley County,H1 +IN,18,139,Rush County,H1 +IN,18,141,St. Joseph County,H1 +IN,18,143,Scott County,H1 +IN,18,145,Shelby County,H1 +IN,18,147,Spencer County,H1 +IN,18,149,Starke County,H1 +IN,18,151,Steuben County,H1 +IN,18,153,Sullivan County,H1 +IN,18,155,Switzerland County,H1 +IN,18,157,Tippecanoe County,H1 +IN,18,159,Tipton County,H1 +IN,18,161,Union County,H1 +IN,18,163,Vanderburgh County,H1 +IN,18,165,Vermillion County,H1 +IN,18,167,Vigo County,H1 +IN,18,169,Wabash County,H1 +IN,18,171,Warren County,H1 +IN,18,173,Warrick County,H1 +IN,18,175,Washington County,H1 +IN,18,177,Wayne County,H1 +IN,18,179,Wells County,H1 +IN,18,181,White County,H1 +IN,18,183,Whitley County,H1 +IA,19,001,Adair County,H1 +IA,19,003,Adams County,H1 +IA,19,005,Allamakee County,H1 +IA,19,007,Appanoose County,H1 +IA,19,009,Audubon County,H1 +IA,19,011,Benton County,H1 +IA,19,013,Black Hawk County,H1 +IA,19,015,Boone County,H1 +IA,19,017,Bremer County,H1 +IA,19,019,Buchanan County,H1 +IA,19,021,Buena Vista County,H1 +IA,19,023,Butler County,H1 +IA,19,025,Calhoun County,H1 +IA,19,027,Carroll County,H1 +IA,19,029,Cass County,H1 +IA,19,031,Cedar County,H1 +IA,19,033,Cerro Gordo County,H1 +IA,19,035,Cherokee County,H1 +IA,19,037,Chickasaw County,H1 +IA,19,039,Clarke County,H1 +IA,19,041,Clay County,H1 +IA,19,043,Clayton County,H1 +IA,19,045,Clinton County,H1 +IA,19,047,Crawford County,H1 +IA,19,049,Dallas County,H1 +IA,19,051,Davis County,H1 +IA,19,053,Decatur County,H1 +IA,19,055,Delaware County,H1 +IA,19,057,Des Moines County,H1 +IA,19,059,Dickinson County,H1 +IA,19,061,Dubuque County,H1 +IA,19,063,Emmet County,H1 +IA,19,065,Fayette County,H1 +IA,19,067,Floyd County,H1 +IA,19,069,Franklin County,H1 +IA,19,071,Fremont County,H1 +IA,19,073,Greene County,H1 +IA,19,075,Grundy County,H1 +IA,19,077,Guthrie County,H1 +IA,19,079,Hamilton County,H1 +IA,19,081,Hancock County,H1 +IA,19,083,Hardin County,H1 +IA,19,085,Harrison County,H1 +IA,19,087,Henry County,H1 +IA,19,089,Howard County,H1 +IA,19,091,Humboldt County,H1 +IA,19,093,Ida County,H1 +IA,19,095,Iowa County,H1 +IA,19,097,Jackson County,H1 +IA,19,099,Jasper County,H1 +IA,19,101,Jefferson County,H1 +IA,19,103,Johnson County,H1 +IA,19,105,Jones County,H1 +IA,19,107,Keokuk County,H1 +IA,19,109,Kossuth County,H1 +IA,19,111,Lee County,H1 +IA,19,113,Linn County,H1 +IA,19,115,Louisa County,H1 +IA,19,117,Lucas County,H1 +IA,19,119,Lyon County,H1 +IA,19,121,Madison County,H1 +IA,19,123,Mahaska County,H1 +IA,19,125,Marion County,H1 +IA,19,127,Marshall County,H1 +IA,19,129,Mills County,H1 +IA,19,131,Mitchell County,H1 +IA,19,133,Monona County,H1 +IA,19,135,Monroe County,H1 +IA,19,137,Montgomery County,H1 +IA,19,139,Muscatine County,H1 +IA,19,141,O'Brien County,H1 +IA,19,143,Osceola County,H1 +IA,19,145,Page County,H1 +IA,19,147,Palo Alto County,H1 +IA,19,149,Plymouth County,H1 +IA,19,151,Pocahontas County,H1 +IA,19,153,Polk County,H1 +IA,19,155,Pottawattamie County,H1 +IA,19,157,Poweshiek County,H1 +IA,19,159,Ringgold County,H1 +IA,19,161,Sac County,H1 +IA,19,163,Scott County,H1 +IA,19,165,Shelby County,H1 +IA,19,167,Sioux County,H1 +IA,19,169,Story County,H1 +IA,19,171,Tama County,H1 +IA,19,173,Taylor County,H1 +IA,19,175,Union County,H1 +IA,19,177,Van Buren County,H1 +IA,19,179,Wapello County,H1 +IA,19,181,Warren County,H1 +IA,19,183,Washington County,H1 +IA,19,185,Wayne County,H1 +IA,19,187,Webster County,H1 +IA,19,189,Winnebago County,H1 +IA,19,191,Winneshiek County,H1 +IA,19,193,Woodbury County,H1 +IA,19,195,Worth County,H1 +IA,19,197,Wright County,H1 +KS,20,001,Allen County,H1 +KS,20,003,Anderson County,H1 +KS,20,005,Atchison County,H1 +KS,20,007,Barber County,H1 +KS,20,009,Barton County,H1 +KS,20,011,Bourbon County,H1 +KS,20,013,Brown County,H1 +KS,20,015,Butler County,H1 +KS,20,017,Chase County,H1 +KS,20,019,Chautauqua County,H1 +KS,20,021,Cherokee County,H1 +KS,20,023,Cheyenne County,H1 +KS,20,025,Clark County,H1 +KS,20,027,Clay County,H1 +KS,20,029,Cloud County,H1 +KS,20,031,Coffey County,H1 +KS,20,033,Comanche County,H1 +KS,20,035,Cowley County,H1 +KS,20,037,Crawford County,H1 +KS,20,039,Decatur County,H1 +KS,20,041,Dickinson County,H1 +KS,20,043,Doniphan County,H1 +KS,20,045,Douglas County,H1 +KS,20,047,Edwards County,H1 +KS,20,049,Elk County,H1 +KS,20,051,Ellis County,H1 +KS,20,053,Ellsworth County,H1 +KS,20,055,Finney County,H1 +KS,20,057,Ford County,H1 +KS,20,059,Franklin County,H1 +KS,20,061,Geary County,H1 +KS,20,063,Gove County,H1 +KS,20,065,Graham County,H1 +KS,20,067,Grant County,H1 +KS,20,069,Gray County,H1 +KS,20,071,Greeley County,H1 +KS,20,073,Greenwood County,H1 +KS,20,075,Hamilton County,H1 +KS,20,077,Harper County,H1 +KS,20,079,Harvey County,H1 +KS,20,081,Haskell County,H1 +KS,20,083,Hodgeman County,H1 +KS,20,085,Jackson County,H1 +KS,20,087,Jefferson County,H1 +KS,20,089,Jewell County,H1 +KS,20,091,Johnson County,H1 +KS,20,093,Kearny County,H1 +KS,20,095,Kingman County,H1 +KS,20,097,Kiowa County,H1 +KS,20,099,Labette County,H1 +KS,20,101,Lane County,H1 +KS,20,103,Leavenworth County,H1 +KS,20,105,Lincoln County,H1 +KS,20,107,Linn County,H1 +KS,20,109,Logan County,H1 +KS,20,111,Lyon County,H1 +KS,20,113,McPherson County,H1 +KS,20,115,Marion County,H1 +KS,20,117,Marshall County,H1 +KS,20,119,Meade County,H1 +KS,20,121,Miami County,H1 +KS,20,123,Mitchell County,H1 +KS,20,125,Montgomery County,H1 +KS,20,127,Morris County,H1 +KS,20,129,Morton County,H1 +KS,20,131,Nemaha County,H1 +KS,20,133,Neosho County,H1 +KS,20,135,Ness County,H1 +KS,20,137,Norton County,H1 +KS,20,139,Osage County,H1 +KS,20,141,Osborne County,H1 +KS,20,143,Ottawa County,H1 +KS,20,145,Pawnee County,H1 +KS,20,147,Phillips County,H1 +KS,20,149,Pottawatomie County,H1 +KS,20,151,Pratt County,H1 +KS,20,153,Rawlins County,H1 +KS,20,155,Reno County,H1 +KS,20,157,Republic County,H1 +KS,20,159,Rice County,H1 +KS,20,161,Riley County,H1 +KS,20,163,Rooks County,H1 +KS,20,165,Rush County,H1 +KS,20,167,Russell County,H1 +KS,20,169,Saline County,H1 +KS,20,171,Scott County,H1 +KS,20,173,Sedgwick County,H1 +KS,20,175,Seward County,H1 +KS,20,177,Shawnee County,H1 +KS,20,179,Sheridan County,H1 +KS,20,181,Sherman County,H1 +KS,20,183,Smith County,H1 +KS,20,185,Stafford County,H1 +KS,20,187,Stanton County,H1 +KS,20,189,Stevens County,H1 +KS,20,191,Sumner County,H1 +KS,20,193,Thomas County,H1 +KS,20,195,Trego County,H1 +KS,20,197,Wabaunsee County,H1 +KS,20,199,Wallace County,H1 +KS,20,201,Washington County,H1 +KS,20,203,Wichita County,H1 +KS,20,205,Wilson County,H1 +KS,20,207,Woodson County,H1 +KS,20,209,Wyandotte County,H6 +KY,21,001,Adair County,H1 +KY,21,003,Allen County,H1 +KY,21,005,Anderson County,H1 +KY,21,007,Ballard County,H1 +KY,21,009,Barren County,H1 +KY,21,011,Bath County,H1 +KY,21,013,Bell County,H1 +KY,21,015,Boone County,H1 +KY,21,017,Bourbon County,H1 +KY,21,019,Boyd County,H1 +KY,21,021,Boyle County,H1 +KY,21,023,Bracken County,H1 +KY,21,025,Breathitt County,H1 +KY,21,027,Breckinridge County,H1 +KY,21,029,Bullitt County,H1 +KY,21,031,Butler County,H1 +KY,21,033,Caldwell County,H1 +KY,21,035,Calloway County,H1 +KY,21,037,Campbell County,H1 +KY,21,039,Carlisle County,H1 +KY,21,041,Carroll County,H1 +KY,21,043,Carter County,H1 +KY,21,045,Casey County,H1 +KY,21,047,Christian County,H1 +KY,21,049,Clark County,H1 +KY,21,051,Clay County,H1 +KY,21,053,Clinton County,H1 +KY,21,055,Crittenden County,H1 +KY,21,057,Cumberland County,H1 +KY,21,059,Daviess County,H1 +KY,21,061,Edmonson County,H1 +KY,21,063,Elliott County,H1 +KY,21,065,Estill County,H1 +KY,21,067,Fayette County,H6 +KY,21,069,Fleming County,H1 +KY,21,071,Floyd County,H1 +KY,21,073,Franklin County,H1 +KY,21,075,Fulton County,H1 +KY,21,077,Gallatin County,H1 +KY,21,079,Garrard County,H1 +KY,21,081,Grant County,H1 +KY,21,083,Graves County,H1 +KY,21,085,Grayson County,H1 +KY,21,087,Green County,H1 +KY,21,089,Greenup County,H1 +KY,21,091,Hancock County,H1 +KY,21,093,Hardin County,H1 +KY,21,095,Harlan County,H1 +KY,21,097,Harrison County,H1 +KY,21,099,Hart County,H1 +KY,21,101,Henderson County,H1 +KY,21,103,Henry County,H1 +KY,21,105,Hickman County,H1 +KY,21,107,Hopkins County,H1 +KY,21,109,Jackson County,H1 +KY,21,111,Jefferson County,H1 +KY,21,113,Jessamine County,H1 +KY,21,115,Johnson County,H1 +KY,21,117,Kenton County,H1 +KY,21,119,Knott County,H1 +KY,21,121,Knox County,H1 +KY,21,123,Larue County,H1 +KY,21,125,Laurel County,H1 +KY,21,127,Lawrence County,H1 +KY,21,129,Lee County,H1 +KY,21,131,Leslie County,H1 +KY,21,133,Letcher County,H1 +KY,21,135,Lewis County,H1 +KY,21,137,Lincoln County,H1 +KY,21,139,Livingston County,H1 +KY,21,141,Logan County,H1 +KY,21,143,Lyon County,H1 +KY,21,145,McCracken County,H1 +KY,21,147,McCreary County,H1 +KY,21,149,McLean County,H1 +KY,21,151,Madison County,H1 +KY,21,153,Magoffin County,H1 +KY,21,155,Marion County,H1 +KY,21,157,Marshall County,H1 +KY,21,159,Martin County,H1 +KY,21,161,Mason County,H1 +KY,21,163,Meade County,H1 +KY,21,165,Menifee County,H1 +KY,21,167,Mercer County,H1 +KY,21,169,Metcalfe County,H1 +KY,21,171,Monroe County,H1 +KY,21,173,Montgomery County,H1 +KY,21,175,Morgan County,H1 +KY,21,177,Muhlenberg County,H1 +KY,21,179,Nelson County,H1 +KY,21,181,Nicholas County,H1 +KY,21,183,Ohio County,H1 +KY,21,185,Oldham County,H1 +KY,21,187,Owen County,H1 +KY,21,189,Owsley County,H1 +KY,21,191,Pendleton County,H1 +KY,21,193,Perry County,H1 +KY,21,195,Pike County,H1 +KY,21,197,Powell County,H1 +KY,21,199,Pulaski County,H1 +KY,21,201,Robertson County,H1 +KY,21,203,Rockcastle County,H1 +KY,21,205,Rowan County,H1 +KY,21,207,Russell County,H1 +KY,21,209,Scott County,H1 +KY,21,211,Shelby County,H1 +KY,21,213,Simpson County,H1 +KY,21,215,Spencer County,H1 +KY,21,217,Taylor County,H1 +KY,21,219,Todd County,H1 +KY,21,221,Trigg County,H1 +KY,21,223,Trimble County,H1 +KY,21,225,Union County,H1 +KY,21,227,Warren County,H1 +KY,21,229,Washington County,H1 +KY,21,231,Wayne County,H1 +KY,21,233,Webster County,H1 +KY,21,235,Whitley County,H1 +KY,21,237,Wolfe County,H1 +KY,21,239,Woodford County,H1 +LA,22,001,Acadia Parish,H1 +LA,22,003,Allen Parish,H1 +LA,22,005,Ascension Parish,H1 +LA,22,007,Assumption Parish,H1 +LA,22,009,Avoyelles Parish,H1 +LA,22,011,Beauregard Parish,H1 +LA,22,013,Bienville Parish,H1 +LA,22,015,Bossier Parish,H1 +LA,22,017,Caddo Parish,H1 +LA,22,019,Calcasieu Parish,H1 +LA,22,021,Caldwell Parish,H1 +LA,22,023,Cameron Parish,H1 +LA,22,025,Catahoula Parish,H1 +LA,22,027,Claiborne Parish,H1 +LA,22,029,Concordia Parish,H1 +LA,22,031,De Soto Parish,H1 +LA,22,033,East Baton Rouge Parish,H1 +LA,22,035,East Carroll Parish,H1 +LA,22,037,East Feliciana Parish,H1 +LA,22,039,Evangeline Parish,H1 +LA,22,041,Franklin Parish,H1 +LA,22,043,Grant Parish,H1 +LA,22,045,Iberia Parish,H1 +LA,22,047,Iberville Parish,H1 +LA,22,049,Jackson Parish,H1 +LA,22,051,Jefferson Parish,H1 +LA,22,053,Jefferson Davis Parish,H1 +LA,22,055,Lafayette Parish,H1 +LA,22,057,Lafourche Parish,H1 +LA,22,059,La Salle Parish,H1 +LA,22,061,Lincoln Parish,H1 +LA,22,063,Livingston Parish,H1 +LA,22,065,Madison Parish,H1 +LA,22,067,Morehouse Parish,H1 +LA,22,069,Natchitoches Parish,H1 +LA,22,071,Orleans Parish,H6 +LA,22,073,Ouachita Parish,H1 +LA,22,075,Plaquemines Parish,H1 +LA,22,077,Pointe Coupee Parish,H1 +LA,22,079,Rapides Parish,H1 +LA,22,081,Red River Parish,H1 +LA,22,083,Richland Parish,H1 +LA,22,085,Sabine Parish,H1 +LA,22,087,St. Bernard Parish,H1 +LA,22,089,St. Charles Parish,H1 +LA,22,091,St. Helena Parish,H1 +LA,22,093,St. James Parish,H1 +LA,22,095,St. John the Baptist Parish,H1 +LA,22,097,St. Landry Parish,H1 +LA,22,099,St. Martin Parish,H1 +LA,22,101,St. Mary Parish,H1 +LA,22,103,St. Tammany Parish,H1 +LA,22,105,Tangipahoa Parish,H1 +LA,22,107,Tensas Parish,H1 +LA,22,109,Terrebonne Parish,H1 +LA,22,111,Union Parish,H1 +LA,22,113,Vermilion Parish,H1 +LA,22,115,Vernon Parish,H1 +LA,22,117,Washington Parish,H1 +LA,22,119,Webster Parish,H1 +LA,22,121,West Baton Rouge Parish,H1 +LA,22,123,West Carroll Parish,H1 +LA,22,125,West Feliciana Parish,H1 +LA,22,127,Winn Parish,H1 +ME,23,001,Androscoggin County,H1 +ME,23,003,Aroostook County,H1 +ME,23,005,Cumberland County,H1 +ME,23,007,Franklin County,H1 +ME,23,009,Hancock County,H1 +ME,23,011,Kennebec County,H1 +ME,23,013,Knox County,H1 +ME,23,015,Lincoln County,H1 +ME,23,017,Oxford County,H1 +ME,23,019,Penobscot County,H1 +ME,23,021,Piscataquis County,H1 +ME,23,023,Sagadahoc County,H1 +ME,23,025,Somerset County,H1 +ME,23,027,Waldo County,H1 +ME,23,029,Washington County,H1 +ME,23,031,York County,H1 +MD,24,001,Allegany County,H1 +MD,24,003,Anne Arundel County,H1 +MD,24,005,Baltimore County,H1 +MD,24,009,Calvert County,H1 +MD,24,011,Caroline County,H1 +MD,24,013,Carroll County,H1 +MD,24,015,Cecil County,H1 +MD,24,017,Charles County,H1 +MD,24,019,Dorchester County,H1 +MD,24,021,Frederick County,H1 +MD,24,023,Garrett County,H1 +MD,24,025,Harford County,H1 +MD,24,027,Howard County,H1 +MD,24,029,Kent County,H1 +MD,24,031,Montgomery County,H1 +MD,24,033,Prince George's County,H1 +MD,24,035,Queen Anne's County,H1 +MD,24,037,St. Mary's County,H1 +MD,24,039,Somerset County,H1 +MD,24,041,Talbot County,H1 +MD,24,043,Washington County,H1 +MD,24,045,Wicomico County,H1 +MD,24,047,Worcester County,H1 +MD,24,510,Baltimore city,C7 +MA,25,001,Barnstable County,H1 +MA,25,003,Berkshire County,H4 +MA,25,005,Bristol County,H1 +MA,25,007,Dukes County,H1 +MA,25,009,Essex County,H4 +MA,25,011,Franklin County,H4 +MA,25,013,Hampden County,H4 +MA,25,015,Hampshire County,H4 +MA,25,017,Middlesex County,H4 +MA,25,019,Nantucket County,H4 +MA,25,021,Norfolk County,H1 +MA,25,023,Plymouth County,H1 +MA,25,025,Suffolk County,H4 +MA,25,027,Worcester County,H4 +MI,26,001,Alcona County,H1 +MI,26,003,Alger County,H1 +MI,26,005,Allegan County,H1 +MI,26,007,Alpena County,H1 +MI,26,009,Antrim County,H1 +MI,26,011,Arenac County,H1 +MI,26,013,Baraga County,H1 +MI,26,015,Barry County,H1 +MI,26,017,Bay County,H1 +MI,26,019,Benzie County,H1 +MI,26,021,Berrien County,H1 +MI,26,023,Branch County,H1 +MI,26,025,Calhoun County,H1 +MI,26,027,Cass County,H1 +MI,26,029,Charlevoix County,H1 +MI,26,031,Cheboygan County,H1 +MI,26,033,Chippewa County,H1 +MI,26,035,Clare County,H1 +MI,26,037,Clinton County,H1 +MI,26,039,Crawford County,H1 +MI,26,041,Delta County,H1 +MI,26,043,Dickinson County,H1 +MI,26,045,Eaton County,H1 +MI,26,047,Emmet County,H1 +MI,26,049,Genesee County,H1 +MI,26,051,Gladwin County,H1 +MI,26,053,Gogebic County,H1 +MI,26,055,Grand Traverse County,H1 +MI,26,057,Gratiot County,H1 +MI,26,059,Hillsdale County,H1 +MI,26,061,Houghton County,H1 +MI,26,063,Huron County,H1 +MI,26,065,Ingham County,H1 +MI,26,067,Ionia County,H1 +MI,26,069,Iosco County,H1 +MI,26,071,Iron County,H1 +MI,26,073,Isabella County,H1 +MI,26,075,Jackson County,H1 +MI,26,077,Kalamazoo County,H1 +MI,26,079,Kalkaska County,H1 +MI,26,081,Kent County,H1 +MI,26,083,Keweenaw County,H1 +MI,26,085,Lake County,H1 +MI,26,087,Lapeer County,H1 +MI,26,089,Leelanau County,H1 +MI,26,091,Lenawee County,H1 +MI,26,093,Livingston County,H1 +MI,26,095,Luce County,H1 +MI,26,097,Mackinac County,H1 +MI,26,099,Macomb County,H1 +MI,26,101,Manistee County,H1 +MI,26,103,Marquette County,H1 +MI,26,105,Mason County,H1 +MI,26,107,Mecosta County,H1 +MI,26,109,Menominee County,H1 +MI,26,111,Midland County,H1 +MI,26,113,Missaukee County,H1 +MI,26,115,Monroe County,H1 +MI,26,117,Montcalm County,H1 +MI,26,119,Montmorency County,H1 +MI,26,121,Muskegon County,H1 +MI,26,123,Newaygo County,H1 +MI,26,125,Oakland County,H1 +MI,26,127,Oceana County,H1 +MI,26,129,Ogemaw County,H1 +MI,26,131,Ontonagon County,H1 +MI,26,133,Osceola County,H1 +MI,26,135,Oscoda County,H1 +MI,26,137,Otsego County,H1 +MI,26,139,Ottawa County,H1 +MI,26,141,Presque Isle County,H1 +MI,26,143,Roscommon County,H1 +MI,26,145,Saginaw County,H1 +MI,26,147,St. Clair County,H1 +MI,26,149,St. Joseph County,H1 +MI,26,151,Sanilac County,H1 +MI,26,153,Schoolcraft County,H1 +MI,26,155,Shiawassee County,H1 +MI,26,157,Tuscola County,H1 +MI,26,159,Van Buren County,H1 +MI,26,161,Washtenaw County,H1 +MI,26,163,Wayne County,H1 +MI,26,165,Wexford County,H1 +MN,27,001,Aitkin County,H1 +MN,27,003,Anoka County,H1 +MN,27,005,Becker County,H1 +MN,27,007,Beltrami County,H1 +MN,27,009,Benton County,H1 +MN,27,011,Big Stone County,H1 +MN,27,013,Blue Earth County,H1 +MN,27,015,Brown County,H1 +MN,27,017,Carlton County,H1 +MN,27,019,Carver County,H1 +MN,27,021,Cass County,H1 +MN,27,023,Chippewa County,H1 +MN,27,025,Chisago County,H1 +MN,27,027,Clay County,H1 +MN,27,029,Clearwater County,H1 +MN,27,031,Cook County,H1 +MN,27,033,Cottonwood County,H1 +MN,27,035,Crow Wing County,H1 +MN,27,037,Dakota County,H1 +MN,27,039,Dodge County,H1 +MN,27,041,Douglas County,H1 +MN,27,043,Faribault County,H1 +MN,27,045,Fillmore County,H1 +MN,27,047,Freeborn County,H1 +MN,27,049,Goodhue County,H1 +MN,27,051,Grant County,H1 +MN,27,053,Hennepin County,H1 +MN,27,055,Houston County,H1 +MN,27,057,Hubbard County,H1 +MN,27,059,Isanti County,H1 +MN,27,061,Itasca County,H1 +MN,27,063,Jackson County,H1 +MN,27,065,Kanabec County,H1 +MN,27,067,Kandiyohi County,H1 +MN,27,069,Kittson County,H1 +MN,27,071,Koochiching County,H1 +MN,27,073,Lac qui Parle County,H1 +MN,27,075,Lake County,H1 +MN,27,077,Lake of the Woods County,H1 +MN,27,079,Le Sueur County,H1 +MN,27,081,Lincoln County,H1 +MN,27,083,Lyon County,H1 +MN,27,085,McLeod County,H1 +MN,27,087,Mahnomen County,H1 +MN,27,089,Marshall County,H1 +MN,27,091,Martin County,H1 +MN,27,093,Meeker County,H1 +MN,27,095,Mille Lacs County,H1 +MN,27,097,Morrison County,H1 +MN,27,099,Mower County,H1 +MN,27,101,Murray County,H1 +MN,27,103,Nicollet County,H1 +MN,27,105,Nobles County,H1 +MN,27,107,Norman County,H1 +MN,27,109,Olmsted County,H1 +MN,27,111,Otter Tail County,H1 +MN,27,113,Pennington County,H1 +MN,27,115,Pine County,H1 +MN,27,117,Pipestone County,H1 +MN,27,119,Polk County,H1 +MN,27,121,Pope County,H1 +MN,27,123,Ramsey County,H1 +MN,27,125,Red Lake County,H1 +MN,27,127,Redwood County,H1 +MN,27,129,Renville County,H1 +MN,27,131,Rice County,H1 +MN,27,133,Rock County,H1 +MN,27,135,Roseau County,H1 +MN,27,137,St. Louis County,H1 +MN,27,139,Scott County,H1 +MN,27,141,Sherburne County,H1 +MN,27,143,Sibley County,H1 +MN,27,145,Stearns County,H1 +MN,27,147,Steele County,H1 +MN,27,149,Stevens County,H1 +MN,27,151,Swift County,H1 +MN,27,153,Todd County,H1 +MN,27,155,Traverse County,H1 +MN,27,157,Wabasha County,H1 +MN,27,159,Wadena County,H1 +MN,27,161,Waseca County,H1 +MN,27,163,Washington County,H1 +MN,27,165,Watonwan County,H1 +MN,27,167,Wilkin County,H1 +MN,27,169,Winona County,H1 +MN,27,171,Wright County,H1 +MN,27,173,Yellow Medicine County,H1 +MS,28,001,Adams County,H1 +MS,28,003,Alcorn County,H1 +MS,28,005,Amite County,H1 +MS,28,007,Attala County,H1 +MS,28,009,Benton County,H1 +MS,28,011,Bolivar County,H1 +MS,28,013,Calhoun County,H1 +MS,28,015,Carroll County,H1 +MS,28,017,Chickasaw County,H1 +MS,28,019,Choctaw County,H1 +MS,28,021,Claiborne County,H1 +MS,28,023,Clarke County,H1 +MS,28,025,Clay County,H1 +MS,28,027,Coahoma County,H1 +MS,28,029,Copiah County,H1 +MS,28,031,Covington County,H1 +MS,28,033,DeSoto County,H1 +MS,28,035,Forrest County,H1 +MS,28,037,Franklin County,H1 +MS,28,039,George County,H1 +MS,28,041,Greene County,H1 +MS,28,043,Grenada County,H1 +MS,28,045,Hancock County,H1 +MS,28,047,Harrison County,H1 +MS,28,049,Hinds County,H1 +MS,28,051,Holmes County,H1 +MS,28,053,Humphreys County,H1 +MS,28,055,Issaquena County,H1 +MS,28,057,Itawamba County,H1 +MS,28,059,Jackson County,H1 +MS,28,061,Jasper County,H1 +MS,28,063,Jefferson County,H1 +MS,28,065,Jefferson Davis County,H1 +MS,28,067,Jones County,H1 +MS,28,069,Kemper County,H1 +MS,28,071,Lafayette County,H1 +MS,28,073,Lamar County,H1 +MS,28,075,Lauderdale County,H1 +MS,28,077,Lawrence County,H1 +MS,28,079,Leake County,H1 +MS,28,081,Lee County,H1 +MS,28,083,Leflore County,H1 +MS,28,085,Lincoln County,H1 +MS,28,087,Lowndes County,H1 +MS,28,089,Madison County,H1 +MS,28,091,Marion County,H1 +MS,28,093,Marshall County,H1 +MS,28,095,Monroe County,H1 +MS,28,097,Montgomery County,H1 +MS,28,099,Neshoba County,H1 +MS,28,101,Newton County,H1 +MS,28,103,Noxubee County,H1 +MS,28,105,Oktibbeha County,H1 +MS,28,107,Panola County,H1 +MS,28,109,Pearl River County,H1 +MS,28,111,Perry County,H1 +MS,28,113,Pike County,H1 +MS,28,115,Pontotoc County,H1 +MS,28,117,Prentiss County,H1 +MS,28,119,Quitman County,H1 +MS,28,121,Rankin County,H1 +MS,28,123,Scott County,H1 +MS,28,125,Sharkey County,H1 +MS,28,127,Simpson County,H1 +MS,28,129,Smith County,H1 +MS,28,131,Stone County,H1 +MS,28,133,Sunflower County,H1 +MS,28,135,Tallahatchie County,H1 +MS,28,137,Tate County,H1 +MS,28,139,Tippah County,H1 +MS,28,141,Tishomingo County,H1 +MS,28,143,Tunica County,H1 +MS,28,145,Union County,H1 +MS,28,147,Walthall County,H1 +MS,28,149,Warren County,H1 +MS,28,151,Washington County,H1 +MS,28,153,Wayne County,H1 +MS,28,155,Webster County,H1 +MS,28,157,Wilkinson County,H1 +MS,28,159,Winston County,H1 +MS,28,161,Yalobusha County,H1 +MS,28,163,Yazoo County,H1 +MO,29,001,Adair County,H1 +MO,29,003,Andrew County,H1 +MO,29,005,Atchison County,H1 +MO,29,007,Audrain County,H1 +MO,29,009,Barry County,H1 +MO,29,011,Barton County,H1 +MO,29,013,Bates County,H1 +MO,29,015,Benton County,H1 +MO,29,017,Bollinger County,H1 +MO,29,019,Boone County,H1 +MO,29,021,Buchanan County,H1 +MO,29,023,Butler County,H1 +MO,29,025,Caldwell County,H1 +MO,29,027,Callaway County,H1 +MO,29,029,Camden County,H1 +MO,29,031,Cape Girardeau County,H1 +MO,29,033,Carroll County,H1 +MO,29,035,Carter County,H1 +MO,29,037,Cass County,H1 +MO,29,039,Cedar County,H1 +MO,29,041,Chariton County,H1 +MO,29,043,Christian County,H1 +MO,29,045,Clark County,H1 +MO,29,047,Clay County,H1 +MO,29,049,Clinton County,H1 +MO,29,051,Cole County,H1 +MO,29,053,Cooper County,H1 +MO,29,055,Crawford County,H1 +MO,29,057,Dade County,H1 +MO,29,059,Dallas County,H1 +MO,29,061,Daviess County,H1 +MO,29,063,DeKalb County,H1 +MO,29,065,Dent County,H1 +MO,29,067,Douglas County,H1 +MO,29,069,Dunklin County,H1 +MO,29,071,Franklin County,H1 +MO,29,073,Gasconade County,H1 +MO,29,075,Gentry County,H1 +MO,29,077,Greene County,H1 +MO,29,079,Grundy County,H1 +MO,29,081,Harrison County,H1 +MO,29,083,Henry County,H1 +MO,29,085,Hickory County,H1 +MO,29,087,Holt County,H1 +MO,29,089,Howard County,H1 +MO,29,091,Howell County,H1 +MO,29,093,Iron County,H1 +MO,29,095,Jackson County,H1 +MO,29,097,Jasper County,H1 +MO,29,099,Jefferson County,H1 +MO,29,101,Johnson County,H1 +MO,29,103,Knox County,H1 +MO,29,105,Laclede County,H1 +MO,29,107,Lafayette County,H1 +MO,29,109,Lawrence County,H1 +MO,29,111,Lewis County,H1 +MO,29,113,Lincoln County,H1 +MO,29,115,Linn County,H1 +MO,29,117,Livingston County,H1 +MO,29,119,McDonald County,H1 +MO,29,121,Macon County,H1 +MO,29,123,Madison County,H1 +MO,29,125,Maries County,H1 +MO,29,127,Marion County,H1 +MO,29,129,Mercer County,H1 +MO,29,131,Miller County,H1 +MO,29,133,Mississippi County,H1 +MO,29,135,Moniteau County,H1 +MO,29,137,Monroe County,H1 +MO,29,139,Montgomery County,H1 +MO,29,141,Morgan County,H1 +MO,29,143,New Madrid County,H1 +MO,29,145,Newton County,H1 +MO,29,147,Nodaway County,H1 +MO,29,149,Oregon County,H1 +MO,29,151,Osage County,H1 +MO,29,153,Ozark County,H1 +MO,29,155,Pemiscot County,H1 +MO,29,157,Perry County,H1 +MO,29,159,Pettis County,H1 +MO,29,161,Phelps County,H1 +MO,29,163,Pike County,H1 +MO,29,165,Platte County,H1 +MO,29,167,Polk County,H1 +MO,29,169,Pulaski County,H1 +MO,29,171,Putnam County,H1 +MO,29,173,Ralls County,H1 +MO,29,175,Randolph County,H1 +MO,29,177,Ray County,H1 +MO,29,179,Reynolds County,H1 +MO,29,181,Ripley County,H1 +MO,29,183,St. Charles County,H1 +MO,29,185,St. Clair County,H1 +MO,29,186,Ste. Genevieve County,H1 +MO,29,187,St. Francois County,H1 +MO,29,189,St. Louis County,H1 +MO,29,195,Saline County,H1 +MO,29,197,Schuyler County,H1 +MO,29,199,Scotland County,H1 +MO,29,201,Scott County,H1 +MO,29,203,Shannon County,H1 +MO,29,205,Shelby County,H1 +MO,29,207,Stoddard County,H1 +MO,29,209,Stone County,H1 +MO,29,211,Sullivan County,H1 +MO,29,213,Taney County,H1 +MO,29,215,Texas County,H1 +MO,29,217,Vernon County,H1 +MO,29,219,Warren County,H1 +MO,29,221,Washington County,H1 +MO,29,223,Wayne County,H1 +MO,29,225,Webster County,H1 +MO,29,227,Worth County,H1 +MO,29,229,Wright County,H1 +MO,29,510,St. Louis city,C7 +MT,30,001,Beaverhead County,H1 +MT,30,003,Big Horn County,H1 +MT,30,005,Blaine County,H1 +MT,30,007,Broadwater County,H1 +MT,30,009,Carbon County,H1 +MT,30,011,Carter County,H1 +MT,30,013,Cascade County,H1 +MT,30,015,Chouteau County,H1 +MT,30,017,Custer County,H1 +MT,30,019,Daniels County,H1 +MT,30,021,Dawson County,H1 +MT,30,023,Deer Lodge County,H6 +MT,30,025,Fallon County,H1 +MT,30,027,Fergus County,H1 +MT,30,029,Flathead County,H1 +MT,30,031,Gallatin County,H1 +MT,30,033,Garfield County,H1 +MT,30,035,Glacier County,H1 +MT,30,037,Golden Valley County,H1 +MT,30,039,Granite County,H1 +MT,30,041,Hill County,H1 +MT,30,043,Jefferson County,H1 +MT,30,045,Judith Basin County,H1 +MT,30,047,Lake County,H1 +MT,30,049,Lewis and Clark County,H1 +MT,30,051,Liberty County,H1 +MT,30,053,Lincoln County,H1 +MT,30,055,McCone County,H1 +MT,30,057,Madison County,H1 +MT,30,059,Meagher County,H1 +MT,30,061,Mineral County,H1 +MT,30,063,Missoula County,H1 +MT,30,065,Musselshell County,H1 +MT,30,067,Park County,H1 +MT,30,069,Petroleum County,H1 +MT,30,071,Phillips County,H1 +MT,30,073,Pondera County,H1 +MT,30,075,Powder River County,H1 +MT,30,077,Powell County,H1 +MT,30,079,Prairie County,H1 +MT,30,081,Ravalli County,H1 +MT,30,083,Richland County,H1 +MT,30,085,Roosevelt County,H1 +MT,30,087,Rosebud County,H1 +MT,30,089,Sanders County,H1 +MT,30,091,Sheridan County,H1 +MT,30,093,Silver Bow County,H6 +MT,30,095,Stillwater County,H1 +MT,30,097,Sweet Grass County,H1 +MT,30,099,Teton County,H1 +MT,30,101,Toole County,H1 +MT,30,103,Treasure County,H1 +MT,30,105,Valley County,H1 +MT,30,107,Wheatland County,H1 +MT,30,109,Wibaux County,H1 +MT,30,111,Yellowstone County,H1 +NE,31,001,Adams County,H1 +NE,31,003,Antelope County,H1 +NE,31,005,Arthur County,H1 +NE,31,007,Banner County,H1 +NE,31,009,Blaine County,H1 +NE,31,011,Boone County,H1 +NE,31,013,Box Butte County,H1 +NE,31,015,Boyd County,H1 +NE,31,017,Brown County,H1 +NE,31,019,Buffalo County,H1 +NE,31,021,Burt County,H1 +NE,31,023,Butler County,H1 +NE,31,025,Cass County,H1 +NE,31,027,Cedar County,H1 +NE,31,029,Chase County,H1 +NE,31,031,Cherry County,H1 +NE,31,033,Cheyenne County,H1 +NE,31,035,Clay County,H1 +NE,31,037,Colfax County,H1 +NE,31,039,Cuming County,H1 +NE,31,041,Custer County,H1 +NE,31,043,Dakota County,H1 +NE,31,045,Dawes County,H1 +NE,31,047,Dawson County,H1 +NE,31,049,Deuel County,H1 +NE,31,051,Dixon County,H1 +NE,31,053,Dodge County,H1 +NE,31,055,Douglas County,H1 +NE,31,057,Dundy County,H1 +NE,31,059,Fillmore County,H1 +NE,31,061,Franklin County,H1 +NE,31,063,Frontier County,H1 +NE,31,065,Furnas County,H1 +NE,31,067,Gage County,H1 +NE,31,069,Garden County,H1 +NE,31,071,Garfield County,H1 +NE,31,073,Gosper County,H1 +NE,31,075,Grant County,H1 +NE,31,077,Greeley County,H1 +NE,31,079,Hall County,H1 +NE,31,081,Hamilton County,H1 +NE,31,083,Harlan County,H1 +NE,31,085,Hayes County,H1 +NE,31,087,Hitchcock County,H1 +NE,31,089,Holt County,H1 +NE,31,091,Hooker County,H1 +NE,31,093,Howard County,H1 +NE,31,095,Jefferson County,H1 +NE,31,097,Johnson County,H1 +NE,31,099,Kearney County,H1 +NE,31,101,Keith County,H1 +NE,31,103,Keya Paha County,H1 +NE,31,105,Kimball County,H1 +NE,31,107,Knox County,H1 +NE,31,109,Lancaster County,H1 +NE,31,111,Lincoln County,H1 +NE,31,113,Logan County,H1 +NE,31,115,Loup County,H1 +NE,31,117,McPherson County,H1 +NE,31,119,Madison County,H1 +NE,31,121,Merrick County,H1 +NE,31,123,Morrill County,H1 +NE,31,125,Nance County,H1 +NE,31,127,Nemaha County,H1 +NE,31,129,Nuckolls County,H1 +NE,31,131,Otoe County,H1 +NE,31,133,Pawnee County,H1 +NE,31,135,Perkins County,H1 +NE,31,137,Phelps County,H1 +NE,31,139,Pierce County,H1 +NE,31,141,Platte County,H1 +NE,31,143,Polk County,H1 +NE,31,145,Red Willow County,H1 +NE,31,147,Richardson County,H1 +NE,31,149,Rock County,H1 +NE,31,151,Saline County,H1 +NE,31,153,Sarpy County,H1 +NE,31,155,Saunders County,H1 +NE,31,157,Scotts Bluff County,H1 +NE,31,159,Seward County,H1 +NE,31,161,Sheridan County,H1 +NE,31,163,Sherman County,H1 +NE,31,165,Sioux County,H1 +NE,31,167,Stanton County,H1 +NE,31,169,Thayer County,H1 +NE,31,171,Thomas County,H1 +NE,31,173,Thurston County,H1 +NE,31,175,Valley County,H1 +NE,31,177,Washington County,H1 +NE,31,179,Wayne County,H1 +NE,31,181,Webster County,H1 +NE,31,183,Wheeler County,H1 +NE,31,185,York County,H1 +NV,32,001,Churchill County,H1 +NV,32,003,Clark County,H1 +NV,32,005,Douglas County,H1 +NV,32,007,Elko County,H1 +NV,32,009,Esmeralda County,H1 +NV,32,011,Eureka County,H1 +NV,32,013,Humboldt County,H1 +NV,32,015,Lander County,H1 +NV,32,017,Lincoln County,H1 +NV,32,019,Lyon County,H1 +NV,32,021,Mineral County,H1 +NV,32,023,Nye County,H1 +NV,32,027,Pershing County,H1 +NV,32,029,Storey County,H1 +NV,32,031,Washoe County,H1 +NV,32,033,White Pine County,H1 +NV,32,510,Carson City,C7 +NH,33,001,Belknap County,H1 +NH,33,003,Carroll County,H1 +NH,33,005,Cheshire County,H1 +NH,33,007,Coos County,H1 +NH,33,009,Grafton County,H1 +NH,33,011,Hillsborough County,H1 +NH,33,013,Merrimack County,H1 +NH,33,015,Rockingham County,H1 +NH,33,017,Strafford County,H1 +NH,33,019,Sullivan County,H1 +NJ,34,001,Atlantic County,H1 +NJ,34,003,Bergen County,H1 +NJ,34,005,Burlington County,H1 +NJ,34,007,Camden County,H1 +NJ,34,009,Cape May County,H1 +NJ,34,011,Cumberland County,H1 +NJ,34,013,Essex County,H1 +NJ,34,015,Gloucester County,H1 +NJ,34,017,Hudson County,H1 +NJ,34,019,Hunterdon County,H1 +NJ,34,021,Mercer County,H1 +NJ,34,023,Middlesex County,H1 +NJ,34,025,Monmouth County,H1 +NJ,34,027,Morris County,H1 +NJ,34,029,Ocean County,H1 +NJ,34,031,Passaic County,H1 +NJ,34,033,Salem County,H1 +NJ,34,035,Somerset County,H1 +NJ,34,037,Sussex County,H1 +NJ,34,039,Union County,H1 +NJ,34,041,Warren County,H1 +NM,35,001,Bernalillo County,H1 +NM,35,003,Catron County,H1 +NM,35,005,Chaves County,H1 +NM,35,006,Cibola County,H1 +NM,35,007,Colfax County,H1 +NM,35,009,Curry County,H1 +NM,35,011,De Baca County,H1 +NM,35,013,Dona Ana County,H1 +NM,35,015,Eddy County,H1 +NM,35,017,Grant County,H1 +NM,35,019,Guadalupe County,H1 +NM,35,021,Harding County,H1 +NM,35,023,Hidalgo County,H1 +NM,35,025,Lea County,H1 +NM,35,027,Lincoln County,H1 +NM,35,028,Los Alamos County,H1 +NM,35,029,Luna County,H1 +NM,35,031,McKinley County,H1 +NM,35,033,Mora County,H1 +NM,35,035,Otero County,H1 +NM,35,037,Quay County,H1 +NM,35,039,Rio Arriba County,H1 +NM,35,041,Roosevelt County,H1 +NM,35,043,Sandoval County,H1 +NM,35,045,San Juan County,H1 +NM,35,047,San Miguel County,H1 +NM,35,049,Santa Fe County,H1 +NM,35,051,Sierra County,H1 +NM,35,053,Socorro County,H1 +NM,35,055,Taos County,H1 +NM,35,057,Torrance County,H1 +NM,35,059,Union County,H1 +NM,35,061,Valencia County,H1 +NY,36,001,Albany County,H1 +NY,36,003,Allegany County,H1 +NY,36,005,Bronx County,H6 +NY,36,007,Broome County,H1 +NY,36,009,Cattaraugus County,H1 +NY,36,011,Cayuga County,H1 +NY,36,013,Chautauqua County,H1 +NY,36,015,Chemung County,H1 +NY,36,017,Chenango County,H1 +NY,36,019,Clinton County,H1 +NY,36,021,Columbia County,H1 +NY,36,023,Cortland County,H1 +NY,36,025,Delaware County,H1 +NY,36,027,Dutchess County,H1 +NY,36,029,Erie County,H1 +NY,36,031,Essex County,H1 +NY,36,033,Franklin County,H1 +NY,36,035,Fulton County,H1 +NY,36,037,Genesee County,H1 +NY,36,039,Greene County,H1 +NY,36,041,Hamilton County,H1 +NY,36,043,Herkimer County,H1 +NY,36,045,Jefferson County,H1 +NY,36,047,Kings County,H6 +NY,36,049,Lewis County,H1 +NY,36,051,Livingston County,H1 +NY,36,053,Madison County,H1 +NY,36,055,Monroe County,H1 +NY,36,057,Montgomery County,H1 +NY,36,059,Nassau County,H1 +NY,36,061,New York County,H6 +NY,36,063,Niagara County,H1 +NY,36,065,Oneida County,H1 +NY,36,067,Onondaga County,H1 +NY,36,069,Ontario County,H1 +NY,36,071,Orange County,H1 +NY,36,073,Orleans County,H1 +NY,36,075,Oswego County,H1 +NY,36,077,Otsego County,H1 +NY,36,079,Putnam County,H1 +NY,36,081,Queens County,H6 +NY,36,083,Rensselaer County,H1 +NY,36,085,Richmond County,H6 +NY,36,087,Rockland County,H1 +NY,36,089,St. Lawrence County,H1 +NY,36,091,Saratoga County,H1 +NY,36,093,Schenectady County,H1 +NY,36,095,Schoharie County,H1 +NY,36,097,Schuyler County,H1 +NY,36,099,Seneca County,H1 +NY,36,101,Steuben County,H1 +NY,36,103,Suffolk County,H1 +NY,36,105,Sullivan County,H1 +NY,36,107,Tioga County,H1 +NY,36,109,Tompkins County,H1 +NY,36,111,Ulster County,H1 +NY,36,113,Warren County,H1 +NY,36,115,Washington County,H1 +NY,36,117,Wayne County,H1 +NY,36,119,Westchester County,H1 +NY,36,121,Wyoming County,H1 +NY,36,123,Yates County,H1 +NC,37,001,Alamance County,H1 +NC,37,003,Alexander County,H1 +NC,37,005,Alleghany County,H1 +NC,37,007,Anson County,H1 +NC,37,009,Ashe County,H1 +NC,37,011,Avery County,H1 +NC,37,013,Beaufort County,H1 +NC,37,015,Bertie County,H1 +NC,37,017,Bladen County,H1 +NC,37,019,Brunswick County,H1 +NC,37,021,Buncombe County,H1 +NC,37,023,Burke County,H1 +NC,37,025,Cabarrus County,H1 +NC,37,027,Caldwell County,H1 +NC,37,029,Camden County,H1 +NC,37,031,Carteret County,H1 +NC,37,033,Caswell County,H1 +NC,37,035,Catawba County,H1 +NC,37,037,Chatham County,H1 +NC,37,039,Cherokee County,H1 +NC,37,041,Chowan County,H1 +NC,37,043,Clay County,H1 +NC,37,045,Cleveland County,H1 +NC,37,047,Columbus County,H1 +NC,37,049,Craven County,H1 +NC,37,051,Cumberland County,H1 +NC,37,053,Currituck County,H1 +NC,37,055,Dare County,H1 +NC,37,057,Davidson County,H1 +NC,37,059,Davie County,H1 +NC,37,061,Duplin County,H1 +NC,37,063,Durham County,H1 +NC,37,065,Edgecombe County,H1 +NC,37,067,Forsyth County,H1 +NC,37,069,Franklin County,H1 +NC,37,071,Gaston County,H1 +NC,37,073,Gates County,H1 +NC,37,075,Graham County,H1 +NC,37,077,Granville County,H1 +NC,37,079,Greene County,H1 +NC,37,081,Guilford County,H1 +NC,37,083,Halifax County,H1 +NC,37,085,Harnett County,H1 +NC,37,087,Haywood County,H1 +NC,37,089,Henderson County,H1 +NC,37,091,Hertford County,H1 +NC,37,093,Hoke County,H1 +NC,37,095,Hyde County,H1 +NC,37,097,Iredell County,H1 +NC,37,099,Jackson County,H1 +NC,37,101,Johnston County,H1 +NC,37,103,Jones County,H1 +NC,37,105,Lee County,H1 +NC,37,107,Lenoir County,H1 +NC,37,109,Lincoln County,H1 +NC,37,111,McDowell County,H1 +NC,37,113,Macon County,H1 +NC,37,115,Madison County,H1 +NC,37,117,Martin County,H1 +NC,37,119,Mecklenburg County,H1 +NC,37,121,Mitchell County,H1 +NC,37,123,Montgomery County,H1 +NC,37,125,Moore County,H1 +NC,37,127,Nash County,H1 +NC,37,129,New Hanover County,H1 +NC,37,131,Northampton County,H1 +NC,37,133,Onslow County,H1 +NC,37,135,Orange County,H1 +NC,37,137,Pamlico County,H1 +NC,37,139,Pasquotank County,H1 +NC,37,141,Pender County,H1 +NC,37,143,Perquimans County,H1 +NC,37,145,Person County,H1 +NC,37,147,Pitt County,H1 +NC,37,149,Polk County,H1 +NC,37,151,Randolph County,H1 +NC,37,153,Richmond County,H1 +NC,37,155,Robeson County,H1 +NC,37,157,Rockingham County,H1 +NC,37,159,Rowan County,H1 +NC,37,161,Rutherford County,H1 +NC,37,163,Sampson County,H1 +NC,37,165,Scotland County,H1 +NC,37,167,Stanly County,H1 +NC,37,169,Stokes County,H1 +NC,37,171,Surry County,H1 +NC,37,173,Swain County,H1 +NC,37,175,Transylvania County,H1 +NC,37,177,Tyrrell County,H1 +NC,37,179,Union County,H1 +NC,37,181,Vance County,H1 +NC,37,183,Wake County,H1 +NC,37,185,Warren County,H1 +NC,37,187,Washington County,H1 +NC,37,189,Watauga County,H1 +NC,37,191,Wayne County,H1 +NC,37,193,Wilkes County,H1 +NC,37,195,Wilson County,H1 +NC,37,197,Yadkin County,H1 +NC,37,199,Yancey County,H1 +ND,38,001,Adams County,H1 +ND,38,003,Barnes County,H1 +ND,38,005,Benson County,H1 +ND,38,007,Billings County,H1 +ND,38,009,Bottineau County,H1 +ND,38,011,Bowman County,H1 +ND,38,013,Burke County,H1 +ND,38,015,Burleigh County,H1 +ND,38,017,Cass County,H1 +ND,38,019,Cavalier County,H1 +ND,38,021,Dickey County,H1 +ND,38,023,Divide County,H1 +ND,38,025,Dunn County,H1 +ND,38,027,Eddy County,H1 +ND,38,029,Emmons County,H1 +ND,38,031,Foster County,H1 +ND,38,033,Golden Valley County,H1 +ND,38,035,Grand Forks County,H1 +ND,38,037,Grant County,H1 +ND,38,039,Griggs County,H1 +ND,38,041,Hettinger County,H1 +ND,38,043,Kidder County,H1 +ND,38,045,LaMoure County,H1 +ND,38,047,Logan County,H1 +ND,38,049,McHenry County,H1 +ND,38,051,McIntosh County,H1 +ND,38,053,McKenzie County,H1 +ND,38,055,McLean County,H1 +ND,38,057,Mercer County,H1 +ND,38,059,Morton County,H1 +ND,38,061,Mountrail County,H1 +ND,38,063,Nelson County,H1 +ND,38,065,Oliver County,H1 +ND,38,067,Pembina County,H1 +ND,38,069,Pierce County,H1 +ND,38,071,Ramsey County,H1 +ND,38,073,Ransom County,H1 +ND,38,075,Renville County,H1 +ND,38,077,Richland County,H1 +ND,38,079,Rolette County,H1 +ND,38,081,Sargent County,H1 +ND,38,083,Sheridan County,H1 +ND,38,085,Sioux County,H1 +ND,38,087,Slope County,H1 +ND,38,089,Stark County,H1 +ND,38,091,Steele County,H1 +ND,38,093,Stutsman County,H1 +ND,38,095,Towner County,H1 +ND,38,097,Traill County,H1 +ND,38,099,Walsh County,H1 +ND,38,101,Ward County,H1 +ND,38,103,Wells County,H1 +ND,38,105,Williams County,H1 +OH,39,001,Adams County,H1 +OH,39,003,Allen County,H1 +OH,39,005,Ashland County,H1 +OH,39,007,Ashtabula County,H1 +OH,39,009,Athens County,H1 +OH,39,011,Auglaize County,H1 +OH,39,013,Belmont County,H1 +OH,39,015,Brown County,H1 +OH,39,017,Butler County,H1 +OH,39,019,Carroll County,H1 +OH,39,021,Champaign County,H1 +OH,39,023,Clark County,H1 +OH,39,025,Clermont County,H1 +OH,39,027,Clinton County,H1 +OH,39,029,Columbiana County,H1 +OH,39,031,Coshocton County,H1 +OH,39,033,Crawford County,H1 +OH,39,035,Cuyahoga County,H1 +OH,39,037,Darke County,H1 +OH,39,039,Defiance County,H1 +OH,39,041,Delaware County,H1 +OH,39,043,Erie County,H1 +OH,39,045,Fairfield County,H1 +OH,39,047,Fayette County,H1 +OH,39,049,Franklin County,H1 +OH,39,051,Fulton County,H1 +OH,39,053,Gallia County,H1 +OH,39,055,Geauga County,H1 +OH,39,057,Greene County,H1 +OH,39,059,Guernsey County,H1 +OH,39,061,Hamilton County,H1 +OH,39,063,Hancock County,H1 +OH,39,065,Hardin County,H1 +OH,39,067,Harrison County,H1 +OH,39,069,Henry County,H1 +OH,39,071,Highland County,H1 +OH,39,073,Hocking County,H1 +OH,39,075,Holmes County,H1 +OH,39,077,Huron County,H1 +OH,39,079,Jackson County,H1 +OH,39,081,Jefferson County,H1 +OH,39,083,Knox County,H1 +OH,39,085,Lake County,H1 +OH,39,087,Lawrence County,H1 +OH,39,089,Licking County,H1 +OH,39,091,Logan County,H1 +OH,39,093,Lorain County,H1 +OH,39,095,Lucas County,H1 +OH,39,097,Madison County,H1 +OH,39,099,Mahoning County,H1 +OH,39,101,Marion County,H1 +OH,39,103,Medina County,H1 +OH,39,105,Meigs County,H1 +OH,39,107,Mercer County,H1 +OH,39,109,Miami County,H1 +OH,39,111,Monroe County,H1 +OH,39,113,Montgomery County,H1 +OH,39,115,Morgan County,H1 +OH,39,117,Morrow County,H1 +OH,39,119,Muskingum County,H1 +OH,39,121,Noble County,H1 +OH,39,123,Ottawa County,H1 +OH,39,125,Paulding County,H1 +OH,39,127,Perry County,H1 +OH,39,129,Pickaway County,H1 +OH,39,131,Pike County,H1 +OH,39,133,Portage County,H1 +OH,39,135,Preble County,H1 +OH,39,137,Putnam County,H1 +OH,39,139,Richland County,H1 +OH,39,141,Ross County,H1 +OH,39,143,Sandusky County,H1 +OH,39,145,Scioto County,H1 +OH,39,147,Seneca County,H1 +OH,39,149,Shelby County,H1 +OH,39,151,Stark County,H1 +OH,39,153,Summit County,H1 +OH,39,155,Trumbull County,H1 +OH,39,157,Tuscarawas County,H1 +OH,39,159,Union County,H1 +OH,39,161,Van Wert County,H1 +OH,39,163,Vinton County,H1 +OH,39,165,Warren County,H1 +OH,39,167,Washington County,H1 +OH,39,169,Wayne County,H1 +OH,39,171,Williams County,H1 +OH,39,173,Wood County,H1 +OH,39,175,Wyandot County,H1 +OK,40,001,Adair County,H1 +OK,40,003,Alfalfa County,H1 +OK,40,005,Atoka County,H1 +OK,40,007,Beaver County,H1 +OK,40,009,Beckham County,H1 +OK,40,011,Blaine County,H1 +OK,40,013,Bryan County,H1 +OK,40,015,Caddo County,H1 +OK,40,017,Canadian County,H1 +OK,40,019,Carter County,H1 +OK,40,021,Cherokee County,H1 +OK,40,023,Choctaw County,H1 +OK,40,025,Cimarron County,H1 +OK,40,027,Cleveland County,H1 +OK,40,029,Coal County,H1 +OK,40,031,Comanche County,H1 +OK,40,033,Cotton County,H1 +OK,40,035,Craig County,H1 +OK,40,037,Creek County,H1 +OK,40,039,Custer County,H1 +OK,40,041,Delaware County,H1 +OK,40,043,Dewey County,H1 +OK,40,045,Ellis County,H1 +OK,40,047,Garfield County,H1 +OK,40,049,Garvin County,H1 +OK,40,051,Grady County,H1 +OK,40,053,Grant County,H1 +OK,40,055,Greer County,H1 +OK,40,057,Harmon County,H1 +OK,40,059,Harper County,H1 +OK,40,061,Haskell County,H1 +OK,40,063,Hughes County,H1 +OK,40,065,Jackson County,H1 +OK,40,067,Jefferson County,H1 +OK,40,069,Johnston County,H1 +OK,40,071,Kay County,H1 +OK,40,073,Kingfisher County,H1 +OK,40,075,Kiowa County,H1 +OK,40,077,Latimer County,H1 +OK,40,079,Le Flore County,H1 +OK,40,081,Lincoln County,H1 +OK,40,083,Logan County,H1 +OK,40,085,Love County,H1 +OK,40,087,McClain County,H1 +OK,40,089,McCurtain County,H1 +OK,40,091,McIntosh County,H1 +OK,40,093,Major County,H1 +OK,40,095,Marshall County,H1 +OK,40,097,Mayes County,H1 +OK,40,099,Murray County,H1 +OK,40,101,Muskogee County,H1 +OK,40,103,Noble County,H1 +OK,40,105,Nowata County,H1 +OK,40,107,Okfuskee County,H1 +OK,40,109,Oklahoma County,H1 +OK,40,111,Okmulgee County,H1 +OK,40,113,Osage County,H1 +OK,40,115,Ottawa County,H1 +OK,40,117,Pawnee County,H1 +OK,40,119,Payne County,H1 +OK,40,121,Pittsburg County,H1 +OK,40,123,Pontotoc County,H1 +OK,40,125,Pottawatomie County,H1 +OK,40,127,Pushmataha County,H1 +OK,40,129,Roger Mills County,H1 +OK,40,131,Rogers County,H1 +OK,40,133,Seminole County,H1 +OK,40,135,Sequoyah County,H1 +OK,40,137,Stephens County,H1 +OK,40,139,Texas County,H1 +OK,40,141,Tillman County,H1 +OK,40,143,Tulsa County,H1 +OK,40,145,Wagoner County,H1 +OK,40,147,Washington County,H1 +OK,40,149,Washita County,H1 +OK,40,151,Woods County,H1 +OK,40,153,Woodward County,H1 +OR,41,001,Baker County,H1 +OR,41,003,Benton County,H1 +OR,41,005,Clackamas County,H1 +OR,41,007,Clatsop County,H1 +OR,41,009,Columbia County,H1 +OR,41,011,Coos County,H1 +OR,41,013,Crook County,H1 +OR,41,015,Curry County,H1 +OR,41,017,Deschutes County,H1 +OR,41,019,Douglas County,H1 +OR,41,021,Gilliam County,H1 +OR,41,023,Grant County,H1 +OR,41,025,Harney County,H1 +OR,41,027,Hood River County,H1 +OR,41,029,Jackson County,H1 +OR,41,031,Jefferson County,H1 +OR,41,033,Josephine County,H1 +OR,41,035,Klamath County,H1 +OR,41,037,Lake County,H1 +OR,41,039,Lane County,H1 +OR,41,041,Lincoln County,H1 +OR,41,043,Linn County,H1 +OR,41,045,Malheur County,H1 +OR,41,047,Marion County,H1 +OR,41,049,Morrow County,H1 +OR,41,051,Multnomah County,H1 +OR,41,053,Polk County,H1 +OR,41,055,Sherman County,H1 +OR,41,057,Tillamook County,H1 +OR,41,059,Umatilla County,H1 +OR,41,061,Union County,H1 +OR,41,063,Wallowa County,H1 +OR,41,065,Wasco County,H1 +OR,41,067,Washington County,H1 +OR,41,069,Wheeler County,H1 +OR,41,071,Yamhill County,H1 +PA,42,001,Adams County,H1 +PA,42,003,Allegheny County,H1 +PA,42,005,Armstrong County,H1 +PA,42,007,Beaver County,H1 +PA,42,009,Bedford County,H1 +PA,42,011,Berks County,H1 +PA,42,013,Blair County,H1 +PA,42,015,Bradford County,H1 +PA,42,017,Bucks County,H1 +PA,42,019,Butler County,H1 +PA,42,021,Cambria County,H1 +PA,42,023,Cameron County,H1 +PA,42,025,Carbon County,H1 +PA,42,027,Centre County,H1 +PA,42,029,Chester County,H1 +PA,42,031,Clarion County,H1 +PA,42,033,Clearfield County,H1 +PA,42,035,Clinton County,H1 +PA,42,037,Columbia County,H1 +PA,42,039,Crawford County,H1 +PA,42,041,Cumberland County,H1 +PA,42,043,Dauphin County,H1 +PA,42,045,Delaware County,H1 +PA,42,047,Elk County,H1 +PA,42,049,Erie County,H1 +PA,42,051,Fayette County,H1 +PA,42,053,Forest County,H1 +PA,42,055,Franklin County,H1 +PA,42,057,Fulton County,H1 +PA,42,059,Greene County,H1 +PA,42,061,Huntingdon County,H1 +PA,42,063,Indiana County,H1 +PA,42,065,Jefferson County,H1 +PA,42,067,Juniata County,H1 +PA,42,069,Lackawanna County,H1 +PA,42,071,Lancaster County,H1 +PA,42,073,Lawrence County,H1 +PA,42,075,Lebanon County,H1 +PA,42,077,Lehigh County,H1 +PA,42,079,Luzerne County,H1 +PA,42,081,Lycoming County,H1 +PA,42,083,McKean County,H1 +PA,42,085,Mercer County,H1 +PA,42,087,Mifflin County,H1 +PA,42,089,Monroe County,H1 +PA,42,091,Montgomery County,H1 +PA,42,093,Montour County,H1 +PA,42,095,Northampton County,H1 +PA,42,097,Northumberland County,H1 +PA,42,099,Perry County,H1 +PA,42,101,Philadelphia County,H6 +PA,42,103,Pike County,H1 +PA,42,105,Potter County,H1 +PA,42,107,Schuylkill County,H1 +PA,42,109,Snyder County,H1 +PA,42,111,Somerset County,H1 +PA,42,113,Sullivan County,H1 +PA,42,115,Susquehanna County,H1 +PA,42,117,Tioga County,H1 +PA,42,119,Union County,H1 +PA,42,121,Venango County,H1 +PA,42,123,Warren County,H1 +PA,42,125,Washington County,H1 +PA,42,127,Wayne County,H1 +PA,42,129,Westmoreland County,H1 +PA,42,131,Wyoming County,H1 +PA,42,133,York County,H1 +RI,44,001,Bristol County,H4 +RI,44,003,Kent County,H4 +RI,44,005,Newport County,H4 +RI,44,007,Providence County,H4 +RI,44,009,Washington County,H4 +SC,45,001,Abbeville County,H1 +SC,45,003,Aiken County,H1 +SC,45,005,Allendale County,H1 +SC,45,007,Anderson County,H1 +SC,45,009,Bamberg County,H1 +SC,45,011,Barnwell County,H1 +SC,45,013,Beaufort County,H1 +SC,45,015,Berkeley County,H1 +SC,45,017,Calhoun County,H1 +SC,45,019,Charleston County,H1 +SC,45,021,Cherokee County,H1 +SC,45,023,Chester County,H1 +SC,45,025,Chesterfield County,H1 +SC,45,027,Clarendon County,H1 +SC,45,029,Colleton County,H1 +SC,45,031,Darlington County,H1 +SC,45,033,Dillon County,H1 +SC,45,035,Dorchester County,H1 +SC,45,037,Edgefield County,H1 +SC,45,039,Fairfield County,H1 +SC,45,041,Florence County,H1 +SC,45,043,Georgetown County,H1 +SC,45,045,Greenville County,H1 +SC,45,047,Greenwood County,H1 +SC,45,049,Hampton County,H1 +SC,45,051,Horry County,H1 +SC,45,053,Jasper County,H1 +SC,45,055,Kershaw County,H1 +SC,45,057,Lancaster County,H1 +SC,45,059,Laurens County,H1 +SC,45,061,Lee County,H1 +SC,45,063,Lexington County,H1 +SC,45,065,McCormick County,H1 +SC,45,067,Marion County,H1 +SC,45,069,Marlboro County,H1 +SC,45,071,Newberry County,H1 +SC,45,073,Oconee County,H1 +SC,45,075,Orangeburg County,H1 +SC,45,077,Pickens County,H1 +SC,45,079,Richland County,H1 +SC,45,081,Saluda County,H1 +SC,45,083,Spartanburg County,H1 +SC,45,085,Sumter County,H1 +SC,45,087,Union County,H1 +SC,45,089,Williamsburg County,H1 +SC,45,091,York County,H1 +SD,46,003,Aurora County,H1 +SD,46,005,Beadle County,H1 +SD,46,007,Bennett County,H1 +SD,46,009,Bon Homme County,H1 +SD,46,011,Brookings County,H1 +SD,46,013,Brown County,H1 +SD,46,015,Brule County,H1 +SD,46,017,Buffalo County,H1 +SD,46,019,Butte County,H1 +SD,46,021,Campbell County,H1 +SD,46,023,Charles Mix County,H1 +SD,46,025,Clark County,H1 +SD,46,027,Clay County,H1 +SD,46,029,Codington County,H1 +SD,46,031,Corson County,H1 +SD,46,033,Custer County,H1 +SD,46,035,Davison County,H1 +SD,46,037,Day County,H1 +SD,46,039,Deuel County,H1 +SD,46,041,Dewey County,H1 +SD,46,043,Douglas County,H1 +SD,46,045,Edmunds County,H1 +SD,46,047,Fall River County,H1 +SD,46,049,Faulk County,H1 +SD,46,051,Grant County,H1 +SD,46,053,Gregory County,H1 +SD,46,055,Haakon County,H1 +SD,46,057,Hamlin County,H1 +SD,46,059,Hand County,H1 +SD,46,061,Hanson County,H1 +SD,46,063,Harding County,H1 +SD,46,065,Hughes County,H1 +SD,46,067,Hutchinson County,H1 +SD,46,069,Hyde County,H1 +SD,46,071,Jackson County,H1 +SD,46,073,Jerauld County,H1 +SD,46,075,Jones County,H1 +SD,46,077,Kingsbury County,H1 +SD,46,079,Lake County,H1 +SD,46,081,Lawrence County,H1 +SD,46,083,Lincoln County,H1 +SD,46,085,Lyman County,H1 +SD,46,087,McCook County,H1 +SD,46,089,McPherson County,H1 +SD,46,091,Marshall County,H1 +SD,46,093,Meade County,H1 +SD,46,095,Mellette County,H1 +SD,46,097,Miner County,H1 +SD,46,099,Minnehaha County,H1 +SD,46,101,Moody County,H1 +SD,46,103,Pennington County,H1 +SD,46,105,Perkins County,H1 +SD,46,107,Potter County,H1 +SD,46,109,Roberts County,H1 +SD,46,111,Sanborn County,H1 +SD,46,113,Shannon County,H1 +SD,46,115,Spink County,H1 +SD,46,117,Stanley County,H1 +SD,46,119,Sully County,H1 +SD,46,121,Todd County,H1 +SD,46,123,Tripp County,H1 +SD,46,125,Turner County,H1 +SD,46,127,Union County,H1 +SD,46,129,Walworth County,H1 +SD,46,135,Yankton County,H1 +SD,46,137,Ziebach County,H1 +TN,47,001,Anderson County,H1 +TN,47,003,Bedford County,H1 +TN,47,005,Benton County,H1 +TN,47,007,Bledsoe County,H1 +TN,47,009,Blount County,H1 +TN,47,011,Bradley County,H1 +TN,47,013,Campbell County,H1 +TN,47,015,Cannon County,H1 +TN,47,017,Carroll County,H1 +TN,47,019,Carter County,H1 +TN,47,021,Cheatham County,H1 +TN,47,023,Chester County,H1 +TN,47,025,Claiborne County,H1 +TN,47,027,Clay County,H1 +TN,47,029,Cocke County,H1 +TN,47,031,Coffee County,H1 +TN,47,033,Crockett County,H1 +TN,47,035,Cumberland County,H1 +TN,47,037,Davidson County,H6 +TN,47,039,Decatur County,H1 +TN,47,041,DeKalb County,H1 +TN,47,043,Dickson County,H1 +TN,47,045,Dyer County,H1 +TN,47,047,Fayette County,H1 +TN,47,049,Fentress County,H1 +TN,47,051,Franklin County,H1 +TN,47,053,Gibson County,H1 +TN,47,055,Giles County,H1 +TN,47,057,Grainger County,H1 +TN,47,059,Greene County,H1 +TN,47,061,Grundy County,H1 +TN,47,063,Hamblen County,H1 +TN,47,065,Hamilton County,H1 +TN,47,067,Hancock County,H1 +TN,47,069,Hardeman County,H1 +TN,47,071,Hardin County,H1 +TN,47,073,Hawkins County,H1 +TN,47,075,Haywood County,H1 +TN,47,077,Henderson County,H1 +TN,47,079,Henry County,H1 +TN,47,081,Hickman County,H1 +TN,47,083,Houston County,H1 +TN,47,085,Humphreys County,H1 +TN,47,087,Jackson County,H1 +TN,47,089,Jefferson County,H1 +TN,47,091,Johnson County,H1 +TN,47,093,Knox County,H1 +TN,47,095,Lake County,H1 +TN,47,097,Lauderdale County,H1 +TN,47,099,Lawrence County,H1 +TN,47,101,Lewis County,H1 +TN,47,103,Lincoln County,H1 +TN,47,105,Loudon County,H1 +TN,47,107,McMinn County,H1 +TN,47,109,McNairy County,H1 +TN,47,111,Macon County,H1 +TN,47,113,Madison County,H1 +TN,47,115,Marion County,H1 +TN,47,117,Marshall County,H1 +TN,47,119,Maury County,H1 +TN,47,121,Meigs County,H1 +TN,47,123,Monroe County,H1 +TN,47,125,Montgomery County,H1 +TN,47,127,Moore County,H6 +TN,47,129,Morgan County,H1 +TN,47,131,Obion County,H1 +TN,47,133,Overton County,H1 +TN,47,135,Perry County,H1 +TN,47,137,Pickett County,H1 +TN,47,139,Polk County,H1 +TN,47,141,Putnam County,H1 +TN,47,143,Rhea County,H1 +TN,47,145,Roane County,H1 +TN,47,147,Robertson County,H1 +TN,47,149,Rutherford County,H1 +TN,47,151,Scott County,H1 +TN,47,153,Sequatchie County,H1 +TN,47,155,Sevier County,H1 +TN,47,157,Shelby County,H1 +TN,47,159,Smith County,H1 +TN,47,161,Stewart County,H1 +TN,47,163,Sullivan County,H1 +TN,47,165,Sumner County,H1 +TN,47,167,Tipton County,H1 +TN,47,169,Trousdale County,H6 +TN,47,171,Unicoi County,H1 +TN,47,173,Union County,H1 +TN,47,175,Van Buren County,H1 +TN,47,177,Warren County,H1 +TN,47,179,Washington County,H1 +TN,47,181,Wayne County,H1 +TN,47,183,Weakley County,H1 +TN,47,185,White County,H1 +TN,47,187,Williamson County,H1 +TN,47,189,Wilson County,H1 +TX,48,001,Anderson County,H1 +TX,48,003,Andrews County,H1 +TX,48,005,Angelina County,H1 +TX,48,007,Aransas County,H1 +TX,48,009,Archer County,H1 +TX,48,011,Armstrong County,H1 +TX,48,013,Atascosa County,H1 +TX,48,015,Austin County,H1 +TX,48,017,Bailey County,H1 +TX,48,019,Bandera County,H1 +TX,48,021,Bastrop County,H1 +TX,48,023,Baylor County,H1 +TX,48,025,Bee County,H1 +TX,48,027,Bell County,H1 +TX,48,029,Bexar County,H1 +TX,48,031,Blanco County,H1 +TX,48,033,Borden County,H1 +TX,48,035,Bosque County,H1 +TX,48,037,Bowie County,H1 +TX,48,039,Brazoria County,H1 +TX,48,041,Brazos County,H1 +TX,48,043,Brewster County,H1 +TX,48,045,Briscoe County,H1 +TX,48,047,Brooks County,H1 +TX,48,049,Brown County,H1 +TX,48,051,Burleson County,H1 +TX,48,053,Burnet County,H1 +TX,48,055,Caldwell County,H1 +TX,48,057,Calhoun County,H1 +TX,48,059,Callahan County,H1 +TX,48,061,Cameron County,H1 +TX,48,063,Camp County,H1 +TX,48,065,Carson County,H1 +TX,48,067,Cass County,H1 +TX,48,069,Castro County,H1 +TX,48,071,Chambers County,H1 +TX,48,073,Cherokee County,H1 +TX,48,075,Childress County,H1 +TX,48,077,Clay County,H1 +TX,48,079,Cochran County,H1 +TX,48,081,Coke County,H1 +TX,48,083,Coleman County,H1 +TX,48,085,Collin County,H1 +TX,48,087,Collingsworth County,H1 +TX,48,089,Colorado County,H1 +TX,48,091,Comal County,H1 +TX,48,093,Comanche County,H1 +TX,48,095,Concho County,H1 +TX,48,097,Cooke County,H1 +TX,48,099,Coryell County,H1 +TX,48,101,Cottle County,H1 +TX,48,103,Crane County,H1 +TX,48,105,Crockett County,H1 +TX,48,107,Crosby County,H1 +TX,48,109,Culberson County,H1 +TX,48,111,Dallam County,H1 +TX,48,113,Dallas County,H1 +TX,48,115,Dawson County,H1 +TX,48,117,Deaf Smith County,H1 +TX,48,119,Delta County,H1 +TX,48,121,Denton County,H1 +TX,48,123,DeWitt County,H1 +TX,48,125,Dickens County,H1 +TX,48,127,Dimmit County,H1 +TX,48,129,Donley County,H1 +TX,48,131,Duval County,H1 +TX,48,133,Eastland County,H1 +TX,48,135,Ector County,H1 +TX,48,137,Edwards County,H1 +TX,48,139,Ellis County,H1 +TX,48,141,El Paso County,H1 +TX,48,143,Erath County,H1 +TX,48,145,Falls County,H1 +TX,48,147,Fannin County,H1 +TX,48,149,Fayette County,H1 +TX,48,151,Fisher County,H1 +TX,48,153,Floyd County,H1 +TX,48,155,Foard County,H1 +TX,48,157,Fort Bend County,H1 +TX,48,159,Franklin County,H1 +TX,48,161,Freestone County,H1 +TX,48,163,Frio County,H1 +TX,48,165,Gaines County,H1 +TX,48,167,Galveston County,H1 +TX,48,169,Garza County,H1 +TX,48,171,Gillespie County,H1 +TX,48,173,Glasscock County,H1 +TX,48,175,Goliad County,H1 +TX,48,177,Gonzales County,H1 +TX,48,179,Gray County,H1 +TX,48,181,Grayson County,H1 +TX,48,183,Gregg County,H1 +TX,48,185,Grimes County,H1 +TX,48,187,Guadalupe County,H1 +TX,48,189,Hale County,H1 +TX,48,191,Hall County,H1 +TX,48,193,Hamilton County,H1 +TX,48,195,Hansford County,H1 +TX,48,197,Hardeman County,H1 +TX,48,199,Hardin County,H1 +TX,48,201,Harris County,H1 +TX,48,203,Harrison County,H1 +TX,48,205,Hartley County,H1 +TX,48,207,Haskell County,H1 +TX,48,209,Hays County,H1 +TX,48,211,Hemphill County,H1 +TX,48,213,Henderson County,H1 +TX,48,215,Hidalgo County,H1 +TX,48,217,Hill County,H1 +TX,48,219,Hockley County,H1 +TX,48,221,Hood County,H1 +TX,48,223,Hopkins County,H1 +TX,48,225,Houston County,H1 +TX,48,227,Howard County,H1 +TX,48,229,Hudspeth County,H1 +TX,48,231,Hunt County,H1 +TX,48,233,Hutchinson County,H1 +TX,48,235,Irion County,H1 +TX,48,237,Jack County,H1 +TX,48,239,Jackson County,H1 +TX,48,241,Jasper County,H1 +TX,48,243,Jeff Davis County,H1 +TX,48,245,Jefferson County,H1 +TX,48,247,Jim Hogg County,H1 +TX,48,249,Jim Wells County,H1 +TX,48,251,Johnson County,H1 +TX,48,253,Jones County,H1 +TX,48,255,Karnes County,H1 +TX,48,257,Kaufman County,H1 +TX,48,259,Kendall County,H1 +TX,48,261,Kenedy County,H1 +TX,48,263,Kent County,H1 +TX,48,265,Kerr County,H1 +TX,48,267,Kimble County,H1 +TX,48,269,King County,H1 +TX,48,271,Kinney County,H1 +TX,48,273,Kleberg County,H1 +TX,48,275,Knox County,H1 +TX,48,277,Lamar County,H1 +TX,48,279,Lamb County,H1 +TX,48,281,Lampasas County,H1 +TX,48,283,La Salle County,H1 +TX,48,285,Lavaca County,H1 +TX,48,287,Lee County,H1 +TX,48,289,Leon County,H1 +TX,48,291,Liberty County,H1 +TX,48,293,Limestone County,H1 +TX,48,295,Lipscomb County,H1 +TX,48,297,Live Oak County,H1 +TX,48,299,Llano County,H1 +TX,48,301,Loving County,H1 +TX,48,303,Lubbock County,H1 +TX,48,305,Lynn County,H1 +TX,48,307,McCulloch County,H1 +TX,48,309,McLennan County,H1 +TX,48,311,McMullen County,H1 +TX,48,313,Madison County,H1 +TX,48,315,Marion County,H1 +TX,48,317,Martin County,H1 +TX,48,319,Mason County,H1 +TX,48,321,Matagorda County,H1 +TX,48,323,Maverick County,H1 +TX,48,325,Medina County,H1 +TX,48,327,Menard County,H1 +TX,48,329,Midland County,H1 +TX,48,331,Milam County,H1 +TX,48,333,Mills County,H1 +TX,48,335,Mitchell County,H1 +TX,48,337,Montague County,H1 +TX,48,339,Montgomery County,H1 +TX,48,341,Moore County,H1 +TX,48,343,Morris County,H1 +TX,48,345,Motley County,H1 +TX,48,347,Nacogdoches County,H1 +TX,48,349,Navarro County,H1 +TX,48,351,Newton County,H1 +TX,48,353,Nolan County,H1 +TX,48,355,Nueces County,H1 +TX,48,357,Ochiltree County,H1 +TX,48,359,Oldham County,H1 +TX,48,361,Orange County,H1 +TX,48,363,Palo Pinto County,H1 +TX,48,365,Panola County,H1 +TX,48,367,Parker County,H1 +TX,48,369,Parmer County,H1 +TX,48,371,Pecos County,H1 +TX,48,373,Polk County,H1 +TX,48,375,Potter County,H1 +TX,48,377,Presidio County,H1 +TX,48,379,Rains County,H1 +TX,48,381,Randall County,H1 +TX,48,383,Reagan County,H1 +TX,48,385,Real County,H1 +TX,48,387,Red River County,H1 +TX,48,389,Reeves County,H1 +TX,48,391,Refugio County,H1 +TX,48,393,Roberts County,H1 +TX,48,395,Robertson County,H1 +TX,48,397,Rockwall County,H1 +TX,48,399,Runnels County,H1 +TX,48,401,Rusk County,H1 +TX,48,403,Sabine County,H1 +TX,48,405,San Augustine County,H1 +TX,48,407,San Jacinto County,H1 +TX,48,409,San Patricio County,H1 +TX,48,411,San Saba County,H1 +TX,48,413,Schleicher County,H1 +TX,48,415,Scurry County,H1 +TX,48,417,Shackelford County,H1 +TX,48,419,Shelby County,H1 +TX,48,421,Sherman County,H1 +TX,48,423,Smith County,H1 +TX,48,425,Somervell County,H1 +TX,48,427,Starr County,H1 +TX,48,429,Stephens County,H1 +TX,48,431,Sterling County,H1 +TX,48,433,Stonewall County,H1 +TX,48,435,Sutton County,H1 +TX,48,437,Swisher County,H1 +TX,48,439,Tarrant County,H1 +TX,48,441,Taylor County,H1 +TX,48,443,Terrell County,H1 +TX,48,445,Terry County,H1 +TX,48,447,Throckmorton County,H1 +TX,48,449,Titus County,H1 +TX,48,451,Tom Green County,H1 +TX,48,453,Travis County,H1 +TX,48,455,Trinity County,H1 +TX,48,457,Tyler County,H1 +TX,48,459,Upshur County,H1 +TX,48,461,Upton County,H1 +TX,48,463,Uvalde County,H1 +TX,48,465,Val Verde County,H1 +TX,48,467,Van Zandt County,H1 +TX,48,469,Victoria County,H1 +TX,48,471,Walker County,H1 +TX,48,473,Waller County,H1 +TX,48,475,Ward County,H1 +TX,48,477,Washington County,H1 +TX,48,479,Webb County,H1 +TX,48,481,Wharton County,H1 +TX,48,483,Wheeler County,H1 +TX,48,485,Wichita County,H1 +TX,48,487,Wilbarger County,H1 +TX,48,489,Willacy County,H1 +TX,48,491,Williamson County,H1 +TX,48,493,Wilson County,H1 +TX,48,495,Winkler County,H1 +TX,48,497,Wise County,H1 +TX,48,499,Wood County,H1 +TX,48,501,Yoakum County,H1 +TX,48,503,Young County,H1 +TX,48,505,Zapata County,H1 +TX,48,507,Zavala County,H1 +UT,49,001,Beaver County,H1 +UT,49,003,Box Elder County,H1 +UT,49,005,Cache County,H1 +UT,49,007,Carbon County,H1 +UT,49,009,Daggett County,H1 +UT,49,011,Davis County,H1 +UT,49,013,Duchesne County,H1 +UT,49,015,Emery County,H1 +UT,49,017,Garfield County,H1 +UT,49,019,Grand County,H1 +UT,49,021,Iron County,H1 +UT,49,023,Juab County,H1 +UT,49,025,Kane County,H1 +UT,49,027,Millard County,H1 +UT,49,029,Morgan County,H1 +UT,49,031,Piute County,H1 +UT,49,033,Rich County,H1 +UT,49,035,Salt Lake County,H1 +UT,49,037,San Juan County,H1 +UT,49,039,Sanpete County,H1 +UT,49,041,Sevier County,H1 +UT,49,043,Summit County,H1 +UT,49,045,Tooele County,H1 +UT,49,047,Uintah County,H1 +UT,49,049,Utah County,H1 +UT,49,051,Wasatch County,H1 +UT,49,053,Washington County,H1 +UT,49,055,Wayne County,H1 +UT,49,057,Weber County,H1 +VT,50,001,Addison County,H1 +VT,50,003,Bennington County,H1 +VT,50,005,Caledonia County,H1 +VT,50,007,Chittenden County,H1 +VT,50,009,Essex County,H1 +VT,50,011,Franklin County,H1 +VT,50,013,Grand Isle County,H1 +VT,50,015,Lamoille County,H1 +VT,50,017,Orange County,H1 +VT,50,019,Orleans County,H1 +VT,50,021,Rutland County,H1 +VT,50,023,Washington County,H1 +VT,50,025,Windham County,H1 +VT,50,027,Windsor County,H1 +VA,51,001,Accomack County,H1 +VA,51,003,Albemarle County,H1 +VA,51,005,Alleghany County,H1 +VA,51,007,Amelia County,H1 +VA,51,009,Amherst County,H1 +VA,51,011,Appomattox County,H1 +VA,51,013,Arlington County,H1 +VA,51,015,Augusta County,H1 +VA,51,017,Bath County,H1 +VA,51,019,Bedford County,H1 +VA,51,021,Bland County,H1 +VA,51,023,Botetourt County,H1 +VA,51,025,Brunswick County,H1 +VA,51,027,Buchanan County,H1 +VA,51,029,Buckingham County,H1 +VA,51,031,Campbell County,H1 +VA,51,033,Caroline County,H1 +VA,51,035,Carroll County,H1 +VA,51,036,Charles City County,H1 +VA,51,037,Charlotte County,H1 +VA,51,041,Chesterfield County,H1 +VA,51,043,Clarke County,H1 +VA,51,045,Craig County,H1 +VA,51,047,Culpeper County,H1 +VA,51,049,Cumberland County,H1 +VA,51,051,Dickenson County,H1 +VA,51,053,Dinwiddie County,H1 +VA,51,057,Essex County,H1 +VA,51,059,Fairfax County,H1 +VA,51,061,Fauquier County,H1 +VA,51,063,Floyd County,H1 +VA,51,065,Fluvanna County,H1 +VA,51,067,Franklin County,H1 +VA,51,069,Frederick County,H1 +VA,51,071,Giles County,H1 +VA,51,073,Gloucester County,H1 +VA,51,075,Goochland County,H1 +VA,51,077,Grayson County,H1 +VA,51,079,Greene County,H1 +VA,51,081,Greensville County,H1 +VA,51,083,Halifax County,H1 +VA,51,085,Hanover County,H1 +VA,51,087,Henrico County,H1 +VA,51,089,Henry County,H1 +VA,51,091,Highland County,H1 +VA,51,093,Isle of Wight County,H1 +VA,51,095,James City County,H1 +VA,51,097,King and Queen County,H1 +VA,51,099,King George County,H1 +VA,51,101,King William County,H1 +VA,51,103,Lancaster County,H1 +VA,51,105,Lee County,H1 +VA,51,107,Loudoun County,H1 +VA,51,109,Louisa County,H1 +VA,51,111,Lunenburg County,H1 +VA,51,113,Madison County,H1 +VA,51,115,Mathews County,H1 +VA,51,117,Mecklenburg County,H1 +VA,51,119,Middlesex County,H1 +VA,51,121,Montgomery County,H1 +VA,51,125,Nelson County,H1 +VA,51,127,New Kent County,H1 +VA,51,131,Northampton County,H1 +VA,51,133,Northumberland County,H1 +VA,51,135,Nottoway County,H1 +VA,51,137,Orange County,H1 +VA,51,139,Page County,H1 +VA,51,141,Patrick County,H1 +VA,51,143,Pittsylvania County,H1 +VA,51,145,Powhatan County,H1 +VA,51,147,Prince Edward County,H1 +VA,51,149,Prince George County,H1 +VA,51,153,Prince William County,H1 +VA,51,155,Pulaski County,H1 +VA,51,157,Rappahannock County,H1 +VA,51,159,Richmond County,H1 +VA,51,161,Roanoke County,H1 +VA,51,163,Rockbridge County,H1 +VA,51,165,Rockingham County,H1 +VA,51,167,Russell County,H1 +VA,51,169,Scott County,H1 +VA,51,171,Shenandoah County,H1 +VA,51,173,Smyth County,H1 +VA,51,175,Southampton County,H1 +VA,51,177,Spotsylvania County,H1 +VA,51,179,Stafford County,H1 +VA,51,181,Surry County,H1 +VA,51,183,Sussex County,H1 +VA,51,185,Tazewell County,H1 +VA,51,187,Warren County,H1 +VA,51,191,Washington County,H1 +VA,51,193,Westmoreland County,H1 +VA,51,195,Wise County,H1 +VA,51,197,Wythe County,H1 +VA,51,199,York County,H1 +VA,51,510,Alexandria city,C7 +VA,51,515,Bedford city,C7 +VA,51,520,Bristol city,C7 +VA,51,530,Buena Vista city,C7 +VA,51,540,Charlottesville city,C7 +VA,51,550,Chesapeake city,C7 +VA,51,570,Colonial Heights city,C7 +VA,51,580,Covington city,C7 +VA,51,590,Danville city,C7 +VA,51,595,Emporia city,C7 +VA,51,600,Fairfax city,C7 +VA,51,610,Falls Church city,C7 +VA,51,620,Franklin city,C7 +VA,51,630,Fredericksburg city,C7 +VA,51,640,Galax city,C7 +VA,51,650,Hampton city,C7 +VA,51,660,Harrisonburg city,C7 +VA,51,670,Hopewell city,C7 +VA,51,678,Lexington city,C7 +VA,51,680,Lynchburg city,C7 +VA,51,683,Manassas city,C7 +VA,51,685,Manassas Park city,C7 +VA,51,690,Martinsville city,C7 +VA,51,700,Newport News city,C7 +VA,51,710,Norfolk city,C7 +VA,51,720,Norton city,C7 +VA,51,730,Petersburg city,C7 +VA,51,735,Poquoson city,C7 +VA,51,740,Portsmouth city,C7 +VA,51,750,Radford city,C7 +VA,51,760,Richmond city,C7 +VA,51,770,Roanoke city,C7 +VA,51,775,Salem city,C7 +VA,51,790,Staunton city,C7 +VA,51,800,Suffolk city,C7 +VA,51,810,Virginia Beach city,C7 +VA,51,820,Waynesboro city,C7 +VA,51,830,Williamsburg city,C7 +VA,51,840,Winchester city,C7 +WA,53,001,Adams County,H1 +WA,53,003,Asotin County,H1 +WA,53,005,Benton County,H1 +WA,53,007,Chelan County,H1 +WA,53,009,Clallam County,H1 +WA,53,011,Clark County,H1 +WA,53,013,Columbia County,H1 +WA,53,015,Cowlitz County,H1 +WA,53,017,Douglas County,H1 +WA,53,019,Ferry County,H1 +WA,53,021,Franklin County,H1 +WA,53,023,Garfield County,H1 +WA,53,025,Grant County,H1 +WA,53,027,Grays Harbor County,H1 +WA,53,029,Island County,H1 +WA,53,031,Jefferson County,H1 +WA,53,033,King County,H1 +WA,53,035,Kitsap County,H1 +WA,53,037,Kittitas County,H1 +WA,53,039,Klickitat County,H1 +WA,53,041,Lewis County,H1 +WA,53,043,Lincoln County,H1 +WA,53,045,Mason County,H1 +WA,53,047,Okanogan County,H1 +WA,53,049,Pacific County,H1 +WA,53,051,Pend Oreille County,H1 +WA,53,053,Pierce County,H1 +WA,53,055,San Juan County,H1 +WA,53,057,Skagit County,H1 +WA,53,059,Skamania County,H1 +WA,53,061,Snohomish County,H1 +WA,53,063,Spokane County,H1 +WA,53,065,Stevens County,H1 +WA,53,067,Thurston County,H1 +WA,53,069,Wahkiakum County,H1 +WA,53,071,Walla Walla County,H1 +WA,53,073,Whatcom County,H1 +WA,53,075,Whitman County,H1 +WA,53,077,Yakima County,H1 +WV,54,001,Barbour County,H1 +WV,54,003,Berkeley County,H1 +WV,54,005,Boone County,H1 +WV,54,007,Braxton County,H1 +WV,54,009,Brooke County,H1 +WV,54,011,Cabell County,H1 +WV,54,013,Calhoun County,H1 +WV,54,015,Clay County,H1 +WV,54,017,Doddridge County,H1 +WV,54,019,Fayette County,H1 +WV,54,021,Gilmer County,H1 +WV,54,023,Grant County,H1 +WV,54,025,Greenbrier County,H1 +WV,54,027,Hampshire County,H1 +WV,54,029,Hancock County,H1 +WV,54,031,Hardy County,H1 +WV,54,033,Harrison County,H1 +WV,54,035,Jackson County,H1 +WV,54,037,Jefferson County,H1 +WV,54,039,Kanawha County,H1 +WV,54,041,Lewis County,H1 +WV,54,043,Lincoln County,H1 +WV,54,045,Logan County,H1 +WV,54,047,McDowell County,H1 +WV,54,049,Marion County,H1 +WV,54,051,Marshall County,H1 +WV,54,053,Mason County,H1 +WV,54,055,Mercer County,H1 +WV,54,057,Mineral County,H1 +WV,54,059,Mingo County,H1 +WV,54,061,Monongalia County,H1 +WV,54,063,Monroe County,H1 +WV,54,065,Morgan County,H1 +WV,54,067,Nicholas County,H1 +WV,54,069,Ohio County,H1 +WV,54,071,Pendleton County,H1 +WV,54,073,Pleasants County,H1 +WV,54,075,Pocahontas County,H1 +WV,54,077,Preston County,H1 +WV,54,079,Putnam County,H1 +WV,54,081,Raleigh County,H1 +WV,54,083,Randolph County,H1 +WV,54,085,Ritchie County,H1 +WV,54,087,Roane County,H1 +WV,54,089,Summers County,H1 +WV,54,091,Taylor County,H1 +WV,54,093,Tucker County,H1 +WV,54,095,Tyler County,H1 +WV,54,097,Upshur County,H1 +WV,54,099,Wayne County,H1 +WV,54,101,Webster County,H1 +WV,54,103,Wetzel County,H1 +WV,54,105,Wirt County,H1 +WV,54,107,Wood County,H1 +WV,54,109,Wyoming County,H1 +WI,55,001,Adams County,H1 +WI,55,003,Ashland County,H1 +WI,55,005,Barron County,H1 +WI,55,007,Bayfield County,H1 +WI,55,009,Brown County,H1 +WI,55,011,Buffalo County,H1 +WI,55,013,Burnett County,H1 +WI,55,015,Calumet County,H1 +WI,55,017,Chippewa County,H1 +WI,55,019,Clark County,H1 +WI,55,021,Columbia County,H1 +WI,55,023,Crawford County,H1 +WI,55,025,Dane County,H1 +WI,55,027,Dodge County,H1 +WI,55,029,Door County,H1 +WI,55,031,Douglas County,H1 +WI,55,033,Dunn County,H1 +WI,55,035,Eau Claire County,H1 +WI,55,037,Florence County,H1 +WI,55,039,Fond du Lac County,H1 +WI,55,041,Forest County,H1 +WI,55,043,Grant County,H1 +WI,55,045,Green County,H1 +WI,55,047,Green Lake County,H1 +WI,55,049,Iowa County,H1 +WI,55,051,Iron County,H1 +WI,55,053,Jackson County,H1 +WI,55,055,Jefferson County,H1 +WI,55,057,Juneau County,H1 +WI,55,059,Kenosha County,H1 +WI,55,061,Kewaunee County,H1 +WI,55,063,La Crosse County,H1 +WI,55,065,Lafayette County,H1 +WI,55,067,Langlade County,H1 +WI,55,069,Lincoln County,H1 +WI,55,071,Manitowoc County,H1 +WI,55,073,Marathon County,H1 +WI,55,075,Marinette County,H1 +WI,55,077,Marquette County,H1 +WI,55,078,Menominee County,H1 +WI,55,079,Milwaukee County,H1 +WI,55,081,Monroe County,H1 +WI,55,083,Oconto County,H1 +WI,55,085,Oneida County,H1 +WI,55,087,Outagamie County,H1 +WI,55,089,Ozaukee County,H1 +WI,55,091,Pepin County,H1 +WI,55,093,Pierce County,H1 +WI,55,095,Polk County,H1 +WI,55,097,Portage County,H1 +WI,55,099,Price County,H1 +WI,55,101,Racine County,H1 +WI,55,103,Richland County,H1 +WI,55,105,Rock County,H1 +WI,55,107,Rusk County,H1 +WI,55,109,St. Croix County,H1 +WI,55,111,Sauk County,H1 +WI,55,113,Sawyer County,H1 +WI,55,115,Shawano County,H1 +WI,55,117,Sheboygan County,H1 +WI,55,119,Taylor County,H1 +WI,55,121,Trempealeau County,H1 +WI,55,123,Vernon County,H1 +WI,55,125,Vilas County,H1 +WI,55,127,Walworth County,H1 +WI,55,129,Washburn County,H1 +WI,55,131,Washington County,H1 +WI,55,133,Waukesha County,H1 +WI,55,135,Waupaca County,H1 +WI,55,137,Waushara County,H1 +WI,55,139,Winnebago County,H1 +WI,55,141,Wood County,H1 +WY,56,001,Albany County,H1 +WY,56,003,Big Horn County,H1 +WY,56,005,Campbell County,H1 +WY,56,007,Carbon County,H1 +WY,56,009,Converse County,H1 +WY,56,011,Crook County,H1 +WY,56,013,Fremont County,H1 +WY,56,015,Goshen County,H1 +WY,56,017,Hot Springs County,H1 +WY,56,019,Johnson County,H1 +WY,56,021,Laramie County,H1 +WY,56,023,Lincoln County,H1 +WY,56,025,Natrona County,H1 +WY,56,027,Niobrara County,H1 +WY,56,029,Park County,H1 +WY,56,031,Platte County,H1 +WY,56,033,Sheridan County,H1 +WY,56,035,Sublette County,H1 +WY,56,037,Sweetwater County,H1 +WY,56,039,Teton County,H1 +WY,56,041,Uinta County,H1 +WY,56,043,Washakie County,H1 +WY,56,045,Weston County,H1 +AS,60,010,Eastern District,H1 +AS,60,020,Manu'a District,H1 +AS,60,030,Rose Island,H4 +AS,60,040,Swains Island,H4 +AS,60,050,Western District,H1 +GU,66,010,Guam,H4 +MP,69,085,Northern Islands Municipality,H1 +MP,69,100,Rota Municipality,H1 +MP,69,110,Saipan Municipality,H1 +MP,69,120,Tinian Municipality,H1 +PR,72,001,Adjuntas Municipio,H1 +PR,72,003,Aguada Municipio,H1 +PR,72,005,Aguadilla Municipio,H1 +PR,72,007,Aguas Buenas Municipio,H1 +PR,72,009,Aibonito Municipio,H1 +PR,72,011,Anasco Municipio,H1 +PR,72,013,Arecibo Municipio,H1 +PR,72,015,Arroyo Municipio,H1 +PR,72,017,Barceloneta Municipio,H1 +PR,72,019,Barranquitas Municipio,H1 +PR,72,021,Bayamon Municipio,H1 +PR,72,023,Cabo Rojo Municipio,H1 +PR,72,025,Caguas Municipio,H1 +PR,72,027,Camuy Municipio,H1 +PR,72,029,Canovanas Municipio,H1 +PR,72,031,Carolina Municipio,H1 +PR,72,033,Catano Municipio,H1 +PR,72,035,Cayey Municipio,H1 +PR,72,037,Ceiba Municipio,H1 +PR,72,039,Ciales Municipio,H1 +PR,72,041,Cidra Municipio,H1 +PR,72,043,Coamo Municipio,H1 +PR,72,045,Comerio Municipio,H1 +PR,72,047,Corozal Municipio,H1 +PR,72,049,Culebra Municipio,H1 +PR,72,051,Dorado Municipio,H1 +PR,72,053,Fajardo Municipio,H1 +PR,72,054,Florida Municipio,H1 +PR,72,055,Guanica Municipio,H1 +PR,72,057,Guayama Municipio,H1 +PR,72,059,Guayanilla Municipio,H1 +PR,72,061,Guaynabo Municipio,H1 +PR,72,063,Gurabo Municipio,H1 +PR,72,065,Hatillo Municipio,H1 +PR,72,067,Hormigueros Municipio,H1 +PR,72,069,Humacao Municipio,H1 +PR,72,071,Isabela Municipio,H1 +PR,72,073,Jayuya Municipio,H1 +PR,72,075,Juana Diaz Municipio,H1 +PR,72,077,Juncos Municipio,H1 +PR,72,079,Lajas Municipio,H1 +PR,72,081,Lares Municipio,H1 +PR,72,083,Las Marias Municipio,H1 +PR,72,085,Las Piedras Municipio,H1 +PR,72,087,Loiza Municipio,H1 +PR,72,089,Luquillo Municipio,H1 +PR,72,091,Manati Municipio,H1 +PR,72,093,Maricao Municipio,H1 +PR,72,095,Maunabo Municipio,H1 +PR,72,097,Mayaguez Municipio,H1 +PR,72,099,Moca Municipio,H1 +PR,72,101,Morovis Municipio,H1 +PR,72,103,Naguabo Municipio,H1 +PR,72,105,Naranjito Municipio,H1 +PR,72,107,Orocovis Municipio,H1 +PR,72,109,Patillas Municipio,H1 +PR,72,111,Penuelas Municipio,H1 +PR,72,113,Ponce Municipio,H1 +PR,72,115,Quebradillas Municipio,H1 +PR,72,117,Rincon Municipio,H1 +PR,72,119,Rio Grande Municipio,H1 +PR,72,121,Sabana Grande Municipio,H1 +PR,72,123,Salinas Municipio,H1 +PR,72,125,San German Municipio,H1 +PR,72,127,San Juan Municipio,H1 +PR,72,129,San Lorenzo Municipio,H1 +PR,72,131,San Sebastian Municipio,H1 +PR,72,133,Santa Isabel Municipio,H1 +PR,72,135,Toa Alta Municipio,H1 +PR,72,137,Toa Baja Municipio,H1 +PR,72,139,Trujillo Alto Municipio,H1 +PR,72,141,Utuado Municipio,H1 +PR,72,143,Vega Alta Municipio,H1 +PR,72,145,Vega Baja Municipio,H1 +PR,72,147,Vieques Municipio,H1 +PR,72,149,Villalba Municipio,H1 +PR,72,151,Yabucoa Municipio,H1 +PR,72,153,Yauco Municipio,H1 +UM,74,300,Midway Islands,H4 +VI,78,010,St. Croix Island,H4 +VI,78,020,St. John Island,H4 +VI,78,030,St. Thomas Island,H4 diff --git a/src/org/ohdsi/whiteRabbit/fakeDataGenerator/FakeDataGenerator.java b/src/org/ohdsi/whiteRabbit/fakeDataGenerator/FakeDataGenerator.java new file mode 100644 index 00000000..9de2f607 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/fakeDataGenerator/FakeDataGenerator.java @@ -0,0 +1,202 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.fakeDataGenerator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.ohdsi.databases.DbType; +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.whiteRabbit.DbSettings; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Database; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Field; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Table; +import org.ohdsi.whiteRabbit.utilities.ETLUtils; + +public class FakeDataGenerator { + + private RichConnection connection; + private DbType dbType; + + public static int ROWS_PER_TABLE = 1000; + + public static void main(String[] args) { + FakeDataGenerator fakeDataGenerator = new FakeDataGenerator(); + + DbSettings dbSettings = new DbSettings(); +// dbSettings.dataType = DbSettings.DATABASE; +// dbSettings.dbType = DbType.MYSQL; +// dbSettings.server = "127.0.0.1"; +// dbSettings.database = "fake_data"; +// dbSettings.user = "root"; +// dbSettings.password = "F1r3starter"; +// fakeDataGenerator.generateData(dbSettings, "S:/Data/THIN/ScanReport.xlsx",true); + + dbSettings.dataType = DbSettings.DATABASE; + dbSettings.dbType = DbType.MSSQL; + dbSettings.server = "RNDUSRDHIT03.jnj.com"; + dbSettings.database = "CDM_THIN"; + fakeDataGenerator.generateData(dbSettings, "S:/Data/THIN/ScanReport.xlsx",false); + } + + private void generateData(DbSettings dbSettings, String filename, boolean createDatabase) { + System.out.println("Loading scan report from " + filename); + Database database = Database.generateModelFromScanReport(filename); + + dbType = dbSettings.dbType; + if (createDatabase && ETLUtils.databaseAlreadyExists(dbSettings)) + return; + connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + if (createDatabase) + connection.execute("CREATE DATABASE IF NOT EXISTS `" + dbSettings.database + "`"); + connection.use(dbSettings.database); + + for (Table table : database.getTables()) { + System.out.println("Generating table " + table.getName()); + createTable(table); + populateTable(table); + } + + connection.close(); + } + + private void populateTable(Table table) { + String[] fieldNames = new String[table.getFields().size()]; + ValueGenerator[] valueGenerators = new ValueGenerator[table.getFields().size()]; + for (int i = 0; i < table.getFields().size(); i++) { + Field field = table.getFields().get(i); + fieldNames[i] = field.getName(); + if (fieldNames[i].equals("data1")) + System.out.println("asdf"); + valueGenerators[i] = new ValueGenerator(field); + } + List rows = new ArrayList(); + for (int i = 0; i < ROWS_PER_TABLE; i++) { + Row row = new Row(); + for (int j = 0; j < fieldNames.length; j++) { + row.add(fieldNames[j], valueGenerators[j].generate()); + } + rows.add(row); + } + connection.insertIntoTable(rows.iterator(), table.getName(), false); + } + + private void createTable(Table table) { + StringBuilder sql = new StringBuilder(); + sql.append("CREATE TABLE " + table.getName() + " (\n"); + for (int i = 0; i < table.getFields().size(); i++) { + Field field = table.getFields().get(i); + sql.append(" " + field.getName() + " " + correctType(field)); + if (i < table.getFields().size() - 1) + sql.append(",\n"); + } + sql.append("\n);"); + connection.execute(sql.toString()); + } + + private String correctType(Field field) { + if (field.getType().equals("VarChar")) + return "VARCHAR(" + field.getMaxLength() + ")"; + else if (field.getType().equals("Integer")) + return "BIGINT"; + else if (field.getType().equals("Date")) + return "DATE"; + else if (field.getType().equals("Real")) + return "DOUBLE"; + else if (field.getType().equals("Empty")) + return "VARCHAR(255)"; + + return null; + } + + private class ValueGenerator { + + private String[] values; + private int[] cumulativeFrequency; + private int totalFrequency; + private String type; + + private boolean randomGenerate; + + private int length; + + private Random random = new Random(); + + public ValueGenerator(Field field) { + String[][] valueCounts = field.getValueCounts(); + type = field.getType(); + if (valueCounts[0][0].equals("List truncated...")) { + randomGenerate = true; + length = field.getMaxLength(); + } else { + randomGenerate = false; + int length = valueCounts.length; + if (valueCounts[length - 1][1].equals("")) // Last value could be "List truncated..." + length--; + + values = new String[length]; + cumulativeFrequency = new int[length]; + totalFrequency = 0; + for (int i = 0; i < length; i++) { + int frequency = (int) (Double.parseDouble(valueCounts[i][1])); + totalFrequency += frequency; + + values[i] = valueCounts[i][0]; + cumulativeFrequency[i] = totalFrequency; + } + } + } + + public String generate() { + if (randomGenerate) { // Random generate a string: + if (type.equals("VarChar")) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; i++) + sb.append(Character.toChars(65 + random.nextInt(26))); + return sb.toString(); + } else if (type.equals("Integer")) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; i++) + sb.append(Character.toChars(48 + random.nextInt(10))); + return sb.toString(); + } else if (type.equals("Date")) // todo: add code + return ""; + else if (type.equals("Real")) // todo: add code + return ""; + else if (type.equals("Empty")) + return ""; + else + return ""; + } else { // Sample from values: + int index = random.nextInt(totalFrequency); + int i = 0; + while (i < values.length - 1 && cumulativeFrequency[i] < index) + i++; + if (!type.equals("VarChar") && values[i].trim().length() == 0) + return ""; + return values[i]; + } + } + } + +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/Arrow.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/Arrow.java new file mode 100644 index 00000000..1c3c82dc --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/Arrow.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Polygon; + +public class Arrow implements MappingComponent { + + public static float thickness = 5; + public static int headThickness = 15; + public static Color color = new Color(128, 128, 128, 128); + private static BasicStroke dashed = new BasicStroke(2.0f, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 10.0f, + new float[] { 10.f }, + 0.0f); + + private int x1; + private int y1; + private int x2; + private int y2; + private LabeledRectangle source = null; + private LabeledRectangle target = null; + + private int width; + private int height; + + private Polygon polygon; + + private boolean isSelected = false; + private boolean isVisible = true; ; + + public Arrow(LabeledRectangle source) { + this.source = source; + } + + public Arrow(int x1, int y1, int x2, int y2) { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + + this.width = Math.abs(x1 - x2); + this.height = Math.abs(y1 - y2); + } + + public Arrow(LabeledRectangle source, LabeledRectangle target) { + this.source = source; + this.target = target; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public LabeledRectangle getSource() { + return source; + } + + public void setTargetPoint(Point point) { + if (point == null) { + x2 = source.getX() + source.getWidth() + Arrow.headThickness; + y2 = source.getY() + source.getHeight() / 2; + } else { + x2 = point.x; + y2 = point.y; + } + } + + public void paint(Graphics g) { + if (!isVisible) + return; + Graphics2D g2d = (Graphics2D) g; + + if (source != null) { + x1 = source.getX() + source.getWidth(); + y1 = source.getY() + source.getHeight() / 2; + width = Math.abs(x1 - x2); + height = Math.abs(y1 - y2); + } + if (target != null) { + x2 = target.getX(); + y2 = target.getY() + target.getHeight() / 2; + width = Math.abs(x1 - x2); + height = Math.abs(y1 - y2); + } + int nPoints = 25; + int[] xPoints = new int[nPoints * 2 + 3]; + int[] yPoints = new int[nPoints * 2 + 3]; + float widthMinHead = getWidth() - headThickness; + float stepSize = widthMinHead / (float) (nPoints - 1); + + for (int i = 0; i < nPoints; i++) { + float x = x1 + stepSize * i; + float y = (float) (y1 + (Math.cos(Math.PI * i / (float) nPoints) / 2d - 0.5) + * (y1 - y2)); + xPoints[i] = Math.round(x); + yPoints[i] = Math.round(y - thickness); + xPoints[nPoints * 2 + 3 - i - 1] = Math.round(x); + yPoints[nPoints * 2 + 3 - i - 1] = Math.round(y + thickness); + } + xPoints[nPoints] = x2 - headThickness; + yPoints[nPoints] = y2 - headThickness; + xPoints[nPoints + 1] = x2; + yPoints[nPoints + 1] = y2; + xPoints[nPoints + 2] = x2 - headThickness; + yPoints[nPoints + 2] = y2 + headThickness; + polygon = new Polygon(xPoints, yPoints, nPoints * 2 + 3); + + g2d.setColor(color); + g2d.fillPolygon(polygon); + + if (isSelected) { + g2d.setColor(Color.BLACK); + g2d.setStroke(dashed); + g2d.drawPolygon(polygon); + } + } + + public static void drawArrowHead(Graphics2D g2d, int x, int y) { + int nPoints = 3; + int[] xPoints = new int[nPoints]; + int[] yPoints = new int[nPoints]; + xPoints[0] = x - headThickness; + yPoints[0] = y - headThickness; + xPoints[1] = x; + yPoints[1] = y; + xPoints[2] = x - headThickness; + yPoints[2] = y + headThickness; + g2d.setColor(color); + g2d.fillPolygon(xPoints, yPoints, nPoints); + } + + public void setTarget(LabeledRectangle target) { + this.target = target; + } + + public LabeledRectangle getTarget() { + return target; + } + + public boolean isSelected() { + return isSelected; + } + + public void setSelected(boolean isSelected) { + this.isSelected = isSelected; + } + + public boolean contains(Point point) { + return polygon.contains(point); + } + + public void setVisible(boolean value) { + isVisible = value; + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/DetailsListener.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/DetailsListener.java new file mode 100644 index 00000000..bdbae74e --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/DetailsListener.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +public interface DetailsListener { + public void showDetails(Object object); +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/DetailsPanel.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/DetailsPanel.java new file mode 100644 index 00000000..4de36701 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/DetailsPanel.java @@ -0,0 +1,403 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridLayout; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.UIManager; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; + +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Field; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.ItemToItemMap; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Table; + +public class DetailsPanel extends JPanel implements DetailsListener { + + public static Font font = new Font("default", Font.PLAIN, 18); + + private static final long serialVersionUID = 4477553676983048468L; + private TablePanel tablePanel; + private FieldPanel fieldPanel; + private ItemToItemMapPanel itemToItemMapPanel; + private CardLayout cardLayout = new CardLayout(); + + public DetailsPanel() { + UIManager.put("Label.font", font); + + setLayout(cardLayout); + + tablePanel = new TablePanel(); + add(tablePanel, Table.class.getName()); + + fieldPanel = new FieldPanel(); + add(fieldPanel, Field.class.getName()); + + itemToItemMapPanel = new ItemToItemMapPanel(); + add(itemToItemMapPanel, ItemToItemMap.class.getName()); + + JPanel nullPanel = new JPanel(); + add(nullPanel, ""); + + cardLayout.show(this, ""); + } + + @Override + public void showDetails(Object object) { + if (object instanceof Table) { + tablePanel.showTable((Table) object); + cardLayout.show(this, Table.class.getName()); + } else if (object instanceof Field) { + fieldPanel.showField((Field) object); + cardLayout.show(this, Field.class.getName()); + } else if (object instanceof ItemToItemMap) { + itemToItemMapPanel.showItemToItemMap((ItemToItemMap) object); + cardLayout.show(this, ItemToItemMap.class.getName()); + } else + cardLayout.show(this, ""); + } + + private class TablePanel extends JPanel implements DocumentListener { + + private static final long serialVersionUID = -4393026616049677944L; + private Table table; + private JLabel nameLabel = new JLabel(""); + private JLabel rowCountLabel = new JLabel(""); + private SimpleTableModel fieldTable = new SimpleTableModel("Field", "Type"); + private JTextArea commentsArea = new JTextArea(); + + public TablePanel() { + setLayout(new BorderLayout()); + + JPanel generalInfoPanel = new JPanel(); + generalInfoPanel.setLayout(new GridLayout(0, 2)); + generalInfoPanel.setBorder(BorderFactory.createTitledBorder("General information")); + + generalInfoPanel.add(new JLabel("Table name: ")); + generalInfoPanel.add(nameLabel); + + generalInfoPanel.add(new JLabel("Number of rows: ")); + generalInfoPanel.add(rowCountLabel); + add(generalInfoPanel, BorderLayout.NORTH); + + JTable table = new JTable(fieldTable); + JScrollPane fieldListPanel = new JScrollPane(table); + table.setFont(font); + table.setRowHeight(24); + fieldListPanel.setBorder(BorderFactory.createTitledBorder("Fields")); + add(fieldListPanel, BorderLayout.CENTER); + + // JScrollPane commentsPanel = new JScrollPane(commentsArea); + // commentsArea.setFont(font); + // commentsArea.getDocument().addDocumentListener(this); + // commentsArea.setWrapStyleWord(true); + // commentsArea.setLineWrap(true); + // + // commentsPanel.setBorder(BorderFactory.createTitledBorder("Comments")); + // commentsPanel.setPreferredSize(new Dimension(100, 200)); + // add(commentsPanel, BorderLayout.SOUTH); + + } + + public void showTable(Table table) { + this.table = table; + nameLabel.setText(table.getName()); + DecimalFormat formatter = new DecimalFormat("#,###"); + rowCountLabel.setText(formatter.format(table.getRowCount())); + fieldTable.clear(); + for (Field field : table.getFields()) + fieldTable.add(field.getName(), field.getType()); + commentsArea.setText(table.getComment()); + } + + @Override + public void changedUpdate(DocumentEvent e) { + table.setComment(commentsArea.getText()); + } + + @Override + public void insertUpdate(DocumentEvent e) { + table.setComment(commentsArea.getText()); + } + + @Override + public void removeUpdate(DocumentEvent e) { + table.setComment(commentsArea.getText()); + } + } + + private class FieldPanel extends JPanel implements DocumentListener { + + private static final long serialVersionUID = -4393026616049677944L; + private JLabel nameLabel = new JLabel(""); + private JLabel rowCountLabel = new JLabel(""); + private SimpleTableModel valueTable = new SimpleTableModel("Value", "Frequency"); + private JTextArea commentsArea = new JTextArea(); + private Field field; + + public FieldPanel() { + setLayout(new BorderLayout()); + + JPanel generalInfoPanel = new JPanel(); + generalInfoPanel.setLayout(new GridLayout(0, 2)); + generalInfoPanel.setBorder(BorderFactory.createTitledBorder("General information")); + + generalInfoPanel.add(new JLabel("Field name: ")); + generalInfoPanel.add(nameLabel); + + generalInfoPanel.add(new JLabel("Field type: ")); + generalInfoPanel.add(rowCountLabel); + + add(generalInfoPanel, BorderLayout.NORTH); + + JTable table = new JTable(valueTable); + JScrollPane fieldListPanel = new JScrollPane(table); + table.setFont(font); + table.setRowHeight(24); + fieldListPanel.setBorder(BorderFactory.createTitledBorder("Fields")); + add(fieldListPanel, BorderLayout.CENTER); + + JScrollPane commentsPanel = new JScrollPane(commentsArea); + commentsArea.setFont(font); + commentsArea.getDocument().addDocumentListener(this); + commentsArea.setWrapStyleWord(true); + commentsArea.setLineWrap(true); + + commentsPanel.setBorder(BorderFactory.createTitledBorder("Comments")); + commentsPanel.setPreferredSize(new Dimension(100, 200)); + + add(commentsPanel, BorderLayout.SOUTH); + } + + public void showField(Field field) { + this.field = field; + nameLabel.setText(field.getName()); + rowCountLabel.setText(field.getType()); + valueTable.clear(); + if (field.getValueCounts() != null) { + DecimalFormat formatter = new DecimalFormat("#,###"); + for (String[] valueCount : field.getValueCounts()) { + String nr = valueCount[1]; + if (StringUtilities.isNumber(nr)) { + double number = Double.parseDouble(nr); + nr = formatter.format(number); + } + valueTable.add(valueCount[0], nr); + } + } + commentsArea.setText(field.getComment()); + } + + @Override + public void changedUpdate(DocumentEvent e) { + field.setComment(commentsArea.getText()); + } + + @Override + public void insertUpdate(DocumentEvent e) { + field.setComment(commentsArea.getText()); + } + + @Override + public void removeUpdate(DocumentEvent e) { + field.setComment(commentsArea.getText()); + } + + } + + private class ItemToItemMapPanel extends JPanel implements DocumentListener { + + private static final long serialVersionUID = -4393026616049677944L; + private JLabel sourceLabel = new JLabel(""); + private JLabel targetLabel = new JLabel(""); + private JTextArea logicArea = new JTextArea(); + private JTextArea commentsArea = new JTextArea(); + // private FlexTable testTable = new FlexTable(); + private ItemToItemMap itemToItemMap; + + public ItemToItemMapPanel() { + setLayout(new BorderLayout()); + + JPanel generalInfoPanel = new JPanel(); + generalInfoPanel.setLayout(new GridLayout(0, 2)); + generalInfoPanel.setBorder(BorderFactory.createTitledBorder("General information")); + + generalInfoPanel.add(new JLabel("Source: ")); + generalInfoPanel.add(sourceLabel); + + generalInfoPanel.add(new JLabel("Target: ")); + generalInfoPanel.add(targetLabel); + + add(generalInfoPanel, BorderLayout.NORTH); + + JScrollPane logicPanel = new JScrollPane(logicArea); + logicArea.setFont(font); + logicArea.getDocument().addDocumentListener(this); + logicArea.setWrapStyleWord(true); + logicArea.setLineWrap(true); + + logicPanel.setBorder(BorderFactory.createTitledBorder("Logic")); + logicPanel.setPreferredSize(new Dimension(100, 200)); + + add(logicPanel, BorderLayout.CENTER); + + JScrollPane commentsPanel = new JScrollPane(commentsArea); + commentsArea.setFont(font); + commentsArea.getDocument().addDocumentListener(this); + commentsArea.setWrapStyleWord(true); + commentsArea.setLineWrap(true); + + commentsPanel.setBorder(BorderFactory.createTitledBorder("Comments")); + commentsPanel.setPreferredSize(new Dimension(100, 200)); + + add(commentsPanel, BorderLayout.SOUTH); + + // testTable.setMinimumSize(new Dimension(200, 200)); + // JScrollPane testPanel = new JScrollPane(testTable); + // testPanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + // add(testPanel, BorderLayout.SOUTH); + } + + public void showItemToItemMap(ItemToItemMap itemToItemMap) { + this.itemToItemMap = itemToItemMap; + sourceLabel.setText(itemToItemMap.getSourceItem().toString()); + targetLabel.setText(itemToItemMap.getCdmItem().toString()); + logicArea.setText(itemToItemMap.getLogic()); + commentsArea.setText(itemToItemMap.getComment()); + } + + @Override + public void changedUpdate(DocumentEvent e) { + if (e.getDocument() == logicArea.getDocument()) + itemToItemMap.setLogic(logicArea.getText()); + else + itemToItemMap.setComment(commentsArea.getText()); + } + + @Override + public void insertUpdate(DocumentEvent e) { + if (e.getDocument() == logicArea.getDocument()) + itemToItemMap.setLogic(logicArea.getText()); + else + itemToItemMap.setComment(commentsArea.getText()); + } + + @Override + public void removeUpdate(DocumentEvent e) { + if (e.getDocument() == logicArea.getDocument()) + itemToItemMap.setLogic(logicArea.getText()); + else + itemToItemMap.setComment(commentsArea.getText()); + } + + } + + private class SimpleTableModel implements TableModel { + + private List listeners = new ArrayList(); + private List> data = new ArrayList>(); + private String[] columnNames; + + public void clear() { + data.clear(); + notifyListeners(); + } + + private void notifyListeners() { + for (TableModelListener listener : listeners) + listener.tableChanged(new TableModelEvent(this)); + } + + public void add(String... values) { + List row = new ArrayList(values.length); + for (int i = 0; i < values.length; i++) + row.add(values[i]); + data.add(row); + notifyListeners(); + } + + public SimpleTableModel(String... columnNames) { + this.columnNames = columnNames; + } + + @Override + public void addTableModelListener(TableModelListener l) { + listeners.add(l); + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public String getColumnName(int columnIndex) { + return columnNames[columnIndex]; + } + + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + return data.get(rowIndex).get(columnIndex); + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } + + @Override + public void removeTableModelListener(TableModelListener l) { + listeners.remove(l); + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + } + + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/ETLDocumentGenerator.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/ETLDocumentGenerator.java new file mode 100644 index 00000000..fb145cdf --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/ETLDocumentGenerator.java @@ -0,0 +1,242 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.zip.GZIPInputStream; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.xwpf.usermodel.BreakType; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.apache.poi.xwpf.usermodel.XWPFRun; +import org.apache.poi.xwpf.usermodel.XWPFTable; +import org.apache.poi.xwpf.usermodel.XWPFTableCell; +import org.apache.poi.xwpf.usermodel.XWPFTableRow; +import org.ohdsi.ooxml.CustomXWPFDocument; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.ETL; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Field; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.ItemToItemMap; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.MappableItem; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Mapping; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Table; + +public class ETLDocumentGenerator { + public static void main(String[] args) throws IOException, ClassNotFoundException { + FileInputStream fileOutputStream = new FileInputStream("C:/home/Research/EMIF WP12/HCUP//HCUP_final.etl"); + GZIPInputStream gzipOutputStream = new GZIPInputStream(fileOutputStream); + ObjectInputStream out = new ObjectInputStream(gzipOutputStream); + ETL etl = (ETL) out.readObject(); + out.close(); + generate(etl, "C:/Users/mschuemi/Desktop/test.docx"); + } + + public static void generate(ETL etl, String filename) { + try { + CustomXWPFDocument document = new CustomXWPFDocument(); + + addTableLevelSection(document, etl); + + for (Table cdmTable : etl.getCDMDatabase().getTables()) + addCDMTableSection(document, etl, cdmTable); + + addSourceTablesAppendix(document, etl); + + document.write(new FileOutputStream(new File(filename))); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InvalidFormatException e) { + e.printStackTrace(); + } + } + + private static void addSourceTablesAppendix(CustomXWPFDocument document, ETL etl) { + XWPFParagraph paragraph = document.createParagraph(); + XWPFRun run = paragraph.createRun(); + run.addBreak(BreakType.PAGE); + run.setText("Appendix: source tables"); + run.setFontSize(18); + + for (Table sourceTable : etl.getSourceDatabase().getTables()) { + paragraph = document.createParagraph(); + run = paragraph.createRun(); + run.setText("Table: " + sourceTable.getName()); + run.setFontSize(14); + + if (!sourceTable.getComment().equals("")) { + paragraph = document.createParagraph(); + run = paragraph.createRun(); + run.setText(sourceTable.getComment()); + } + + XWPFTable table = document.createTable(sourceTable.getFields().size() + 1, 4); + // table.setWidth(2000); + XWPFTableRow header = table.getRow(0); + setTextAndHeaderShading(header.getCell(0), "Field"); + setTextAndHeaderShading(header.getCell(1), "Type"); + setTextAndHeaderShading(header.getCell(2), "Most freq. value"); + setTextAndHeaderShading(header.getCell(3), "Comment"); + int rowNr = 1; + for (Field sourceField : sourceTable.getFields()) { + XWPFTableRow row = table.getRow(rowNr++); + row.getCell(0).setText(sourceField.getName()); + row.getCell(1).setText(sourceField.getType()); + if (sourceField.getValueCounts() != null) + row.getCell(2).setText(sourceField.getValueCounts()[0][0]); + row.getCell(3).setText(sourceField.getComment()); + } + + } + + run.setFontSize(18); + } + + private static void addCDMTableSection(CustomXWPFDocument document, ETL etl, Table cdmTable) throws InvalidFormatException, FileNotFoundException { + XWPFParagraph paragraph = document.createParagraph(); + XWPFRun run = paragraph.createRun(); + run.addBreak(BreakType.PAGE); + + run.setText("Table name: " + cdmTable.getName()); + run.setFontSize(18); + + if (!cdmTable.getComment().equals("")) { + paragraph = document.createParagraph(); + run = paragraph.createRun(); + run.setText(cdmTable.getComment()); + } + + for (ItemToItemMap tableToTableMap : etl.getTableToTableMapping().getSourceToCdmMaps()) + if (tableToTableMap.getCdmItem() == cdmTable) { + Table sourceTable = (Table) tableToTableMap.getSourceItem(); + Mapping fieldtoFieldMapping = etl.getFieldToFieldMapping(sourceTable, cdmTable); + + paragraph = document.createParagraph(); + run = paragraph.createRun(); + run.setText("Reading from " + tableToTableMap.getSourceItem()); + run.setFontSize(14); + + if (!tableToTableMap.getLogic().equals("")) { + paragraph = document.createParagraph(); + run = paragraph.createRun(); + run.setText(tableToTableMap.getLogic()); + } + + if (!tableToTableMap.getComment().equals("")) { + paragraph = document.createParagraph(); + run = paragraph.createRun(); + run.setText(tableToTableMap.getComment()); + } + + // Add picture of field to field mapping + MappingPanel mappingPanel = new MappingPanel(fieldtoFieldMapping); + mappingPanel.setShowOnlyConnectedItems(true); + int height = mappingPanel.getMinimumSize().height; + mappingPanel.setSize(800, height); + + BufferedImage im = new BufferedImage(800, height, BufferedImage.TYPE_INT_ARGB); + im.getGraphics().setColor(Color.WHITE); + im.getGraphics().fillRect(0, 0, im.getWidth(), im.getHeight()); + mappingPanel.paint(im.getGraphics()); + document.addPicture(im, 600, height * 6 / 8); + + // Add table of field to field mapping + XWPFTable table = document.createTable(fieldtoFieldMapping.getCdmItems().size() + 1, 4); + // table.setWidth(2000); + XWPFTableRow header = table.getRow(0); + setTextAndHeaderShading(header.getCell(0), "Destination Field"); + setTextAndHeaderShading(header.getCell(1), "Source Field"); + setTextAndHeaderShading(header.getCell(2), "Logic"); + setTextAndHeaderShading(header.getCell(3), "Comment"); + int rowNr = 1; + for (MappableItem cdmField : fieldtoFieldMapping.getCdmItems()) { + XWPFTableRow row = table.getRow(rowNr++); + row.getCell(0).setText(cdmField.getName()); + + StringBuilder source = new StringBuilder(); + StringBuilder logic = new StringBuilder(); + StringBuilder comment = new StringBuilder(); + for (ItemToItemMap fieldToFieldMap : fieldtoFieldMapping.getSourceToCdmMaps()) + if (fieldToFieldMap.getCdmItem() == cdmField) { + if (source.length() != 0) + source.append("\n"); + source.append(fieldToFieldMap.getSourceItem().getName()); + + if (logic.length() != 0) + logic.append("\n"); + logic.append(fieldToFieldMap.getLogic()); + + if (comment.length() != 0) + comment.append("\n"); + comment.append(fieldToFieldMap.getComment()); + } + for (Field field : cdmTable.getFields()) + if (field.getName().equals(cdmField.getName())) { + if (comment.length() != 0) + comment.append("\n"); + comment.append(field.getComment()); + } + + row.getCell(1).setText(source.toString()); + row.getCell(2).setText(logic.toString()); + row.getCell(3).setText(comment.toString()); + } + } + + } + + private static void setTextAndHeaderShading(XWPFTableCell cell, String text) { + cell.setText(text); + + cell.setColor("AAAAFF"); + // CTShd ctshd = cell.getCTTc().addNewTcPr().addNewShd(); + // ctshd.setColor("FFFFFF"); + // ctshd.setVal(STShd.CLEAR); + // ctshd.setFill("6666BB"); + + } + + private static void addTableLevelSection(CustomXWPFDocument document, ETL etl) throws InvalidFormatException, FileNotFoundException { + XWPFParagraph tmpParagraph = document.createParagraph(); + XWPFRun tmpRun = tmpParagraph.createRun(); + + tmpRun.setText("Source Data Mapping Approach"); + tmpRun.setFontSize(18); + + MappingPanel mappingPanel = new MappingPanel(etl.getTableToTableMapping()); + mappingPanel.setShowOnlyConnectedItems(true); + int height = mappingPanel.getMinimumSize().height; + mappingPanel.setSize(800, height); + + BufferedImage im = new BufferedImage(800, height, BufferedImage.TYPE_INT_ARGB); + im.getGraphics().setColor(Color.WHITE); + im.getGraphics().fillRect(0, 0, im.getWidth(), im.getHeight()); + mappingPanel.paint(im.getGraphics()); + document.addPicture(im, 600, height * 6 / 8); + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/FetchCDMModelFromServer.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/FetchCDMModelFromServer.java new file mode 100644 index 00000000..2faf11ab --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/FetchCDMModelFromServer.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +import org.ohdsi.databases.DbType; +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.utilities.files.WriteCSVFileWithHeader; + +public class FetchCDMModelFromServer { + + public static void main(String[] args) { + RichConnection connection = new RichConnection("127.0.0.1", null, "root", "F1r3starter", DbType.MYSQL); + connection.use("cdm_v4"); + + WriteCSVFileWithHeader out = new WriteCSVFileWithHeader("c:/temp/CDMV4Model.csv"); + String query = "SELECT table_name,column_name,is_nullable,column_type FROM information_schema.columns WHERE table_schema = 'cdm_v4';"; + for (Row row : connection.query(query)) + out.write(row); + out.close(); + + } + +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/FlexTable.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/FlexTable.java new file mode 100644 index 00000000..68436528 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/FlexTable.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.JTable; +import javax.swing.KeyStroke; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; + +public class FlexTable extends JTable implements ActionListener { + + private static final long serialVersionUID = 3017125804758269739L; + + private String rowstring, value; + private Clipboard system; + private StringSelection stsel; + private FlexTableModel model = new FlexTableModel(); + + public FlexTable() { + super(); + setModel(model); + model.addTableModelListener(this); + KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK, false); + KeyStroke paste = KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK, false); + registerKeyboardAction(this, "Copy", copy, JComponent.WHEN_FOCUSED); + registerKeyboardAction(this, "Paste", paste, JComponent.WHEN_FOCUSED); + system = Toolkit.getDefaultToolkit().getSystemClipboard(); + } + + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().compareTo("Copy") == 0) { + StringBuilder stringBuilder = new StringBuilder(); + int numcols = getSelectedColumnCount(); + int numrows = getSelectedRowCount(); + int[] rowsselected = getSelectedRows(); + int[] colsselected = getSelectedColumns(); + if (!((numrows - 1 == rowsselected[rowsselected.length - 1] - rowsselected[0] && numrows == rowsselected.length) && (numcols - 1 == colsselected[colsselected.length - 1] + - colsselected[0] && numcols == colsselected.length))) { + JOptionPane.showMessageDialog(null, "Invalid Copy Selection", "Invalid Copy Selection", JOptionPane.ERROR_MESSAGE); + return; + } + for (int i = 0; i < numrows; i++) { + for (int j = 0; j < numcols; j++) { + stringBuilder.append(getValueAt(rowsselected[i], colsselected[j])); + if (j < numcols - 1) + stringBuilder.append("\t"); + } + stringBuilder.append("\n"); + } + stsel = new StringSelection(stringBuilder.toString()); + system = Toolkit.getDefaultToolkit().getSystemClipboard(); + system.setContents(stsel, stsel); + } + if (e.getActionCommand().compareTo("Paste") == 0) { + int startRow = (getSelectedRows())[0]; + int startCol = (getSelectedColumns())[0]; + try { + String trstring = (String) (system.getContents(this).getTransferData(DataFlavor.stringFlavor)); + StringTokenizer tokenizer = new StringTokenizer(trstring, "\n"); + for (int i = 0; tokenizer.hasMoreTokens(); i++) { + rowstring = tokenizer.nextToken(); + StringTokenizer tokenizer2 = new StringTokenizer(rowstring, "\t"); + for (int j = 0; tokenizer2.hasMoreTokens(); j++) { + value = (String) tokenizer2.nextToken(); + setValueAt(value, startRow + i, startCol + j); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + private class FlexTableModel implements TableModel { + private List listeners = new ArrayList(); + private List> rows = new ArrayList>(); + private int columnCount = 0; + + private void notifyListeners() { + for (TableModelListener listener : listeners) + listener.tableChanged(new TableModelEvent(this, TableModelEvent.HEADER_ROW)); + } + + @Override + public void addTableModelListener(TableModelListener l) { + listeners.add(l); + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public int getColumnCount() { + return columnCount + 1; + } + + @Override + public String getColumnName(int columnIndex) { + return null; + } + + @Override + public int getRowCount() { + return rows.size() + 1; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + if (rowIndex >= rows.size()) + return ""; + List row = rows.get(rowIndex); + if (row.size() <= columnIndex) + return ""; + else + return row.get(columnIndex); + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return true; + } + + @Override + public void removeTableModelListener(TableModelListener l) { + listeners.remove(l); + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + for (int i = rows.size(); i <= rowIndex; i++) + rows.add(new ArrayList()); + List row = rows.get(rowIndex); + for (int i = row.size(); i <= columnIndex; i++) + row.add(""); + + row.set(columnIndex, aValue.toString()); + if (columnIndex >= columnCount) + columnCount = columnIndex + 1; + notifyListeners(); + } + + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/LabeledRectangle.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/LabeledRectangle.java new file mode 100644 index 00000000..b8fc6a8d --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/LabeledRectangle.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Stroke; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.event.ChangeListener; + +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.MappableItem; + +public class LabeledRectangle implements MappingComponent { + + public static int FONT_SIZE = 18; + + private static Stroke stroke = new BasicStroke(2); + private static BasicStroke dashed = new BasicStroke(2.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] { 10.f }, 0.0f); + private List changeListeners = new ArrayList(); + private int x; + private int y; + private int width; + private int height; + private MappableItem item; + private Color baseColor; + private Color transparentColor; + private boolean isVisible = true; + private boolean isSelected = false; + + public void addChangeListener(ChangeListener x) { + changeListeners.add(x); + } + + public void removeChangeListener(ChangeListener x) { + changeListeners.remove(x); + } + + public LabeledRectangle(int x, int y, int width, int height, MappableItem item, Color baseColor) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.item = item; + this.baseColor = baseColor; + this.transparentColor = new Color(baseColor.getRed(), baseColor.getGreen(), baseColor.getBlue(), 128); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public void setLocation(int x, int y) { + this.x = x; + this.y = y; + } + + public void paint(Graphics g) { + if (!isVisible) + return; + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(transparentColor); + g2d.fillRect(x, y, width, height); + if (isSelected) { + g2d.setColor(Color.BLACK); + g2d.setStroke(dashed); + } else { + g2d.setColor(baseColor); + g2d.setStroke(stroke); + } + g2d.drawRect(x, y, width, height); + g2d.setColor(Color.BLACK); + + g2d.setFont(new Font("default", Font.PLAIN, FONT_SIZE)); + FontMetrics fm = g2d.getFontMetrics(); + + Rectangle2D r = fm.getStringBounds(item.getName(), g2d); + if (r.getWidth() >= width) { + int breakPoint = 0; + int index = item.getName().indexOf('_'); + double midPoint = item.getName().length() / 2d; + while (index != -1) { + if (Math.abs(index - midPoint) < Math.abs(breakPoint - midPoint)) + breakPoint = index; + index = item.getName().indexOf('_', index + 1); + } + if (breakPoint == 0) { + int textX = (this.getWidth() - (int) r.getWidth()) / 2; + int textY = (this.getHeight() - (int) r.getHeight()) / 2 + fm.getAscent(); + g2d.drawString(item.getName(), x + textX, y + textY); + } + breakPoint++; + String line1 = item.getName().substring(0, breakPoint); + String line2 = item.getName().substring(breakPoint); + r = fm.getStringBounds(line1, g2d); + int textX = (this.getWidth() - (int) r.getWidth()) / 2; + int textY = (this.getHeight() / 2 - (int) r.getHeight()) / 2 + fm.getAscent(); + g2d.drawString(line1, x + textX, y + textY); + r = fm.getStringBounds(line2, g2d); + textX = (this.getWidth() - (int) r.getWidth()) / 2; + textY = (int) Math.round(this.getHeight() * 1.5 - (int) r.getHeight()) / 2 + fm.getAscent(); + g2d.drawString(line2, x + textX, y + textY); + } else { + int textX = (this.getWidth() - (int) r.getWidth()) / 2; + int textY = (this.getHeight() - (int) r.getHeight()) / 2 + fm.getAscent(); + g2d.drawString(item.getName(), x + textX, y + textY); + } + } + + public boolean contains(Point point) { + return (point.x >= x && point.x <= x + width && point.y >= y && point.y <= y + height); + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public MappableItem getItem() { + return item; + } + + public boolean isSelected() { + return isSelected; + } + + public void setSelected(boolean isSelected) { + this.isSelected = isSelected; + } + + public void setVisible(boolean value) { + isVisible = value; + } + +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/MappingComponent.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/MappingComponent.java new file mode 100644 index 00000000..290f1505 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/MappingComponent.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +import java.awt.Graphics; + +public interface MappingComponent { + + public void paint(Graphics g); +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/MappingPanel.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/MappingPanel.java new file mode 100644 index 00000000..0e97c7db --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/MappingPanel.java @@ -0,0 +1,601 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import javax.swing.JPanel; + +import org.ohdsi.utilities.collections.IntegerComparator; +import org.ohdsi.whiteRabbit.ObjectExchange; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.ItemToItemMap; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.MappableItem; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Mapping; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Table; + +public class MappingPanel extends JPanel implements MouseListener, MouseMotionListener, KeyListener { + + private static final long serialVersionUID = 4589294949568810155L; + + public static int ITEM_HEIGHT = 50; + public static int ITEM_WIDTH = 200; + public static int MARGIN = 10; + public static int HEADER_HEIGHT = 25; + public static int MIN_SPACE_BETWEEN_COLUMNS = 200; + public static int ARROW_START_WIDTH = 50; + public static int BORDER_HEIGHT = 25; + + private int sourceX = 10; + private int cdmX = 200; + + private Mapping mapping; + private List sourceComponents = new ArrayList(); + private List cdmComponents = new ArrayList(); + private List arrows = new ArrayList(); + private LabeledRectangle dragRectangle = null; + private LabeledRectangle selectedRectangle = null; + private Arrow dragArrow = null; + private Arrow zoomArrow = null; + private Arrow selectedArrow = null; + private LabeledRectangle dragArrowPreviousTarget = null; + private int dragOffsetY; + private int maxHeight = Integer.MAX_VALUE; + private boolean minimized = false; + private MappingPanel slaveMappingPanel; + private boolean showOnlyConnectedItems = false; + + private boolean showingArrowStarts = false; + + private DetailsListener detailsListener; + + public MappingPanel(Mapping mapping) { + super(); + this.mapping = mapping; + this.setFocusable(true); + addMouseListener(this); + addMouseMotionListener(this); + addKeyListener(this); + renderModel(); + } + + public void setMapping(Mapping mapping) { + maximize(); + this.mapping = mapping; + renderModel(); + } + + public void setSlaveMappingPanel(MappingPanel mappingPanel) { + this.slaveMappingPanel = mappingPanel; + } + + public void setShowOnlyConnectedItems(boolean value) { + showOnlyConnectedItems = value; + renderModel(); + } + + private void renderModel() { + sourceComponents.clear(); + cdmComponents.clear(); + arrows.clear(); + for (MappableItem item : mapping.getSourceItems()) + if (!showOnlyConnectedItems || isConnected(item)) { + LabeledRectangle component = new LabeledRectangle(0, 400, ITEM_WIDTH, ITEM_HEIGHT, item, new Color(255, 128, 0)); + sourceComponents.add(component); + } + for (MappableItem item : mapping.getCdmItems()) + if (!showOnlyConnectedItems || isConnected(item)) { + LabeledRectangle component = new LabeledRectangle(0, 400, ITEM_WIDTH, ITEM_HEIGHT, item, new Color(128, 128, 255)); + cdmComponents.add(component); + } + for (ItemToItemMap map : mapping.getSourceToCdmMaps()) { + Arrow component = new Arrow(getComponentWithItem(map.getSourceItem(), sourceComponents), getComponentWithItem(map.getCdmItem(), cdmComponents)); + arrows.add(component); + } + layoutItems(); + repaint(); + } + + private boolean isConnected(MappableItem item) { + for (ItemToItemMap map : mapping.getSourceToCdmMaps()) + if (map.getSourceItem() == item || map.getCdmItem() == item) + return true; + return false; + } + + private LabeledRectangle getComponentWithItem(MappableItem item, List components) { + for (LabeledRectangle component : components) + if (component.getItem().equals(item)) + return component; + return null; + } + + private void layoutItems() { + if (minimized) { // Only update x coordinate + for (LabeledRectangle cdmComponent : cdmComponents) + cdmComponent.setLocation(cdmX, cdmComponent.getY()); + } else { + int avoidY = Integer.MAX_VALUE; + if (dragRectangle != null && dragRectangle.getX() == sourceX) + avoidY = dragRectangle.getY(); + int y = HEADER_HEIGHT; + for (int i = 0; i < sourceComponents.size(); i++) { + LabeledRectangle item = sourceComponents.get(i); + if (y > avoidY - ITEM_HEIGHT && y <= avoidY + MARGIN) + y += MARGIN + ITEM_HEIGHT; + + if (dragRectangle == null || item != dragRectangle) { + item.setLocation(sourceX, y); + y += MARGIN + ITEM_HEIGHT; + } + } + + avoidY = Integer.MAX_VALUE; + if (dragRectangle != null && dragRectangle.getX() == cdmX) + avoidY = dragRectangle.getY(); + y = HEADER_HEIGHT; + for (int i = 0; i < cdmComponents.size(); i++) { + LabeledRectangle item = cdmComponents.get(i); + if (y > avoidY - ITEM_HEIGHT && y <= avoidY + MARGIN) + y += MARGIN + ITEM_HEIGHT; + + if (dragRectangle == null || item != dragRectangle) { + item.setLocation(cdmX, y); + y += MARGIN + ITEM_HEIGHT; + } + } + } + } + + public Dimension getMinimumSize() { + Dimension dimension = new Dimension(); + dimension.width = 2 * (ITEM_WIDTH + MARGIN) + MIN_SPACE_BETWEEN_COLUMNS; + dimension.height = Math.min(HEADER_HEIGHT + Math.max(sourceComponents.size(), cdmComponents.size()) * (ITEM_HEIGHT + MARGIN), maxHeight); + return dimension; + } + + public Dimension getPreferredSize() { + return getMinimumSize(); + } + + public void setSize(Dimension dimension) { + setSize(dimension.width, dimension.height); + } + + public void setSize(int width, int height) { + sourceX = MARGIN; + cdmX = width - MARGIN - ITEM_WIDTH; + + layoutItems(); + super.setSize(width, height); + } + + public void paint(Graphics g) { + Image offscreen = createVolatileImage(getWidth(), getHeight()); + Graphics2D g2d; + if (offscreen == null) + g2d = (Graphics2D) g; + else + g2d = (Graphics2D) offscreen.getGraphics(); + + RenderingHints rh = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g2d.setRenderingHints(rh); + // g2d.clearRect(0, 0, getWidth(), getHeight()); + + addLabel(g2d, "Source", sourceX + ITEM_WIDTH / 2, HEADER_HEIGHT / 2); + addLabel(g2d, "CDM", cdmX + ITEM_WIDTH / 2, HEADER_HEIGHT / 2); + + if (showingArrowStarts && dragRectangle == null) { + for (LabeledRectangle item : sourceComponents) + Arrow.drawArrowHead(g2d, Math.round(item.getX() + item.getWidth() + Arrow.headThickness), item.getY() + item.getHeight() / 2); + } + + for (LabeledRectangle component : sourceComponents) + if (component != dragRectangle) + component.paint(g2d); + + for (LabeledRectangle component : cdmComponents) + if (component != dragRectangle) + component.paint(g2d); + + for (Arrow component : arrows) + if (component != dragArrow) + component.paint(g2d); + + if (dragRectangle != null) + dragRectangle.paint(g2d); + + if (dragArrow != null) + dragArrow.paint(g2d); + + if (offscreen != null) + g.drawImage(offscreen, 0, 0, this); + } + + private void addLabel(Graphics2D g2d, String string, int x, int y) { + g2d.setFont(new Font("default", Font.PLAIN, 20)); + FontMetrics fm = g2d.getFontMetrics(); + Rectangle2D r = fm.getStringBounds(string, g2d); + g2d.drawString(string, x - Math.round(r.getWidth() / 2), y - Math.round(r.getHeight() / 2) + fm.getAscent()); + } + + @Override + public void mouseClicked(MouseEvent event) { + if (selectedArrow != null) { + selectedArrow.setSelected(false); + detailsListener.showDetails(null); + selectedArrow = null; + } + if (selectedRectangle != null) { + selectedRectangle.setSelected(false); + detailsListener.showDetails(null); + selectedRectangle = null; + } + + if (event.getX() > sourceX && event.getX() < sourceX + ITEM_WIDTH) { // Source component + for (LabeledRectangle component : sourceComponents) { + if (component.contains(event.getPoint())) { + if (!component.isSelected()) { + component.setSelected(true); + detailsListener.showDetails(component.getItem()); + selectedRectangle = component; + } + repaint(); + break; + } + } + } + if (event.getX() > cdmX && event.getX() < cdmX + ITEM_WIDTH) { // cdm component + for (LabeledRectangle component : cdmComponents) { + if (component.contains(event.getPoint())) { + if (!component.isSelected()) { + component.setSelected(true); + detailsListener.showDetails(component.getItem()); + selectedRectangle = component; + } + repaint(); + break; + } + } + } + if (event.getX() > sourceX + ITEM_WIDTH && event.getX() < cdmX) { // Arrows + for (Arrow component : arrows) { + if (component.contains(event.getPoint())) { + if (event.getClickCount() == 2) { // double click + zoomArrow = component; + if (slaveMappingPanel != null) { + slaveMappingPanel.setMapping(ObjectExchange.etl.getFieldToFieldMapping((Table) zoomArrow.getSource().getItem(), (Table) zoomArrow + .getTarget().getItem())); + new AnimateThread(true).start(); + } + + } else { // single click + if (!component.isSelected()) { + component.setSelected(true); + selectedArrow = component; + detailsListener.showDetails(mapping.getSourceToCdmMap(selectedArrow.getSource().getItem(), selectedArrow.getTarget().getItem())); + } + repaint(); + break; + } + } + } + } + + } + + private class AnimateThread extends Thread { + public int nSteps = 10; + private boolean minimizing; + + public AnimateThread(boolean minimizing) { + this.minimizing = minimizing; + } + + public void run() { + if (minimizing) { + LabeledRectangle sourceComponent = zoomArrow.getSource(); + LabeledRectangle cdmComponent = zoomArrow.getTarget(); + + for (LabeledRectangle component : sourceComponents) + if (component != sourceComponent) + component.setVisible(false); + + for (LabeledRectangle component : cdmComponents) + if (component != cdmComponent) + component.setVisible(false); + + for (Arrow component : arrows) + if (component != zoomArrow) + component.setVisible(false); + minimized = true; + Path heightPath = new Path(getHeight(), HEADER_HEIGHT + MARGIN + ITEM_HEIGHT + BORDER_HEIGHT); + Path sourcePath = new Path(sourceComponent.getY(), HEADER_HEIGHT); + Path cdmPath = new Path(cdmComponent.getY(), HEADER_HEIGHT); + for (int i = 0; i < nSteps; i++) { + maxHeight = heightPath.getValue(i); + sourceComponent.setLocation(sourceX, sourcePath.getValue(i)); + cdmComponent.setLocation(cdmX, cdmPath.getValue(i)); + for (ResizeListener resizeListener : resizeListeners) + resizeListener.notifyResized(maxHeight, false, false); + try { + sleep(20); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + maxHeight = heightPath.getEnd(); + sourceComponent.setLocation(sourceX, sourcePath.getEnd()); + cdmComponent.setLocation(cdmX, cdmPath.getEnd()); + for (ResizeListener resizeListener : resizeListeners) + resizeListener.notifyResized(maxHeight, true, false); + } else { // maximizing + + } + } + + private class Path { + private int start; + private int end; + private int stepSize; + + public Path(int start, int end) { + this.start = start; + this.end = end; + this.stepSize = (end - start) / nSteps; + } + + public int getValue(int step) { + return start + stepSize * step; + } + + public int getEnd() { + return end; + } + } + } + + @Override + public void mouseEntered(MouseEvent event) { + + } + + @Override + public void mouseExited(MouseEvent event) { + if (showingArrowStarts) { + showingArrowStarts = false; + repaint(); + } + } + + private void maximize() { + maxHeight = Integer.MAX_VALUE; + minimized = false; + for (ResizeListener resizeListener : resizeListeners) + resizeListener.notifyResized(maxHeight, false, true); + for (LabeledRectangle component : sourceComponents) + component.setVisible(true); + + for (LabeledRectangle component : cdmComponents) + component.setVisible(true); + + for (Arrow component : arrows) + component.setVisible(true); + } + + @Override + public void mousePressed(MouseEvent event) { + if (minimized) { + maximize(); + return; + } + + if (event.getX() > sourceX + ITEM_WIDTH && event.getX() < sourceX + ITEM_WIDTH + ARROW_START_WIDTH) { // Arrow starts + for (LabeledRectangle item : sourceComponents) { + if (event.getY() >= item.getY() && event.getY() <= item.getY() + item.getHeight()) { + dragArrow = new Arrow(item); + dragArrow.setTargetPoint(new Point(item.getX() + item.getWidth() + Arrow.headThickness, item.getY() + item.getHeight() / 2)); + showingArrowStarts = false; + repaint(); + break; + } + } + } else if (event.getX() > cdmX - ARROW_START_WIDTH && event.getX() < cdmX && dragArrow == null) { // Existing arrowheads + for (Arrow arrow : arrows) { + if (event.getY() >= arrow.getTarget().getY() && event.getY() <= arrow.getTarget().getY() + arrow.getTarget().getHeight()) { + dragArrow = arrow; + dragArrowPreviousTarget = dragArrow.getTarget(); + dragArrow.setTarget(null); + break; + } + } + if (dragArrow != null) { + arrows.remove(dragArrow); + } + repaint(); + } else { + for (LabeledRectangle item : sourceComponents) { + if (item.contains(event.getPoint())) { + dragRectangle = item; + dragOffsetY = event.getY() - item.getY(); + break; + } + } + for (LabeledRectangle item : cdmComponents) { + if (item.contains(event.getPoint())) { + dragRectangle = item; + dragOffsetY = event.getY() - item.getY(); + break; + } + } + } + } + + @Override + public void mouseReleased(MouseEvent event) { + if (dragRectangle != null) { + if (!isSorted(sourceComponents, new YComparator())) { + Collections.sort(sourceComponents, new YComparator()); + mapping.setSourceItems(getItemsList(sourceComponents)); + } + if (!isSorted(cdmComponents, new YComparator())) { + Collections.sort(cdmComponents, new YComparator()); + mapping.setCdmItems(getItemsList(cdmComponents)); + } + dragRectangle = null; + layoutItems(); + } else if (dragArrow != null) { + if (event.getX() > cdmX - ARROW_START_WIDTH && event.getX() < cdmX + ITEM_WIDTH) + for (LabeledRectangle component : cdmComponents) { + if (event.getY() >= component.getY() && event.getY() <= component.getY() + component.getHeight()) { + dragArrow.setTarget(component); + if (dragArrow.getTarget() == dragArrowPreviousTarget) { + arrows.add(dragArrow); + break; + } + + boolean isNew = true; + for (Arrow other : arrows) + if (dragArrow.getSource() == other.getSource() && dragArrow.getTarget() == other.getTarget()) + isNew = false; + if (isNew) { + arrows.add(dragArrow); + mapping.addSourceToCdmMap(dragArrow.getSource().getItem(), dragArrow.getTarget().getItem()); + } + break; + } + } + if (dragArrowPreviousTarget != null && dragArrow.getTarget() != dragArrowPreviousTarget) { // Retargeted an existing arrow, remove old map from + // model + mapping.removeSourceToCdmMap(dragArrow.getSource().getItem(), dragArrowPreviousTarget.getItem()); + } + dragArrowPreviousTarget = null; + dragArrow = null; + } + repaint(); + } + + private List getItemsList(List components) { + List items = new ArrayList(); + for (LabeledRectangle component : components) + items.add(component.getItem()); + return items; + } + + private boolean isSorted(List components, Comparator comparator) { + for (int i = 0; i < components.size() - 1; i++) + if (comparator.compare(components.get(i), components.get(i + 1)) < 0) + return false; + return true; + } + + @Override + public void mouseDragged(MouseEvent event) { + if (dragRectangle != null) { + dragRectangle.setLocation(dragRectangle.getX(), event.getY() - dragOffsetY); + layoutItems(); + repaint(); + } + if (dragArrow != null) { + if (event.getX() < sourceX + ITEM_WIDTH + Arrow.headThickness) + dragArrow.setTargetPoint(null); + else + dragArrow.setTargetPoint(event.getPoint()); + repaint(); + } + this.scrollRectToVisible(new Rectangle(event.getX() - 40, event.getY() - 40, 80, 80)); + + } + + @Override + public void mouseMoved(MouseEvent event) { + if (event.getX() > sourceX + ITEM_WIDTH && event.getX() < sourceX + ITEM_WIDTH + ARROW_START_WIDTH && dragArrow == null) { + if (!showingArrowStarts) { + showingArrowStarts = true; + repaint(); + } + } else { + if (showingArrowStarts) { + showingArrowStarts = false; + repaint(); + } + } + } + + private class YComparator implements Comparator { + + @Override + public int compare(LabeledRectangle o1, LabeledRectangle o2) { + return IntegerComparator.compare(o1.getY(), o2.getY()); + } + + } + + @Override + public void keyPressed(KeyEvent event) { + if (event.getKeyCode() == KeyEvent.VK_DELETE) { + if (selectedArrow != null) { + arrows.remove(selectedArrow); + mapping.removeSourceToCdmMap(selectedArrow.getSource().getItem(), selectedArrow.getTarget().getItem()); + repaint(); + } + } + } + + @Override + public void keyReleased(KeyEvent event) { + + } + + @Override + public void keyTyped(KeyEvent event) { + + } + + private List resizeListeners = new ArrayList(); + + public void addResizeListener(ResizeListener resizeListener) { + resizeListeners.add(resizeListener); + } + + public void setDetailsListener(DetailsListener detailsListener) { + this.detailsListener = detailsListener; + } + +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat.java new file mode 100644 index 00000000..800b7ed3 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat.java @@ -0,0 +1,305 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Image; +import java.awt.MediaTracker; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import javax.swing.BoxLayout; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.KeyStroke; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileNameExtensionFilter; + +import org.ohdsi.whiteRabbit.ObjectExchange; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.Database; +import org.ohdsi.whiteRabbit.interactiveMapping.dataModel.ETL; + +public class RabbitInAHat implements ResizeListener, ActionListener { + + private JFrame frame; + private JScrollPane scrollPane1; + private JScrollPane scrollPane2; + private MappingPanel tableMappingPanel; + private JSplitPane tableFieldSplitPane; + private String filename; + + public static void main(String[] args) { + new RabbitInAHat(); + } + + public RabbitInAHat() { + frame = new JFrame("Rabbit in a hat"); + + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + frame.setPreferredSize(new Dimension(700, 600)); + + frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS)); + + frame.setJMenuBar(createMenuBar()); + + ETL etl = new ETL(); + etl.setCDMDatabase(Database.generateCDMModel()); + ObjectExchange.etl = etl; + + tableMappingPanel = new MappingPanel(etl.getTableToTableMapping()); + tableMappingPanel.addResizeListener(this); + scrollPane1 = new JScrollPane(tableMappingPanel); + scrollPane1.setBorder(new TitledBorder("Tables")); + scrollPane1.getVerticalScrollBar().setUnitIncrement(16); + scrollPane1.setAutoscrolls(true); + frame.addKeyListener(tableMappingPanel); + + MappingPanel fieldMappingPanel = new MappingPanel( + etl.getTableToTableMapping()); + tableMappingPanel.setSlaveMappingPanel(fieldMappingPanel); + fieldMappingPanel.addResizeListener(this); + scrollPane2 = new JScrollPane(fieldMappingPanel); + scrollPane2.getVerticalScrollBar().setUnitIncrement(16); + scrollPane2.setVisible(false); + scrollPane2.setBorder(new TitledBorder("Fields")); + frame.addKeyListener(fieldMappingPanel); + tableFieldSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, + scrollPane1, scrollPane2); + tableFieldSplitPane.setDividerLocation(600); + tableFieldSplitPane.setDividerSize(0); + + DetailsPanel detailsPanel = new DetailsPanel(); + detailsPanel.setBorder(new TitledBorder("Details")); + detailsPanel.setPreferredSize(new Dimension(200, 500)); + tableMappingPanel.setDetailsListener(detailsPanel); + fieldMappingPanel.setDetailsListener(detailsPanel); + JSplitPane leftRightSplinePane = new JSplitPane( + JSplitPane.HORIZONTAL_SPLIT, tableFieldSplitPane, detailsPanel); + leftRightSplinePane.setDividerLocation(700); + frame.add(leftRightSplinePane); + + loadIcons(frame); + frame.pack(); + frame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH); + frame.setVisible(true); + } + + private void loadIcons(JFrame f) { + List icons = new ArrayList(); + icons.add(loadIcon("RabbitInAHat16.png", f)); + icons.add(loadIcon("RabbitInAHat32.png", f)); + icons.add(loadIcon("RabbitInAHat48.png", f)); + icons.add(loadIcon("RabbitInAHat64.png", f)); + icons.add(loadIcon("RabbitInAHat128.png", f)); + icons.add(loadIcon("RabbitInAHat256.png", f)); + f.setIconImages(icons); + } + + private Image loadIcon(String name, JFrame f) { + Image icon = Toolkit.getDefaultToolkit().getImage( + RabbitInAHat.class.getResource(name)); + MediaTracker mediaTracker = new MediaTracker(f); + mediaTracker.addImage(icon, 0); + try { + mediaTracker.waitForID(0); + return icon; + } catch (Exception e1) { + e1.printStackTrace(); + } + return null; + } + + private JMenuBar createMenuBar() { + JMenuBar menuBar = new JMenuBar(); + JMenu fileMenu = new JMenu("File"); + menuBar.add(fileMenu); + + JMenuItem openItem = new JMenuItem("Open ETL specs"); + openItem.addActionListener(this); + openItem.setActionCommand("Open ETL specs"); + openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, + InputEvent.CTRL_MASK)); + fileMenu.add(openItem); + + JMenuItem openScanReportItem = new JMenuItem("Open scan report"); + openScanReportItem.addActionListener(this); + openScanReportItem.setActionCommand("Open scan report"); + fileMenu.add(openScanReportItem); + + JMenuItem saveItem = new JMenuItem("Save"); + saveItem.addActionListener(this); + saveItem.setActionCommand("Save"); + saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, + InputEvent.CTRL_MASK)); + fileMenu.add(saveItem); + + JMenuItem saveAsItem = new JMenuItem("Save as"); + saveAsItem.addActionListener(this); + saveAsItem.setActionCommand("Save as"); + fileMenu.add(saveAsItem); + + JMenuItem generateDocItem = new JMenuItem("Generate ETL document"); + generateDocItem.addActionListener(this); + generateDocItem.setActionCommand("Generate ETL document"); + fileMenu.add(generateDocItem); + + JMenu editMenu = new JMenu("Edit"); + menuBar.add(editMenu); + + JMenu viewMenu = new JMenu("View"); + menuBar.add(viewMenu); + + JMenu helpMenu = new JMenu("Help"); + menuBar.add(helpMenu); + return menuBar; + } + + @Override + public void notifyResized(int height, boolean minimized, boolean maximized) { + if (scrollPane2.isVisible() == maximized) + scrollPane2.setVisible(!maximized); + + if (!maximized) + scrollPane1 + .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); + else + scrollPane1 + .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + + if (!minimized) + scrollPane2 + .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); + else + scrollPane2 + .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + + tableFieldSplitPane.setDividerLocation(height); + } + + @Override + public void actionPerformed(ActionEvent event) { + if (event.getActionCommand().equals("Save") + || event.getActionCommand().equals("Save as")) { + if (filename == null || event.getActionCommand().equals("Save as")) { + JFileChooser fileChooser = new JFileChooser(); + if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) { + File file = fileChooser.getSelectedFile(); + filename = file.getAbsolutePath(); + + } + } + if (filename != null) { + try { + frame.setCursor(Cursor + .getPredefinedCursor(Cursor.WAIT_CURSOR)); + FileOutputStream fileOutputStream = new FileOutputStream( + filename); + GZIPOutputStream gzipOutputStream = new GZIPOutputStream( + fileOutputStream); + ObjectOutputStream out = new ObjectOutputStream( + gzipOutputStream); + out.writeObject(ObjectExchange.etl); + out.close(); + frame.setCursor(Cursor + .getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } catch (IOException e) { + e.printStackTrace(); + } + } + } else if (event.getActionCommand().equals("Open ETL specs")) { + JFileChooser fileChooser = new JFileChooser(); + if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) { + File file = fileChooser.getSelectedFile(); + filename = file.getAbsolutePath(); + try { + frame.setCursor(Cursor + .getPredefinedCursor(Cursor.WAIT_CURSOR)); + FileInputStream fileOutputStream = new FileInputStream( + filename); + GZIPInputStream gzipOutputStream = new GZIPInputStream( + fileOutputStream); + ObjectInputStream out = new ObjectInputStream( + gzipOutputStream); + ObjectExchange.etl = (ETL) out.readObject(); + out.close(); + tableMappingPanel.setMapping(ObjectExchange.etl + .getTableToTableMapping()); + frame.setCursor(Cursor + .getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (event.getActionCommand().equals("Open scan report")) { + JFileChooser fileChooser = new JFileChooser(); + if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) { + frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + File file = fileChooser.getSelectedFile(); + ETL etl = new ETL(); + etl.setSourceDatabase(Database.generateModelFromScanReport(file + .getAbsolutePath())); + etl.setCDMDatabase(Database.generateCDMModel()); + ObjectExchange.etl = etl; + tableMappingPanel.setMapping(etl.getTableToTableMapping()); + frame.setCursor(Cursor + .getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + } else if (event.getActionCommand().equals("Generate ETL document")) { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileFilter(new FileNameExtensionFilter("DocX Files", + "docX")); + if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) { + File file = fileChooser.getSelectedFile(); + filename = file.getAbsolutePath(); + if (!filename.toLowerCase().endsWith(".docx")) + filename = filename + ".docx"; + ETLDocumentGenerator.generate(ObjectExchange.etl, filename); + } + } + + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat128.png b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat128.png new file mode 100644 index 00000000..8a38f69a Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat128.png differ diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat16.png b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat16.png new file mode 100644 index 00000000..87f7364f Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat16.png differ diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat256.png b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat256.png new file mode 100644 index 00000000..d3ba6142 Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat256.png differ diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat32.png b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat32.png new file mode 100644 index 00000000..d0d619c6 Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat32.png differ diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat48.png b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat48.png new file mode 100644 index 00000000..284e5998 Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat48.png differ diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat64.png b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat64.png new file mode 100644 index 00000000..972ff149 Binary files /dev/null and b/src/org/ohdsi/whiteRabbit/interactiveMapping/RabbitInAHat64.png differ diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/ResizeListener.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/ResizeListener.java new file mode 100644 index 00000000..16f0ec66 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/ResizeListener.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping; + +public interface ResizeListener { + public void notifyResized(int heigth, boolean minimized, boolean maximized); + +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/CDMV4Model.csv b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/CDMV4Model.csv new file mode 100644 index 00000000..caf9c290 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/CDMV4Model.csv @@ -0,0 +1,162 @@ +TABLE_NAME,COLUMN_NAME,IS_NULLABLE,COLUMN_TYPE +location,LOCATION_ID,NO,int(11) +location,ADDRESS_1,YES,varchar(50) +location,ADDRESS_2,YES,varchar(50) +location,CITY,YES,varchar(50) +location,STATE,YES,char(2) +location,ZIP,YES,varchar(9) +location,COUNTY,YES,varchar(20) +location,LOCATION_SOURCE_VALUE,YES,varchar(50) +person,PERSON_ID,NO,bigint(20) +person,GENDER_CONCEPT_ID,NO,int(11) +person,YEAR_OF_BIRTH,NO,int(11) +person,MONTH_OF_BIRTH,YES,int(11) +person,DAY_OF_BIRTH,YES,int(11) +person,RACE_CONCEPT_ID,YES,int(11) +person,ETHNICITY_CONCEPT_ID,YES,int(11) +person,LOCATION_ID,YES,int(11) +person,PROVIDER_ID,YES,int(11) +person,CARE_SITE_ID,YES,int(11) +person,PERSON_SOURCE_VALUE,YES,varchar(50) +person,GENDER_SOURCE_VALUE,YES,varchar(50) +person,RACE_SOURCE_VALUE,YES,varchar(50) +person,ETHNICITY_SOURCE_VALUE,YES,varchar(50) +observation_period,OBSERVATION_PERIOD_ID,NO,bigint(20) +observation_period,PERSON_ID,NO,bigint(20) +observation_period,OBSERVATION_PERIOD_START_DATE,NO,date +observation_period,OBSERVATION_PERIOD_END_DATE,NO,date +care_site,CARE_SITE_ID,NO,int(11) +care_site,LOCATION_ID,YES,int(11) +care_site,ORGANIZATION_ID,YES,int(11) +care_site,PLACE_OF_SERVICE_CONCEPT_ID,YES,int(11) +care_site,CARE_SITE_SOURCE_VALUE,YES,varchar(50) +care_site,PLACE_OF_SERVICE_SOURCE_VALUE,YES,varchar(50) +visit_occurrence,VISIT_OCCURRENCE_ID,NO,bigint(20) +visit_occurrence,PERSON_ID,NO,bigint(20) +visit_occurrence,PLACE_OF_SERVICE_CONCEPT_ID,NO,int(11) +visit_occurrence,VISIT_START_DATE,NO,date +visit_occurrence,VISIT_END_DATE,NO,date +visit_occurrence,PLACE_OF_SERVICE_SOURCE_VALUE,YES,varchar(50) +visit_occurrence,CARE_SITE_ID,YES,int(11) +provider,PROVIDER_ID,NO,bigint(20) +provider,NPI,YES,varchar(20) +provider,DEA,YES,varchar(20) +provider,SPECIALTY_CONCEPT_ID,YES,int(11) +provider,CARE_SITE_ID,YES,int(11) +provider,PROVIDER_SOURCE_VALUE,YES,varchar(50) +provider,SPECIALTY_SOURCE_VALUE,YES,varchar(50) +condition_occurrence,CONDITION_OCCURRENCE_ID,NO,bigint(20) +condition_occurrence,PERSON_ID,NO,bigint(20) +condition_occurrence,CONDITION_CONCEPT_ID,NO,int(11) +condition_occurrence,CONDITION_START_DATE,NO,date +condition_occurrence,CONDITION_END_DATE,YES,date +condition_occurrence,CONDITION_TYPE_CONCEPT_ID,NO,int(11) +condition_occurrence,STOP_REASON,YES,varchar(20) +condition_occurrence,ASSOCIATED_PROVIDER_ID,YES,int(11) +condition_occurrence,VISIT_OCCURRENCE_ID,YES,bigint(20) +condition_occurrence,CONDITION_SOURCE_VALUE,YES,varchar(50) +death,PERSON_ID,NO,bigint(20) +death,DEATH_DATE,NO,date +death,DEATH_TYPE_CONCEPT_ID,NO,int(11) +death,CAUSE_OF_DEATH_CONCEPT_ID,YES,int(11) +death,CAUSE_OF_DEATH_SOURCE_VALUE,YES,varchar(50) +drug_exposure,DRUG_CONCEPT_ID,NO,int(11) +drug_exposure,DRUG_EXPOSURE_START_DATE,NO,date +drug_exposure,DRUG_EXPOSURE_END_DATE,YES,date +drug_exposure,DRUG_TYPE_CONCEPT_ID,NO,int(11) +drug_exposure,STOP_REASON,YES,varchar(20) +drug_exposure,REFILLS,YES,int(11) +drug_exposure,QUANTITY,YES,int(11) +drug_exposure,DAYS_SUPPLY,YES,int(11) +drug_exposure,SIG,YES,varchar(500) +drug_exposure,PRESCRIBING_PROVIDER_ID,YES,int(11) +drug_exposure,VISIT_OCCURRENCE_ID,YES,bigint(20) +drug_exposure,RELEVANT_CONDITION_CONCEPT_ID,YES,int(11) +drug_exposure,DRUG_SOURCE_VALUE,YES,varchar(50) +drug_exposure,DRUG_EXPOSURE_ID,NO,bigint(20) +drug_exposure,PERSON_ID,NO,bigint(20) +procedure_occurrence,PROCEDURE_OCCURRENCE_ID,NO,bigint(20) +procedure_occurrence,PERSON_ID,NO,bigint(20) +procedure_occurrence,PROCEDURE_TYPE_CONCEPT_ID,NO,int(11) +procedure_occurrence,PROCEDURE_DATE,NO,date +procedure_occurrence,PROCEDURE_CONCEPT_ID,NO,bigint(20) +procedure_occurrence,ASSOCIATED_PROVIDER_ID,YES,int(11) +procedure_occurrence,PROCEDURE_SOURCE_VALUE,YES,varchar(50) +procedure_occurrence,VISIT_OCCURRENCE_ID,YES,bigint(20) +procedure_occurrence,RELEVANT_CONDITION_CONCEPT_ID,YES,int(11) +observation,OBSERVATION_ID,NO,bigint(20) +observation,PERSON_ID,NO,bigint(20) +observation,OBSERVATION_CONCEPT_ID,NO,bigint(20) +observation,OBSERVATION_TYPE_CONCEPT_ID,NO,int(11) +observation,OBSERVATION_DATE,NO,date +observation,OBSERVATION_TIME,YES,time +observation,VALUE_AS_NUMBER,YES,"decimal(10,0)" +observation,VALUE_AS_STRING,YES,varchar(256) +observation,VALUE_AS_CONCEPT_ID,YES,int(11) +observation,UNIT_CONCEPT_ID,YES,bigint(20) +observation,RANGE_LOW,YES,float +observation,RANGE_HIGH,YES,float +observation,ASSOCIATED_PROVIDER_ID,YES,int(11) +observation,VISIT_OCCURRENCE_ID,YES,bigint(20) +observation,OBSERVATION_SOURCE_VALUE,YES,varchar(256) +observation,UNIT_SOURCE_VALUE,YES,varchar(256) +observation,RELEVANT_CONDITION_CONCEPT_ID,YES,int(11) +condition_era,CONDITION_ERA_ID,NO,bigint(20) +condition_era,PERSON_ID,NO,bigint(20) +condition_era,CONDITION_CONCEPT_ID,NO,int(11) +condition_era,CONDITION_ERA_START_DATE,NO,date +condition_era,CONDITION_ERA_END_DATE,NO,date +condition_era,CONDITION_TYPE_CONCEPT_ID,NO,int(11) +condition_era,CONDITION_OCCURRENCE_COUNT,YES,int(11) +drug_era,DRUG_ERA_ID,NO,bigint(20) +drug_era,PERSON_ID,NO,bigint(20) +drug_era,DRUG_ERA_START_DATE,NO,date +drug_era,DRUG_ERA_END_DATE,NO,date +drug_era,DRUG_TYPE_CONCEPT_ID,NO,int(11) +drug_era,DRUG_CONCEPT_ID,YES,int(11) +drug_era,DRUG_EXPOSURE_COUNT,NO,int(11) +organization,ORGANIZATION_ID,NO,int(11) +organization,PLACE_OF_SERVICE_CONCEPT_ID,YES,int(11) +organization,LOCATION_ID,YES,int(11) +organization,ORGANIZATION_SOURCE_VALUE,YES,varchar(50) +organization,PLACE_OF_SERVICE_SOURCE_VALUE,YES,varchar(50) +payer_plan_period,PAYER_PLAN_PERIOD_ID,NO,bigint(20) +payer_plan_period,PERSON_ID,NO,bigint(20) +payer_plan_period,PAYER_PLAN_PERIOD_START_DATE,NO,date +payer_plan_period,PAYER_PLAN_PERIOD_END_DATE,NO,date +payer_plan_period,PAYER_SOURCE_VALUE,YES,varchar(50) +payer_plan_period,PLAN_SOURCE_VALUE,YES,varchar(50) +payer_plan_period,FAMILY_SOURCE_VALUE,YES,varchar(50) +drug_cost,DRUG_COST_ID,NO,bigint(20) +drug_cost,DRUG_EXPOSURE_ID,NO,bigint(20) +drug_cost,PAID_COPAY,YES,"decimal(10,0)" +drug_cost,PAID_COINSURANCE,YES,"decimal(10,0)" +drug_cost,PAID_TOWARD_DEDUCTIBLE,YES,"decimal(10,0)" +drug_cost,PAID_BY_PAYER,YES,"decimal(10,0)" +drug_cost,PAID_BY_COORDINATION_BENEFITS,YES,"decimal(10,0)" +drug_cost,TOTAL_OUT_OF_POCKET,YES,"decimal(10,0)" +drug_cost,TOTAL_PAID,YES,"decimal(10,0)" +drug_cost,INGREDIENT_COST,YES,"decimal(10,0)" +drug_cost,DISPENSING_FEE,YES,"decimal(10,0)" +drug_cost,AVERAGE_WHOLESALE_PRICE,YES,"decimal(10,0)" +drug_cost,PAYER_PLAN_PERIOD_ID,YES,int(11) +procedure_cost,PROCEDURE_COST_ID,NO,bigint(20) +procedure_cost,PROCEDURE_OCCURRENCE_ID,NO,bigint(20) +procedure_cost,PAID_COPAY,YES,"decimal(10,0)" +procedure_cost,PAID_COINSURANCE,YES,"decimal(10,0)" +procedure_cost,PAID_TOWARD_DEDUCTIBLE,YES,"decimal(10,0)" +procedure_cost,PAID_BY_PAYER,YES,"decimal(10,0)" +procedure_cost,PAID_BY_COORDINATION_BENEFITS,YES,"decimal(10,0)" +procedure_cost,TOTAL_OUT_OF_POCKET,YES,"decimal(10,0)" +procedure_cost,TOTAL_PAID,YES,"decimal(10,0)" +procedure_cost,DISEASE_CLASS_CONCEPT_ID,YES,int(11) +procedure_cost,REVENUE_CODE_CONCEPT_ID,YES,int(11) +procedure_cost,PAYER_PLAN_PERIOD_ID,YES,bigint(20) +procedure_cost,DISEASE_CLASS_SOURCE_VALUE,YES,varchar(50) +procedure_cost,REVENUE_CODE_SOURCE_VALUE,YES,varchar(50) +cohort,COHORT_ID,NO,int(11) +cohort,COHORT_CONCEPT_ID,NO,int(11) +cohort,COHORT_START_DATE,NO,date +cohort,COHORT_END_DATE,YES,date +cohort,SUBJECT_ID,NO,bigint(20) +cohort,STOP_REASON,YES,varchar(20) diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Database.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Database.java new file mode 100644 index 00000000..0c500435 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Database.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping.dataModel; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.ohdsi.utilities.files.QuickAndDirtyXlsxReader; +import org.ohdsi.utilities.files.QuickAndDirtyXlsxReader.Sheet; +import org.ohdsi.utilities.files.ReadCSVFileWithHeader; +import org.ohdsi.utilities.files.Row; + +public class Database implements Serializable { + + private List tables = new ArrayList
(); + // private List
defaultOrdering; + private static final long serialVersionUID = -3912166654601191039L; + + public List
getTables() { + return tables; + } + + public void setTables(List
tables) { + this.tables = tables; + } + + public static Database generateCDMModel() { + Database database = new Database(); + Map nameToTable = new HashMap(); + for (Row row : new ReadCSVFileWithHeader(Database.class.getResourceAsStream("CDMV4Model.csv"))) { + Table table = nameToTable.get(row.get("TABLE_NAME").toLowerCase()); + if (table == null) { + table = new Table(); + table.setName(row.get("TABLE_NAME").toLowerCase()); + nameToTable.put(row.get("TABLE_NAME").toLowerCase(), table); + database.tables.add(table); + } + Field field = new Field(row.get("COLUMN_NAME").toLowerCase(), table); + field.setNullable(row.get("IS_NULLABLE").equals("YES")); + field.setType(row.get("COLUMN_TYPE")); + table.getFields().add(field); + } + // database.defaultOrdering = new ArrayList
(database.tables); + return database; + } + + public static Database generateModelFromScanReport(String filename) { + Database database = new Database(); + Map nameToTable = new HashMap(); + QuickAndDirtyXlsxReader workbook = new QuickAndDirtyXlsxReader(filename); + Sheet sheet = workbook.get(0); + Iterator iterator = sheet.iterator(); + Map fieldName2ColumnIndex = new HashMap(); + for (String header : iterator.next()) + fieldName2ColumnIndex.put(header, fieldName2ColumnIndex.size()); + + while (iterator.hasNext()) { + org.ohdsi.utilities.files.QuickAndDirtyXlsxReader.Row row = iterator.next(); + String tableName = row.get(fieldName2ColumnIndex.get("Table")); + if (tableName.length() != 0) { + Table table = nameToTable.get(tableName); + if (table == null) { + table = new Table(); + table.setName(tableName.toLowerCase()); + table.setRowCount((int) Double.parseDouble(row.get(fieldName2ColumnIndex.get("N rows")))); + nameToTable.put(tableName, table); + database.tables.add(table); + } + String fieldName = row.get(fieldName2ColumnIndex.get("Field")); + Field field = new Field(fieldName.toLowerCase(), table); + int index; + // Someone may have manually deleted data, so can't assume this + // is always there: + index = fieldName2ColumnIndex.get("Fraction empty"); + if (index < row.size()) + field.setNullable(!row.get(index).equals("0")); + + index = fieldName2ColumnIndex.get("Type"); + if (index < row.size()) + field.setType(row.get(index)); + + index = fieldName2ColumnIndex.get("Max length"); + if (index >= 0 && index < row.size()) + field.setMaxLength((int)(Double.parseDouble(row.get(index)))); + field.setValueCounts(getValueCounts(workbook, tableName, fieldName)); + table.getFields().add(field); + } + } + // database.defaultOrdering = new ArrayList
(database.tables); + return database; + } + + private static String[][] getValueCounts(QuickAndDirtyXlsxReader workbook, String tableName, String fieldName) { + Sheet tableSheet = null; + for (Sheet sheet : workbook) + if (sheet.getName().equals(tableName)) { + tableSheet = sheet; + break; + } + + Iterator iterator = tableSheet.iterator(); + org.ohdsi.utilities.files.QuickAndDirtyXlsxReader.Row header = iterator.next(); + int index = header.indexOf(fieldName); + List list = new ArrayList(); + if (index != -1) // Could happen when people manually delete columns + while (iterator.hasNext()) { + org.ohdsi.utilities.files.QuickAndDirtyXlsxReader.Row row = iterator.next(); + if (row.size() > index) { + String value = row.get(index); + String count; + if (row.size() > index + 1) + count = row.get(index + 1); + else + count = ""; + if (value.equals("") && count.equals("")) + break; + list.add(new String[] { value, count }); + } + } + return list.toArray(new String[list.size()][2]); + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/ETL.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/ETL.java new file mode 100644 index 00000000..de60492f --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/ETL.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping.dataModel; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ETL implements Serializable { + private Database sourceDb = new Database(); + private Database cdmDb = new Database(); + private List tableToTableMaps = new ArrayList(); + private Map> tableMapToFieldToFieldMaps = new HashMap>(); + private static final long serialVersionUID = 8987388381751618498L; + + public void saveCurrentState() { + + } + + public void revertToPreviousState() { + + } + + public void revertToNextState() { + + } + + public Mapping
getTableToTableMapping() { + return new Mapping
(sourceDb.getTables(), cdmDb.getTables(), tableToTableMaps); + } + + public Mapping getFieldToFieldMapping(Table sourceTable, Table cdmTable) { + List fieldToFieldMaps = tableMapToFieldToFieldMaps.get(new ItemToItemMap(sourceTable, cdmTable)); + if (fieldToFieldMaps == null) { + fieldToFieldMaps = new ArrayList(); + tableMapToFieldToFieldMaps.put(new ItemToItemMap(sourceTable, cdmTable), fieldToFieldMaps); + } + return new Mapping(sourceTable.getFields(), cdmTable.getFields(), fieldToFieldMaps); + } + + public void setCDMDatabase(Database cdmDb) { + this.cdmDb = cdmDb; + } + + public void setSourceDatabase(Database sourceDb) { + this.sourceDb = sourceDb; + } + + public Database getCDMDatabase() { + return cdmDb; + } + + public Database getSourceDatabase() { + return sourceDb; + } + + public ItemToItemMap createItemToItemMap(MappableItem source, MappableItem target) { + ItemToItemMap itemToItemMap = new ItemToItemMap(source, target); + if (source instanceof Table) { + tableToTableMaps.add(itemToItemMap); + } else { + tableMapToFieldToFieldMaps.get(((Field) source).getTable()).add(itemToItemMap); + } + return itemToItemMap; + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Field.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Field.java new file mode 100644 index 00000000..2fab97ea --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Field.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping.dataModel; + +public class Field implements MappableItem { + + private static final long serialVersionUID = 3687778470032619497L; + private Table table; + private String name; + private String comment = ""; + // private List> valueCounts; + private String[][] valueCounts; + private boolean isNullable; + private String type; + private int maxLength; + + public Field(String name, Table table) { + this.table = table; + this.name = name; + } + + public Table getTable() { + return table; + } + + public void setTable(Table table) { + this.table = table; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String[][] getValueCounts() { + return valueCounts; + } + + public void setValueCounts(String[][] valueCounts) { + this.valueCounts = valueCounts; + } + + public boolean isNullable() { + return isNullable; + } + + public void setNullable(boolean isNullable) { + this.isNullable = isNullable; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String toString() { + return table.getName() + "." + name; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getComment() { + return comment; + } + + public int getMaxLength() { + return maxLength; + } + + public void setMaxLength(int maxLength) { + this.maxLength = maxLength; + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/ItemToItemMap.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/ItemToItemMap.java new file mode 100644 index 00000000..4540f967 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/ItemToItemMap.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping.dataModel; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class ItemToItemMap implements Serializable { + + private MappableItem sourceItem; + private MappableItem cdmItem; + private Map extraFieldToValue = new HashMap(); + private String comment = ""; + private String logic = ""; + private static final long serialVersionUID = -7803242002700513410L; + + public ItemToItemMap(MappableItem sourceItem, MappableItem cdmItem) { + this.sourceItem = sourceItem; + this.cdmItem = cdmItem; + } + + public MappableItem getSourceItem() { + return sourceItem; + } + + public void setSourceItem(MappableItem sourceItem) { + this.sourceItem = sourceItem; + } + + public MappableItem getCdmItem() { + return cdmItem; + } + + public void setCdmItem(MappableItem cdmItem) { + this.cdmItem = cdmItem; + } + + public Map getExtraFieldToValue() { + return extraFieldToValue; + } + + public boolean equals(Object other) { + if (other instanceof ItemToItemMap) { + return (((ItemToItemMap) other).sourceItem.equals(sourceItem) && ((ItemToItemMap) other).cdmItem.equals(cdmItem)); + } else + return false; + } + + public int hashCode() { + return (sourceItem.toString() + "\t" + cdmItem.toString()).hashCode(); + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getLogic() { + return logic; + } + + public void setLogic(String logic) { + this.logic = logic; + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/MappableItem.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/MappableItem.java new file mode 100644 index 00000000..2f4d14d5 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/MappableItem.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping.dataModel; + +import java.io.Serializable; + +public interface MappableItem extends Serializable{ + public String getName(); +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Mapping.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Mapping.java new file mode 100644 index 00000000..fd9d0dc4 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Mapping.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping.dataModel; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class Mapping { + private List sourceItems; + private List cdmItems; + private List sourceToCdmMaps; + + public Mapping(List sourceItems, List cdmItems, List sourceToCdmMaps) { + this.sourceItems = sourceItems; + this.cdmItems = cdmItems; + this.sourceToCdmMaps = sourceToCdmMaps; + } + + public void addSourceToCdmMap(MappableItem sourceItem, MappableItem cdmItem) { + sourceToCdmMaps.add(new ItemToItemMap(sourceItem, cdmItem)); + } + + public List getSourceItems() { + List list = new ArrayList(); + for (MappableItem item : sourceItems) + list.add(item); + return list; + } + + @SuppressWarnings("unchecked") + public void setSourceItems(List sourceItems) { + this.sourceItems.clear(); + for (MappableItem item : sourceItems) + this.sourceItems.add((T)item); + } + + @SuppressWarnings("unchecked") + public void setCdmItems(List cdmItems) { + this.cdmItems.clear(); + for (MappableItem item : cdmItems) + this.cdmItems.add((T) item); + } + + public List getCdmItems() { + List list = new ArrayList(); + for (MappableItem item : cdmItems) + list.add(item); + return list; + + } + + public List getSourceToCdmMaps() { + return sourceToCdmMaps; + } + + public void removeSourceToCdmMap(MappableItem sourceItem, MappableItem cdmItem) { + Iterator iterator = sourceToCdmMaps.iterator(); + while (iterator.hasNext()) { + ItemToItemMap sourceToCdmMap = iterator.next(); + if (sourceToCdmMap.getSourceItem().equals(sourceItem) && sourceToCdmMap.getCdmItem().equals(cdmItem)) + iterator.remove(); + } + } + + public ItemToItemMap getSourceToCdmMap(MappableItem sourceItem, MappableItem cdmItem) { + Iterator iterator = sourceToCdmMaps.iterator(); + while (iterator.hasNext()) { + ItemToItemMap sourceToCdmMap = iterator.next(); + if (sourceToCdmMap.getSourceItem().equals(sourceItem) && sourceToCdmMap.getCdmItem().equals(cdmItem)) + return sourceToCdmMap; + } + return null; + } +} diff --git a/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Table.java b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Table.java new file mode 100644 index 00000000..bd96b087 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/interactiveMapping/dataModel/Table.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.interactiveMapping.dataModel; + +import java.util.ArrayList; +import java.util.List; + +public class Table implements MappableItem { + + private Database db; + private String name; + private int rowCount; + private String comment = ""; + private List fields = new ArrayList(); + private static final long serialVersionUID = 8866500385429215492L; + + public Database getDb() { + return db; + } + + public void setDb(Database db) { + this.db = db; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getRowCount() { + return rowCount; + } + + public void setRowCount(int rowCount) { + this.rowCount = rowCount; + } + + public List getFields() { + return fields; + } + + public String toString() { + return name; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getComment() { + return comment; + } +} diff --git a/src/org/ohdsi/whiteRabbit/scan/SourceDataScan.java b/src/org/ohdsi/whiteRabbit/scan/SourceDataScan.java new file mode 100644 index 00000000..25aa85c1 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/scan/SourceDataScan.java @@ -0,0 +1,456 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.scan; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.ohdsi.databases.DbType; +import org.ohdsi.databases.RichConnection; +import org.ohdsi.databases.RichConnection.QueryResult; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.collections.CountingSet; +import org.ohdsi.utilities.collections.CountingSet.Count; +import org.ohdsi.utilities.collections.Pair; +import org.ohdsi.utilities.files.ReadTextFile; +import org.ohdsi.whiteRabbit.DbSettings; + +public class SourceDataScan { + + public static int MAX_VALUES_IN_MEMORY = 100000; + public static int MAX_VALUES_TO_REPORT = 25000; + public static int MIN_REPORTING_COUNT = 25; + public static int N_FOR_FREE_TEXT_CHECK = 1000; + public static int MIN_AVERAGE_LENGTH_FOR_FREE_TEXT = 100; + + private char delimiter = ','; + private int sampleSize; + + public static void main(String[] args) { + DbSettings dbSettings = new DbSettings(); + dbSettings.dataType = DbSettings.DATABASE; + dbSettings.dbType = DbType.POSTGRESQL; + dbSettings.server = "127.0.0.1/test"; + dbSettings.database = "test_schema"; + dbSettings.tables.add("test_table"); + dbSettings.user = "postgres"; + dbSettings.password = "F1r3starter"; + SourceDataScan scan = new SourceDataScan(); + scan.process(dbSettings, 1000000, "s:/data/ScanReport.xlsx"); + + // DbSettings dbSettings = new DbSettings(); + // dbSettings.dataType = DbSettings.DATABASE; + // dbSettings.dbType = DbType.ORACLE; + // dbSettings.server = "127.0.0.1/xe"; + // dbSettings.database = "test"; + // dbSettings.tables.add("test_table"); + // dbSettings.user = "system"; + // dbSettings.password = "F1r3starter"; + // SourceDataScan scan = new SourceDataScan(); + // scan.process(dbSettings, 1000000, "s:/data/ScanReport.xlsx"); + + // DbSettings dbSettings = new DbSettings(); + // dbSettings.dataType = DbSettings.DATABASE; + // dbSettings.dbType = DbType.MSSQL; + // dbSettings.server = "RNDUSRDHIT03.jnj.com"; + // dbSettings.database = "[HCUP-NIS]"; + // dbSettings.tables.add("hospital"); + // dbSettings.tables.add("severity"); + // dbSettings.tables.add("dx_pr_grps"); + // dbSettings.tables.add("core"); + // SourceDataScan scan = new SourceDataScan(); + // scan.process(dbSettings, 1000000, "s:/data/ScanReport.xlsx"); + + // DbSettings dbSettings = new DbSettings(); + // dbSettings.dataType = DbSettings.DATABASE; + // dbSettings.dbType = DbType.MYSQL; + // dbSettings.server = "127.0.0.1"; + // dbSettings.database = "CDM_v4"; + // dbSettings.user = "root"; + // dbSettings.password = "F1r3starter"; + // dbSettings.tables.add("person"); + // dbSettings.tables.add("provider"); + // + // SourceDataScan scan = new SourceDataScan(); + // scan.process(dbSettings, 1000000, "c:/temp/ScanReport.xlsx"); + } + + public void process(DbSettings dbSettings, int sampleSize, String filename) { + this.sampleSize = sampleSize; + Map> tableToFieldInfos; + if (dbSettings.dataType == DbSettings.CSVFILES) + tableToFieldInfos = processCsvFiles(dbSettings); + else + tableToFieldInfos = processDatabase(dbSettings); + generateReport(tableToFieldInfos, filename); + } + + private Map> processDatabase(DbSettings dbSettings) { + Map> tableToFieldInfos = new HashMap>(); + RichConnection connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + connection.setVerbose(false); + connection.use(dbSettings.database); + + for (String table : dbSettings.tables) { + List fieldInfos = processDatabaseTable(table, connection, dbSettings.dbType); + tableToFieldInfos.put(table, fieldInfos); + } + + connection.close(); + return tableToFieldInfos; + } + + private Map> processCsvFiles(DbSettings dbSettings) { + delimiter = dbSettings.delimiter; + Map> tableToFieldInfos = new HashMap>(); + for (String table : dbSettings.tables) { + List fieldInfos = processCsvFile(table); + String tableName = new File(table).getName(); + tableToFieldInfos.put(tableName, fieldInfos); + } + return tableToFieldInfos; + } + + private void generateReport(Map> tableToFieldInfos, String filename) { + System.out.println("Generating scan report"); + removeEmptyTables(tableToFieldInfos); + List tables = new ArrayList(tableToFieldInfos.keySet()); + Collections.sort(tables); + + // XSSFWorkbook workbook = new XSSFWorkbook(); + SXSSFWorkbook workbook = new SXSSFWorkbook(100); // keep 100 rows in + // memory, exceeding + // rows will be + // flushed to disk + + // Create overview sheet + // XSSFSheet sheet = workbook.createSheet("Overview"); + Sheet sheet = workbook.createSheet("Overview"); + addRow(sheet, "Table", "Field", "Type", "N rows", "N rows checked", "Fraction empty", "Average length", "Max length", "Number of unique values", "Most common value", + "2nd common value", "3rd common value"); + for (String table : tables) { + for (FieldInfo fieldInfo : tableToFieldInfos.get(table)) { + List> counts = fieldInfo.getSortedValuesWithoutSmallValues(); + String value1 = counts.size() > 0 ? counts.get(0).getItem1() : ""; + String value2 = counts.size() > 1 ? counts.get(1).getItem1() : ""; + String value3 = counts.size() > 2 ? counts.get(2).getItem1() : ""; + addRow(sheet, table, fieldInfo.name, fieldInfo.getTypeDescription(), Long.valueOf(fieldInfo.rowCount), Long.valueOf(fieldInfo.nProcessed), + fieldInfo.getFractionEmpty(), fieldInfo.getAverageLength(), fieldInfo.maxLength, fieldInfo.tooManyValues ? "> " + MAX_VALUES_TO_REPORT + : fieldInfo.valueCounts.size(), value1, value2, value3); + } + addRow(sheet, ""); + } + + // Create per table sheets + for (String table : tables) { + sheet = workbook.createSheet(table); + List fieldInfos = tableToFieldInfos.get(table); + List>> valueCounts = new ArrayList>>(); + Object[] header = new Object[fieldInfos.size() * 2]; + int maxCount = 0; + for (int i = 0; i < fieldInfos.size(); i++) { + FieldInfo fieldInfo = fieldInfos.get(i); + header[i * 2] = fieldInfo.name; + if (fieldInfo.isFreeText) + header[(i * 2) + 1] = "Word count"; + else + header[(i * 2) + 1] = "Frequency"; + List> counts = fieldInfo.getSortedValuesWithoutSmallValues(); + valueCounts.add(counts); + if (counts.size() > maxCount) + maxCount = counts.size(); + } + addRow(sheet, header); + for (int i = 0; i < maxCount; i++) { + Object[] row = new Object[fieldInfos.size() * 2]; + for (int j = 0; j < fieldInfos.size(); j++) { + List> counts = valueCounts.get(j); + if (counts.size() > i) { + row[j * 2] = counts.get(i).getItem1(); + row[(j * 2) + 1] = counts.get(i).getItem2() == -1 ? "" : counts.get(i).getItem2(); + } else { + row[j * 2] = ""; + row[(j * 2) + 1] = ""; + } + } + addRow(sheet, row); + } + // Save some memory by derefencing tables already included in the + // report: + tableToFieldInfos.remove(table); + } + + try { + FileOutputStream out = new FileOutputStream(new File(filename)); + workbook.write(out); + out.close(); + StringUtilities.outputWithTime("Scan report generated: " + filename); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + + } + + private void removeEmptyTables(Map> tableToFieldInfos) { + Iterator>> iterator = tableToFieldInfos.entrySet().iterator(); + while (iterator.hasNext()) { + if (iterator.next().getValue().size() == 0) + iterator.remove(); + } + } + + private List processDatabaseTable(String table, RichConnection connection, DbType dbType) { + StringUtilities.outputWithTime("Scanning table " + table); + List fieldInfos = new ArrayList(); + + long rowCount = connection.getTableSize(table); + if (rowCount == 0) + return new ArrayList(); + + String query; + if (dbType == DbType.MSSQL) + query = "SELECT * FROM [" + table + "]"; + else + query = "SELECT * FROM " + table; + + if (sampleSize != -1) { + if (dbType == DbType.MSSQL) + query += " TABLESAMPLE (" + sampleSize + " ROWS)"; + else if (dbType == DbType.MYSQL) + query += " ORDER BY RAND() LIMIT " + sampleSize; + else if (dbType == DbType.ORACLE) { + if (sampleSize < rowCount) { + double percentage = 100 * sampleSize / (double) rowCount; + if (percentage < 100) + query += " SAMPLE(" + percentage + ")"; + } + } else if (dbType == DbType.POSTGRESQL) + query += " ORDER BY RANDOM() LIMIT " + sampleSize; + } + System.out.println("SQL: " + query); + int actualCount = 0; + boolean first = true; + QueryResult queryResult = connection.query(query); + for (org.ohdsi.utilities.files.Row row : queryResult) { + if (first) { + for (String field : row.getFieldNames()) + fieldInfos.add(new FieldInfo(field)); + first = false; + } + for (int i = 0; i < fieldInfos.size(); i++) + fieldInfos.get(i).processValue(row.getCells().get(i)); + actualCount++; + if (sampleSize != -1 && actualCount >= sampleSize) { + System.out.println("Stopped after " + actualCount + " rows"); + break; + } + } + queryResult.close(); // Not normally needed, but if we ended prematurely + // make sure its closed + for (FieldInfo fieldInfo : fieldInfos) { + fieldInfo.trim(); + fieldInfo.rowCount = rowCount; + } + + return fieldInfos; + + } + + private List processCsvFile(String filename) { + StringUtilities.outputWithTime("Scanning table " + filename); + List fieldInfos = new ArrayList(); + int lineNr = 0; + for (String line : new ReadTextFile(filename)) { + lineNr++; + List row = StringUtilities.safeSplit(line, delimiter); + for (int i = 0; i < row.size(); i++) { + String column = row.get(i); + if (column.startsWith("\"") && column.endsWith("\"") && column.length() > 1) + column = column.substring(1, column.length() - 1); + column = column.replace("\\\"", "\""); + row.set(i, column); + } + if (lineNr == 1) { + for (String cell : row) + fieldInfos.add(new FieldInfo(cell)); + } else { + if (row.size() == fieldInfos.size()) { // Else there appears to + // be a formatting + // error, so skip + for (int i = 0; i < row.size(); i++) + fieldInfos.get(i).processValue(row.get(i)); + } + } + if (sampleSize != -1 && lineNr == sampleSize) + break; + } + for (FieldInfo fieldInfo : fieldInfos) + fieldInfo.trim(); + + return fieldInfos; + } + + private class FieldInfo { + public String name; + public CountingSet valueCounts = new CountingSet(); + public long sumLength = 0; + public long nProcessed = 0; + public long emptyCount = 0; + public long rowCount = -1; + public int maxLength = 0; + // public String dataTypeAccordingToSchema = ""; + public boolean isInteger = true; + public boolean isReal = true; + public boolean isDate = true; + public boolean isFreeText = false; + public boolean tooManyValues = false; + + public FieldInfo(String name) { + this.name = name; + } + + public void trim() { + if (valueCounts.size() > MAX_VALUES_TO_REPORT) + valueCounts.keepTopN(MAX_VALUES_TO_REPORT); + } + + public Double getFractionEmpty() { + return emptyCount / (double) nProcessed; + } + + public Double getAverageLength() { + if (nProcessed == emptyCount) + return 0d; + else + return sumLength / (double) (nProcessed - emptyCount); + } + + public String getTypeDescription() { + if (nProcessed == emptyCount) + return "Empty"; + else if (isFreeText) + return "Free text"; + else if (isDate) + return "Date"; + else if (isInteger) + return "Integer"; + else if (isReal) + return "Real"; + else + return "VarChar"; + } + + public void processValue(String value) { + String trimValue = value.trim(); + nProcessed++; + sumLength += value.length(); + if (trimValue.length() == 0) + emptyCount++; + if (value.length() > maxLength) + maxLength = value.length(); + + if (!isFreeText) { + valueCounts.add(value); + + if (trimValue.length() != 0) { + if (isReal && !StringUtilities.isNumber(trimValue)) + isReal = false; + if (isInteger && !StringUtilities.isLong(trimValue)) + isInteger = false; + if (isDate && !StringUtilities.isDate(trimValue)) + isDate = false; + } + if (nProcessed == N_FOR_FREE_TEXT_CHECK) { + if (!isInteger && !isReal && !isDate) { + double averageLength = sumLength / (double) (nProcessed - emptyCount); + if (averageLength >= MIN_AVERAGE_LENGTH_FOR_FREE_TEXT) { + isFreeText = true; + CountingSet wordCounts = new CountingSet(); + for (Map.Entry entry : valueCounts.key2count.entrySet()) + for (String word : StringUtilities.mapToWords(entry.getKey().toLowerCase())) + wordCounts.add(word, entry.getValue().count); + valueCounts = wordCounts; + } + } + } + } else { + for (String word : StringUtilities.mapToWords(trimValue.toLowerCase())) + valueCounts.add(word); + } + + if (valueCounts.size() > MAX_VALUES_IN_MEMORY) { + tooManyValues = true; + valueCounts.keepTopN(MAX_VALUES_TO_REPORT); + } + } + + public List> getSortedValuesWithoutSmallValues() { + boolean truncated = false; + List> result = new ArrayList>(); + + for (Map.Entry entry : valueCounts.key2count.entrySet()) { + if (entry.getValue().count < MIN_REPORTING_COUNT) + truncated = true; + else { + result.add(new Pair(entry.getKey(), entry.getValue().count)); + if (result.size() > MAX_VALUES_TO_REPORT) { + truncated = true; + break; + } + } + } + + Collections.sort(result, new Comparator>() { + public int compare(Pair o1, Pair o2) { + return o2.getItem2().compareTo(o1.getItem2()); + } + }); + if (truncated) + result.add(new Pair("List truncated...", -1)); + return result; + } + } + + private void addRow(Sheet sheet, Object... values) { + Row row = sheet.createRow(sheet.getPhysicalNumberOfRows()); + for (Object value : values) { + Cell cell = row.createCell(row.getPhysicalNumberOfCells()); + + if (value instanceof Integer || value instanceof Long || value instanceof Double) + cell.setCellValue(Double.parseDouble(value.toString())); + else + cell.setCellValue(value.toString()); + + } + } +} diff --git a/src/org/ohdsi/whiteRabbit/utilities/CSVFileChecker.java b/src/org/ohdsi/whiteRabbit/utilities/CSVFileChecker.java new file mode 100644 index 00000000..dfd99833 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/utilities/CSVFileChecker.java @@ -0,0 +1,396 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.utilities; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import org.ohdsi.ooxml.ReadXlsxFileWithHeader; +import org.ohdsi.utilities.RandomUtilities; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.collections.OneToManyList; +import org.ohdsi.utilities.files.ReadTextFile; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.utilities.files.WriteTextFile; +import org.ohdsi.whiteRabbit.etls.ars.ARSETL; + +/** + * Checks a CSV file for formatting issues + * + * @author MSCHUEMI + */ +public class CSVFileChecker { + + private static char delimiter = ','; + private static int bufferSize = 10000; + private static int sampleSize = 1000; + private static double minFractionDateCorrect = 0.95; + private int columnCount; + private String filename; + private List errors; + private List columnInfos; + private JFrame frame; + private List header; + + public static void main(String[] args) { + JFrame frame = new JFrame("Test"); + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + frame.pack(); + frame.setVisible(true); + + CSVFileChecker checker = new CSVFileChecker(); + checker.setFrame(frame); + // checker.checkFile("S:/Data/ARS/Simulation/OUTPAT.csv"); + checker.checkSpecifiedFields("S:/Data/ARS/Simulation/", new ReadXlsxFileWithHeader(ARSETL.class.getResourceAsStream("Fields.xlsx")).iterator()); + } + + public void checkFile(String filename) { + checkFile(filename, null); + } + + private void checkFile(String filename, List columnInfos) { + this.columnInfos = columnInfos; + this.filename = filename; + errors = new ArrayList(); + int lineNr = 0; + List> rowBuffer = new ArrayList>(); + for (String line : new ReadTextFile(filename)) { + lineNr++; + List row = StringUtilities.safeSplit(line, delimiter); + + if (lineNr == 1) { // header + columnCount = row.size(); + if (columnInfos == null) + header = row; + else + for (ColumnInfo info : columnInfos) { + int column = row.indexOf(info.header); + if (column == -1) + throw new RuntimeException("Could not find column " + info.header + " in table " + filename); + else + info.column = column; + } + } else { + if (columnInfos == null) { + if (rowBuffer.size() < bufferSize) + rowBuffer.add(row); + else { + profile(rowBuffer); + rowBuffer = null; + } + } else + checkRow(lineNr, row); + } + } + if (columnInfos == null && rowBuffer.size() > 1) + profile(rowBuffer); + + if (errors.size() != 0) + if (frame != null) { + showDialog(); + } else + reportToConsole(); + } + + private void checkRow(int lineNr, List row) { + if (row.size() != columnCount) { + errors.add(new LineError(lineNr, "Incorrect number of columns (expected " + columnCount + ", found " + row.size() + ")")); + } else { + for (ColumnInfo info : columnInfos) { + String value = row.get(info.column); + if (value.trim().length() != 0) { + if (info.isInteger && !StringUtilities.isInteger(value)) + errors.add(new LineError(lineNr, "Found non-integer value ('" + value + "') where integer value expected in column " + + (info.column + 1) + " (" + info.header + ")")); + else if (info.isDateFormat1 && !isDateFormat1(value)) + errors.add(new LineError(lineNr, "Error in date ('" + value + "') in column " + (info.column + 1) + " (" + info.header + ")")); + else if (info.isReal && !StringUtilities.isNumber(value)) + errors.add(new LineError(lineNr, "Error in real number ('" + value + "') in column " + (info.column + 1) + " (" + info.header + ")")); + } + } + } + } + + private void showDialog() { + if (new ErrorDialog(frame, true, null).getAnswer()) { + String backupName = createBackup(); + copyWithoutErrorLines(backupName, filename); + } + } + + private void copyWithoutErrorLines(String source, String target) { + Set errorLineNrs = new HashSet(); + for (LineError error : errors) + errorLineNrs.add(error.lineNr); + + WriteTextFile out = new WriteTextFile(target); + int lineNr = 0; + for (String line : new ReadTextFile(source)) { + lineNr++; + if (!errorLineNrs.contains(lineNr)) + out.writeln(line); + } + out.close(); + System.out.println("Removed " + errorLineNrs.size() + " lines from " + target); + } + + private String createBackup() { + String filenameWithoutExtention = filename.substring(0, filename.lastIndexOf('.')); + + String backupName = filenameWithoutExtention + ".backup"; + if (new File(backupName).exists()) { + int i = 1; + while (new File(filenameWithoutExtention + ".backup" + i).exists()) + i++; + backupName = filenameWithoutExtention + ".backup" + i; + } + + WriteTextFile out = new WriteTextFile(backupName); + for (String line : new ReadTextFile(filename)) + out.writeln(line); + out.close(); + System.out.println("Backed up " + filename + " to " + backupName); + return backupName; + } + + private class ErrorDialog extends JDialog implements ActionListener { + private static final long serialVersionUID = 4440825466397612738L; + private JButton yesButton = null; + private JButton noButton = null; + private boolean answer = false; + + public boolean getAnswer() { + return answer; + } + + public ErrorDialog(JFrame frame, boolean modal, String dummy) { + super(frame, modal); + String shortFilename = new File(filename).getName(); + setTitle("Errors found in " + shortFilename); + JPanel panel = new JPanel(); + panel.setPreferredSize(new Dimension(800, 500)); + getContentPane().add(panel); + panel.setLayout(new BorderLayout()); + + JLabel message = new JLabel("Found " + errors.size() + " errors in " + shortFilename + + ". Do you want to automatically remove these lines (a backup will be created)?"); + panel.add(message, BorderLayout.NORTH); + + StringBuilder errorText = new StringBuilder(); + for (LineError error : errors) + errorText.append(error + "\n"); + JTextArea errorArea = new JTextArea(errorText.toString()); + JScrollPane scrollPane = new JScrollPane(errorArea); + panel.add(scrollPane, BorderLayout.CENTER); + + JPanel buttonPanel = new JPanel(); + yesButton = new JButton("Yes"); + yesButton.addActionListener(this); + buttonPanel.add(yesButton); + noButton = new JButton("No"); + noButton.addActionListener(this); + buttonPanel.add(noButton); + panel.add(buttonPanel, BorderLayout.SOUTH); + + pack(); + setLocationRelativeTo(frame); + setVisible(true); + } + + public void actionPerformed(ActionEvent e) { + if (yesButton == e.getSource()) { + answer = true; + setVisible(false); + } else if (noButton == e.getSource()) { + answer = false; + setVisible(false); + } + } + + } + + private void reportToConsole() { + for (LineError error : errors) + System.out.println(error); + } + + private void profile(List> rows) { + columnInfos = new ArrayList(columnCount); + for (int i = 0; i < header.size(); i++) + columnInfos.add(new ColumnInfo(i, header.get(i))); + + for (List row : RandomUtilities.sampleWithoutReplacement(new ArrayList>(rows), sampleSize)) { + if (row.size() == columnCount) { + for (ColumnInfo info : columnInfos) { + String value = row.get(info.column); + if (value.trim().length() != 0) { + if (StringUtilities.isInteger(value)) + info.nNotDateFormat1++; + else { + info.isInteger = false; + if (isDateFormat1(value)) { + info.nDateFormat1++; + info.isReal = false; + } else { + info.nNotDateFormat1++; + if (!StringUtilities.isNumber(value)) + info.isReal = false; + } + } + } + } + } + } + for (ColumnInfo columnInfo : columnInfos) + if (columnInfo.nDateFormat1 > 0 + && (columnInfo.nDateFormat1 / (double) (columnInfo.nDateFormat1 + columnInfo.nNotDateFormat1) > minFractionDateCorrect)) + columnInfo.isDateFormat1 = true; + + // for (int i = 0; i < columnInfos.size(); i++) + // System.out.println("Column " + columnInfos.get(i).header + "(" + i + "): IsInteger=" + columnInfos.get(i).isInteger + ", IsDate=" + // + columnInfos.get(i).isDateFormat1); + + int lineNr = 1; // Skipping header, so start at 1 + for (List row : rows) { + lineNr++; + checkRow(lineNr, row); + } + } + + public static boolean isDateFormat1(String string) { + if (string.length() >= 10) + if ((string.charAt(4) == '-' || string.charAt(4) == '/') || (string.charAt(4) == string.charAt(7))) + try { + int year = Integer.parseInt(string.substring(0, 4)); + if (year < 1700 || year > 3000) + return false; + int month = Integer.parseInt(string.substring(5, 7)); + if (month < 1 || month > 12) + return false; + int day = Integer.parseInt(string.substring(8, 10)); + if (day < 1 || day > 31) + return false; + return true; + } catch (Exception e) { + return false; + } + return false; + } + + public JFrame getFrame() { + return frame; + } + + public void setFrame(JFrame frame) { + this.frame = frame; + } + + private class LineError { + public int lineNr; + public String error; + + public LineError(int lineNr, String error) { + this.lineNr = lineNr; + this.error = error; + } + + public String toString() { + return "Error in line " + lineNr + ": " + error; + } + } + + private class ColumnInfo { + public ColumnInfo() { + } + + public ColumnInfo(int column, String header) { + this.header = header; + this.column = column; + } + + public int column; + public String header; + public int nDateFormat1 = 0; + public int nNotDateFormat1 = 0; + public boolean isDateFormat1 = false; // yyyy-mm-dd + public boolean isInteger = true; + public boolean isReal = true; + } + + public void checkSpecifiedFields(String folder, Iterator iterator) { + OneToManyList tableToFields = new OneToManyList(); + while (iterator.hasNext()) { + Row row = iterator.next(); + if (row.get("Table").trim().length() != 0) + tableToFields.put(row.get("Table"), row); + } + for (String table : tableToFields.keySet()) { + System.out.println("Checking " + table); + List columnInfos = new ArrayList(); + for (Row row : tableToFields.get(table)) + if (row.get("Check").equals("1")) { + ColumnInfo info = new ColumnInfo(); + info.header = row.get("Field"); + if (row.get("Type").toLowerCase().equals("integer")) { + info.isInteger = true; + info.isDateFormat1 = false; + info.isReal = false; + } else if (row.get("Type").toLowerCase().equals("real")) { + info.isInteger = false; + info.isDateFormat1 = false; + info.isReal = true; + } else if (row.get("Type").toLowerCase().equals("date")) { + info.isInteger = false; + info.isDateFormat1 = true; + info.isReal = false; + } else { + info.isInteger = false; + info.isDateFormat1 = false; + info.isReal = false; + } + columnInfos.add(info); + } + checkFile(folder + "/" + table, columnInfos); + } + } +} diff --git a/src/org/ohdsi/whiteRabbit/utilities/CodeToConceptMap.java b/src/org/ohdsi/whiteRabbit/utilities/CodeToConceptMap.java new file mode 100644 index 00000000..367ff4b4 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/utilities/CodeToConceptMap.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.utilities; + +import java.util.HashMap; +import java.util.Map; + +import org.ohdsi.utilities.collections.CountingSet; + +public class CodeToConceptMap { + + private String name; + private Map codeToData = new HashMap(); + private CountingSet codeCounts = new CountingSet(); + + public CodeToConceptMap(String name) { + this.name = name; + } + + public void add(String code, String description, int targetConceptId, String targetCode, String targetDescription) { + CodeData data = codeToData.get(code); + if (data == null) { + data = new CodeData(); + data.description = description; + codeToData.put(code, data); + data.targetCodes = new String[] { targetCode }; + data.targetDescriptions = new String[] { targetDescription }; + data.targetConceptIds = new int[] { targetConceptId }; + } else { + String[] targetCodes = new String[data.targetCodes.length + 1]; + String[] targetDescriptions = new String[data.targetDescriptions.length + 1]; + int[] targetConceptIds = new int[data.targetConceptIds.length + 1]; + System.arraycopy(data.targetCodes, 0, targetCodes, 0, data.targetCodes.length); + System.arraycopy(data.targetDescriptions, 0, targetDescriptions, 0, data.targetDescriptions.length); + System.arraycopy(data.targetConceptIds, 0, targetConceptIds, 0, data.targetConceptIds.length); + targetCodes[targetCodes.length - 1] = targetCode; + targetDescriptions[targetDescriptions.length - 1] = targetDescription; + targetConceptIds[targetConceptIds.length - 1] = targetConceptId; + data.targetCodes = targetCodes; + data.targetDescriptions = targetDescriptions; + data.targetConceptIds = targetConceptIds; + } + } + + public String getName() { + return name; + } + + public Integer getConceptId(String code) { + codeCounts.add(code); + CodeData data = codeToData.get(code); + if (data == null) { + return 0; + } else + return data.targetConceptIds[0]; + } + + public int[] getConceptIds(String code) { + codeCounts.add(code); + CodeData data = codeToData.get(code); + if (data == null) + return new int[0]; + else + return data.targetConceptIds; + } + + public CountingSet getCodeCounts() { + return codeCounts; + } + + public CodeData getCodeData(String code) { + return codeToData.get(code); + } + + public class CodeData { + public String description; + public int[] targetConceptIds; + public String[] targetCodes; + public String[] targetDescriptions; + } +} diff --git a/src/org/ohdsi/whiteRabbit/utilities/ConditionEraGenerator.java b/src/org/ohdsi/whiteRabbit/utilities/ConditionEraGenerator.java new file mode 100644 index 00000000..5111b453 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/utilities/ConditionEraGenerator.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.utilities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.collections.IntegerComparator; +import org.ohdsi.utilities.collections.LongComparator; +import org.ohdsi.utilities.files.Row; + +/** + * Creates drug_eras for a single person + * + * @author MSCHUEMI + */ +public class ConditionEraGenerator { + + public static int PERSISTENCE_WINDOW = 30; + public static int TYPE_CONCEPT_ID = 38000247; + public static int CONDITION_ERA_ID = 1; + private List conditions = new ArrayList(); + + public void addCondition(int personId, long startDate, long endDate, int conceptId) { + if (startDate != StringUtilities.MISSING_DATE) + conditions.add(new ConditionOccurence(personId, startDate, endDate, conceptId)); + } + + public List generateRows() { + if (conditions.size() == 0) + return Collections.emptyList(); + + List rows = new ArrayList(); + Collections.sort(conditions, new Comparator() { + + @Override + public int compare(ConditionOccurence o1, ConditionOccurence o2) { + int result = IntegerComparator.compare(o1.personId, o2.personId); + if (result == 0) + result = LongComparator.compare(o1.startDate, o2.startDate); + return result; + } + }); + + int oldPersonId = Integer.MIN_VALUE; + List personExposures = new ArrayList(); + for (ConditionOccurence exposure : conditions) + if (exposure.personId == oldPersonId) + personExposures.add(exposure); + else { + processPerson(personExposures, rows); + personExposures.clear(); + oldPersonId = exposure.personId; + } + processPerson(personExposures, rows); + return rows; + } + + private void processPerson(List personExposures, List rows) { + Map conceptIdToLastExposure = new HashMap(); + for (ConditionOccurence condition : personExposures) { + ConditionOccurence lastCondition = conceptIdToLastExposure.get(condition.conceptId); + if (lastCondition == null) + conceptIdToLastExposure.put(condition.conceptId, condition); + else if (lastCondition.endDate + PERSISTENCE_WINDOW >= condition.startDate) { + lastCondition.endDate = condition.endDate; + lastCondition.conditionCount++; + } else { + Row row = lastCondition.toRow(); + if (row != null) + rows.add(row); + conceptIdToLastExposure.put(condition.conceptId, condition); + } + } + for (ConditionOccurence exposure : conceptIdToLastExposure.values()) { + Row row = exposure.toRow(); + if (row != null) + rows.add(row); + } + } + + private class ConditionOccurence { + public int personId; + public long startDate; + public long endDate; + public int conceptId; + public int conditionCount = 1; + + public ConditionOccurence(int personId, long startDate, long endDate, int conceptId) { + this.personId = personId; + this.startDate = startDate; + this.endDate = endDate; + this.conceptId = conceptId; + } + + public Row toRow() { + Row row = new Row(); + row.add("condition_era_id", CONDITION_ERA_ID++); + row.add("person_id", personId); + row.add("condition_concept_id", conceptId); + if (startDate == StringUtilities.MISSING_DATE) + return null; + row.add("condition_era_start_date", StringUtilities.daysToDatabaseDateString(startDate)); + if (endDate == StringUtilities.MISSING_DATE) + row.add("condition_era_end_date", StringUtilities.daysToDatabaseDateString(startDate)); + else + row.add("condition_era_end_date", StringUtilities.daysToDatabaseDateString(endDate)); + row.add("condition_type_concept_id", TYPE_CONCEPT_ID); + row.add("condition_occurrence_count", conditionCount); + return row; + } + + } +} diff --git a/src/org/ohdsi/whiteRabbit/utilities/DrugEraGenerator.java b/src/org/ohdsi/whiteRabbit/utilities/DrugEraGenerator.java new file mode 100644 index 00000000..c2a0d675 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/utilities/DrugEraGenerator.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.utilities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.collections.IntegerComparator; +import org.ohdsi.utilities.collections.LongComparator; +import org.ohdsi.utilities.files.Row; + +/** + * Creates drug_eras for a single person + * + * @author MSCHUEMI + */ +public class DrugEraGenerator { + + public static int PERSISTENCE_WINDOW = 30; + public static int TYPE_CONCEPT_ID = 38000182; + public static int DRUG_ERA_ID = 1; + private List exposures = new ArrayList(); + + public void addExposure(int personId, long startDate, long endDate, int conceptId) { + if (startDate != StringUtilities.MISSING_DATE) + exposures.add(new DrugExposure(personId, startDate, endDate, conceptId)); + } + + public List generateRows() { + if (exposures.size() == 0) + return Collections.emptyList(); + + List rows = new ArrayList(); + Collections.sort(exposures, new Comparator() { + + @Override + public int compare(DrugExposure o1, DrugExposure o2) { + int result = IntegerComparator.compare(o1.personId, o2.personId); + if (result == 0) + result = LongComparator.compare(o1.startDate, o2.startDate); + return result; + } + }); + + int oldPersonId = Integer.MIN_VALUE; + List personExposures = new ArrayList(); + for (DrugExposure exposure : exposures) + if (exposure.personId == oldPersonId) + personExposures.add(exposure); + else { + processPerson(personExposures, rows); + personExposures.clear(); + oldPersonId = exposure.personId; + } + processPerson(personExposures, rows); + return rows; + } + + private void processPerson(List personExposures, List rows) { + Map conceptIdToLastExposure = new HashMap(); + for (DrugExposure exposure : personExposures) { + DrugExposure lastExposure = conceptIdToLastExposure.get(exposure.conceptId); + if (lastExposure == null) + conceptIdToLastExposure.put(exposure.conceptId, exposure); + else if (lastExposure.endDate + PERSISTENCE_WINDOW >= exposure.startDate) { + lastExposure.endDate = exposure.endDate; + lastExposure.exposureCount++; + } else { + rows.add(lastExposure.toRow()); + conceptIdToLastExposure.put(exposure.conceptId, exposure); + } + } + for (DrugExposure exposure : conceptIdToLastExposure.values()) + rows.add(exposure.toRow()); + } + + private class DrugExposure { + public int personId; + public long startDate; + public long endDate; + public int conceptId; + public int exposureCount = 1; + + public DrugExposure(int personId, long startDate, long endDate, int conceptId) { + this.personId = personId; + this.startDate = startDate; + this.endDate = endDate; + this.conceptId = conceptId; + } + + public Row toRow() { + Row row = new Row(); + row.add("drug_era_id", DRUG_ERA_ID++); + row.add("person_id", personId); + row.add("drug_concept_id", conceptId); + if (startDate == StringUtilities.MISSING_DATE) + row.add("drug_era_start_date", ""); + else + row.add("drug_era_start_date", StringUtilities.daysToDatabaseDateString(startDate)); + if (endDate == StringUtilities.MISSING_DATE) + row.add("drug_era_end_date", ""); + else + row.add("drug_era_end_date", StringUtilities.daysToDatabaseDateString(endDate)); + row.add("drug_type_concept_id", TYPE_CONCEPT_ID); + row.add("drug_exposure_count", exposureCount); + return row; + } + } +} diff --git a/src/org/ohdsi/whiteRabbit/utilities/ETLUtils.java b/src/org/ohdsi/whiteRabbit/utilities/ETLUtils.java new file mode 100644 index 00000000..9fbbe464 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/utilities/ETLUtils.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.utilities; + +import javax.swing.JOptionPane; + +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.whiteRabbit.DbSettings; +import org.ohdsi.whiteRabbit.ObjectExchange; + +public class ETLUtils { + public static boolean databaseAlreadyExists(DbSettings dbSettings) { + RichConnection connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + if (connection.getDatabaseNames().contains(dbSettings.database.toLowerCase())) { + if (ObjectExchange.frame == null) { + System.out.println("DB already exists. Exiting"); + return true; + } else { + String message = "A DB called '" + dbSettings.database + "' alread exists. Do you want to remove it before proceeding?"; + String title = "CDM database already exists"; + int answer = JOptionPane.showConfirmDialog(ObjectExchange.frame, message, title, JOptionPane.YES_NO_OPTION); + if (answer == JOptionPane.YES_OPTION) { + StringUtilities.outputWithTime("Dropping database " + dbSettings.database); + connection.dropDatabaseIfExists(dbSettings.database); + return false; + } else { + System.out.println("DB already exists. Exiting"); + return true; + } + } + } else + return false; + } +} diff --git a/src/org/ohdsi/whiteRabbit/utilities/QCSampleConstructor.java b/src/org/ohdsi/whiteRabbit/utilities/QCSampleConstructor.java new file mode 100644 index 00000000..c0bbca25 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/utilities/QCSampleConstructor.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.utilities; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.files.MultiRowIterator.MultiRowSet; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.utilities.files.RowUtilities; +import org.ohdsi.utilities.files.WriteCSVFile; +import org.ohdsi.whiteRabbit.DbSettings; + +/** + * Creates a sample of patient records pre and post ETL for Quality Control + * + * @author MSCHUEMI + */ +public class QCSampleConstructor { + + public static double sampleProbability = 0.001; + private String folder; + private Random random = new Random(0); + private Set sampledPersonIds; + private Map conceptIdToName; + + public QCSampleConstructor(String folder) { + File f = new File(folder); + + if (f.exists()) { + System.out.println("Folder " + folder + " exists: deleting all entries in folder"); + for (File file : f.listFiles()) + file.delete(); + } else { + System.out.println("Folder " + folder + " does not exists. Creating"); + f.mkdir(); + } + this.folder = folder; + sampledPersonIds = new HashSet(); + } + + public void registerPersonData(String table, Row row, Long personId) { + if (random.nextDouble() < sampleProbability) { + sampledPersonIds.add(personId); + MultiRowSet multiRowSet = new MultiRowSet(new String[] { table }); + multiRowSet.get(table).add(row); + outputToFile(multiRowSet, folder + "/" + personId + "_SOURCE.csv"); + } + } + + public void registerPersonData(MultiRowSet multiRowSet, Long personId) { + if (random.nextDouble() < sampleProbability) { + sampledPersonIds.add(personId); + outputToFile(multiRowSet, folder + "/" + personId + "_SOURCE.csv"); + } + } + + public void addCdmData(DbSettings cdmDbSettings, DbSettings vocabDbSettings) { + StringUtilities.outputWithTime("Adding CDM data to sample for quality control"); + loadConceptIdToName(vocabDbSettings); + RichConnection connection = new RichConnection(cdmDbSettings.server, cdmDbSettings.domain, cdmDbSettings.user, cdmDbSettings.password, + cdmDbSettings.dbType); + connection.use(cdmDbSettings.database); + List tables = getTablesWithPersonIdField(connection, cdmDbSettings.database); + for (Long personId : sampledPersonIds) { + WriteCSVFile out = new WriteCSVFile(folder + "/" + personId + "_CDM.csv"); + for (String table : tables) { + String sortField = null; + for (String fieldName : connection.getFieldNames(table)) + if (fieldName.endsWith("_DATE")) { + sortField = fieldName; + break; + } + + boolean first = true; + for (Row row : connection.query("SELECT * FROM " + table + " WHERE person_id = " + personId + + (sortField == null ? "" : " ORDER BY " + sortField))) { + if (first) { + first = false; + List tableHeader = new ArrayList(2); + tableHeader.add("Table:"); + tableHeader.add(table); + out.write(tableHeader); + + List headerPlus = new ArrayList(); + for (String fieldName : row.getFieldNames()) { + headerPlus.add(fieldName); + if (fieldName.endsWith("_CONCEPT_ID")) + headerPlus.add("(" + fieldName.replace("_CONCEPT_ID", "_CONCEPT_NAME") + ")"); + } + out.write(headerPlus); + } + List rowPlus = new ArrayList(); + for (String fieldName : row.getFieldNames()) { + rowPlus.add(row.get(fieldName)); + if (fieldName.endsWith("_CONCEPT_ID")) { + String conceptId = row.get(fieldName); + if (StringUtilities.isNumber(conceptId)) { + String name = conceptIdToName.get(Integer.parseInt(conceptId)); + if (name == null) + rowPlus.add(""); + else + rowPlus.add(name); + } else + rowPlus.add(""); + } + } + out.write(rowPlus); + } + if (!first) + out.write(new ArrayList()); + } + + out.close(); + } + conceptIdToName = null; + } + + private List getTablesWithPersonIdField(RichConnection connection, String database) { + List tables = new ArrayList(); + for (String table : connection.getTableNames(database)) + if (connection.getFieldNames(table).contains("PERSON_ID")) + tables.add(table); + return tables; + } + + private void loadConceptIdToName(DbSettings dbSettings) { + RichConnection connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + connection.use("vocabulary"); + conceptIdToName = new HashMap(); + for (Row row : connection.query("SELECT concept_id, concept_name FROM concept;")) + conceptIdToName.put(row.getInt("CONCEPT_ID"), row.get("CONCEPT_NAME")); + } + + private void outputToFile(MultiRowSet multiRowSet, String filename) { + List tables = new ArrayList(multiRowSet.keySet()); + Collections.sort(tables); + WriteCSVFile out = new WriteCSVFile(filename); + for (String table : tables) { + List tableHeader = new ArrayList(2); + tableHeader.add("Table:"); + tableHeader.add(table); + out.write(tableHeader); + List rows = multiRowSet.get(table); + if (rows.size() != 0) { + out.write(rows.get(0).getFieldNames()); + for (String fieldName : rows.get(0).getFieldNames()) + if (fieldName.endsWith("_DATE")) { + RowUtilities.sort(rows, fieldName); + break; + } + } + for (Row row : rows) + out.write(row.getCells()); + out.write(new ArrayList()); + } + out.close(); + } + +} diff --git a/src/org/ohdsi/whiteRabbit/utilities/SqlDump.java b/src/org/ohdsi/whiteRabbit/utilities/SqlDump.java new file mode 100644 index 00000000..2ff7d4af --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/utilities/SqlDump.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.utilities; + +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.utilities.files.WriteCSVFileWithHeader; +import org.ohdsi.whiteRabbit.DbSettings; + +public class SqlDump { + public void process(DbSettings dbSettings, String sql, String filename) { + StringUtilities.outputWithTime("Writing query results to file: " + filename); + RichConnection connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + connection.use(dbSettings.database); + WriteCSVFileWithHeader out = new WriteCSVFileWithHeader(filename); + int rowCount = 0; + for (Row row : connection.query(sql)) { + out.write(row); + rowCount++; + if (rowCount % 100000 == 0) + System.out.println(rowCount + " rows written to file"); + } + System.out.println(rowCount + " rows written to file"); + out.close(); + } +} diff --git a/src/org/ohdsi/whiteRabbit/vocabulary/Crap.java b/src/org/ohdsi/whiteRabbit/vocabulary/Crap.java new file mode 100644 index 00000000..a9a10170 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/vocabulary/Crap.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.vocabulary; + +import org.ohdsi.utilities.files.ReadTextFile; +import org.ohdsi.utilities.files.WriteTextFile; + +public class Crap { + public static String folder = "C:/home/Software/WhiteRabbit"; + + public static void main(String[] args) { + WriteTextFile out = new WriteTextFile(folder+"/SOURCE_TO_CONCEPT_MAP2.csv"); + String previousLine = null; + for (String line : new ReadTextFile(folder+ "/SOURCE_TO_CONCEPT_MAP.csv")){ + if (line.charAt(0)==',') + previousLine = previousLine + line; + else { + if (previousLine != null) + out.writeln(previousLine); + previousLine = line; + } + } + out.close(); + + } + +} diff --git a/src/org/ohdsi/whiteRabbit/vocabulary/CreateVocabIndices.sql b/src/org/ohdsi/whiteRabbit/vocabulary/CreateVocabIndices.sql new file mode 100644 index 00000000..5384f016 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/vocabulary/CreateVocabIndices.sql @@ -0,0 +1,22 @@ +CREATE INDEX INDEX_CONCEPT_CONCEPT_ID ON CONCEPT (CONCEPT_ID ASC); +CREATE INDEX INDEX_CONCEPT_CODE_ID ON CONCEPT (CONCEPT_CODE ASC); +CREATE INDEX INDEX_CONCEPT_VOCABULARY_ID ON CONCEPT (VOCABULARY_ID ASC); +CREATE INDEX INDEX_CONCEPT_CONCEPT_LEVEL ON CONCEPT (CONCEPT_LEVEL ASC); + +CREATE INDEX INDEX_VOCABULARY_VOCABULARY_ID ON VOCABULARY (VOCABULARY_ID ASC); + +CREATE INDEX INDEX_SOURCE_TO_CONCEPT_MAP_SOURCE_VOCABULARY_ID ON SOURCE_TO_CONCEPT_MAP (SOURCE_VOCABULARY_ID ASC); +CREATE INDEX INDEX_SOURCE_TO_CONCEPT_MAP_TARGET_VOCABULARY_ID ON SOURCE_TO_CONCEPT_MAP (TARGET_VOCABULARY_ID ASC); +CREATE INDEX INDEX_SOURCE_TO_CONCEPT_MAP_SOURCE_CODE ON SOURCE_TO_CONCEPT_MAP (SOURCE_CODE ASC); +CREATE INDEX INDEX_SOURCE_TO_CONCEPT_MAP_TARGET_CONCEPT_ID ON SOURCE_TO_CONCEPT_MAP (TARGET_CONCEPT_ID ASC); + +CREATE INDEX INDEX_CONCEPT_RELATIONSHIP_RELATIONSHIP_ID ON CONCEPT_RELATIONSHIP (RELATIONSHIP_ID ASC); +CREATE INDEX INDEX_CONCEPT_RELATIONSHIP_CONCEPT_ID_1 ON CONCEPT_RELATIONSHIP (CONCEPT_ID_1 ASC); +CREATE INDEX INDEX_CONCEPT_RELATIONSHIP_CONCEPT_ID_2 ON CONCEPT_RELATIONSHIP (CONCEPT_ID_2 ASC); + +CREATE INDEX INDEX_RELATIONSHIP_RELATIONSHIP_ID ON CONCEPT_RELATIONSHIP (RELATIONSHIP_ID ASC); + +CREATE INDEX INDEX_CONCEPT_ANCESTOR_ANCESTOR_CONCEPT_ID ON CONCEPT_ANCESTOR (ANCESTOR_CONCEPT_ID ASC); +CREATE INDEX INDEX_CONCEPT_ANCESTOR_DESCENDANT_CONCEPT_ID ON CONCEPT_ANCESTOR (DESCENDANT_CONCEPT_ID ASC); +CREATE INDEX INDEX_CONCEPT_ANCESTOR_MAX_LEVELS_OF_SEPARATION ON CONCEPT_ANCESTOR (MAX_LEVELS_OF_SEPARATION ASC); +CREATE INDEX INDEX_CONCEPT_ANCESTOR_MIN_LEVELS_OF_SEPARATION ON CONCEPT_ANCESTOR (MIN_LEVELS_OF_SEPARATION ASC); diff --git a/src/org/ohdsi/whiteRabbit/vocabulary/CreateVocabStructure.sql b/src/org/ohdsi/whiteRabbit/vocabulary/CreateVocabStructure.sql new file mode 100644 index 00000000..ed0a6ba0 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/vocabulary/CreateVocabStructure.sql @@ -0,0 +1,70 @@ +CREATE DATABASE IF NOT EXISTS `VOCABULARY`; +USE `VOCABULARY`; + +CREATE TABLE IF NOT EXISTS `CONCEPT` ( + `CONCEPT_ID` INT NOT NULL, + `CONCEPT_NAME` VARCHAR(260) NULL, + `VOCABULARY_ID` INT NULL, + `CONCEPT_LEVEL` INT NULL, + `CONCEPT_CODE` VARCHAR(20) NULL, + `CONCEPT_CLASS` VARCHAR(60) NULL, + `VALID_START_DATE` DATE NULL, + `VALID_END_DATE` DATE NULL, + `INVALID_REASON` CHAR(1) NULL, + PRIMARY KEY (`CONCEPT_ID`) +); + +CREATE TABLE IF NOT EXISTS `CONCEPT_ANCESTOR` ( + `ANCESTOR_CONCEPT_ID` INT NOT NULL, + `DESCENDANT_CONCEPT_ID` INT NOT NULL, + `MAX_LEVELS_OF_SEPARATION` INT NULL, + `MIN_LEVELS_OF_SEPARATION` INT NULL, + PRIMARY KEY (`ANCESTOR_CONCEPT_ID`,`DESCENDANT_CONCEPT_ID`) +); + +CREATE TABLE IF NOT EXISTS `CONCEPT_RELATIONSHIP` ( + `RELATIONSHIP_ID` INT NOT NULL, + `CONCEPT_ID_1` INT NOT NULL, + `CONCEPT_ID_2` INT NOT NULL, + `VALID_START_DATE` DATE NOT NULL, + `VALID_END_DATE` DATE NOT NULL, + `INVALID_REASON` CHAR(1) NULL, + PRIMARY KEY (`CONCEPT_ID_1`,`CONCEPT_ID_2`,`RELATIONSHIP_ID`) +); + +CREATE TABLE IF NOT EXISTS `CONCEPT_SYNONYM` ( + `CONCEPT_SYNONYM_ID` INT NOT NULL, + `CONCEPT_ID` INT NOT NULL, + `CONCEPT_SYNONYM_NAME` VARCHAR(1000) NOT NULL, + PRIMARY KEY (`CONCEPT_SYNONYM_ID`) +); + +CREATE TABLE IF NOT EXISTS `RELATIONSHIP` ( + `RELATIONSHIP_ID` INT NOT NULL, + `RELATIONSHIP_NAME` VARCHAR(256) NOT NULL, + `IS_HIERARCHICAL` CHAR(1) NULL, + `DEFINES_ANCESTRY` CHAR(1) NULL, + `REVERSE_RELATIONSHIP` INT NULL, + PRIMARY KEY (`RELATIONSHIP_ID`) +); + +CREATE TABLE IF NOT EXISTS `SOURCE_TO_CONCEPT_MAP` ( + `SOURCE_TO_CONCEPT_MAP_ID` INT NOT NULL, + `SOURCE_CODE` VARCHAR(20) NOT NULL, + `SOURCE_CODE_DESCRIPTION` VARCHAR(256) NULL, + `MAPPING_TYPE` VARCHAR(20) NOT NULL, + `TARGET_CONCEPT_ID` INT NOT NULL, + `TARGET_VOCABULARY_ID` INT NOT NULL, + `SOURCE_VOCABULARY_ID` INT NOT NULL, + `PRIMARY_MAP` CHAR(1) NULL, + `VALID_START_DATE` DATE NOT NULL, + `VALID_END_DATE` DATE NOT NULL, + `INVALID_REASON` CHAR(1) NULL, + PRIMARY KEY (`SOURCE_TO_CONCEPT_MAP_ID`) +); + +CREATE TABLE IF NOT EXISTS `VOCABULARY` ( + `VOCABULARY_ID` INT NOT NULL, + `VOCABULARY_NAME` VARCHAR(256) NOT NULL, + PRIMARY KEY (`VOCABULARY_ID`) +); diff --git a/src/org/ohdsi/whiteRabbit/vocabulary/FetchVocabularyFromServer.java b/src/org/ohdsi/whiteRabbit/vocabulary/FetchVocabularyFromServer.java new file mode 100644 index 00000000..0d98752e --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/vocabulary/FetchVocabularyFromServer.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.vocabulary; + +import org.ohdsi.databases.DbType; +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.utilities.files.WriteCSVFileWithHeader; + + +public class FetchVocabularyFromServer { + + public static String server = "RNDUSRDHIT06"; + public static String database = "OMOP_Vocabulary"; + public static String outputFolder = "S:/Data/OMOP Standard Vocabulary V4/FromJnJServer/"; + public static String[] tables = new String[]{"CONCEPT","CONCEPT_ANCESTOR","CONCEPT_RELATIONSHIP","CONCEPT_SYNONYM","RELATIONSHIP","SOURCE_TO_CONCEPT_MAP","VOCABULARY"}; + + public static void main(String[] args) { + RichConnection connection = new RichConnection(server, null, null, null, DbType.MSSQL); + connection.use(database); + + for (String table : tables){ + System.out.println("Writing table " + table); + + WriteCSVFileWithHeader out = new WriteCSVFileWithHeader(outputFolder+table+".csv"); + for (Row row : connection.query("SELECT * FROM " + table)) + out.write(row); + out.close(); + } + + + } + +} diff --git a/src/org/ohdsi/whiteRabbit/vocabulary/InsertVocabularyInServer.java b/src/org/ohdsi/whiteRabbit/vocabulary/InsertVocabularyInServer.java new file mode 100644 index 00000000..a76a88f4 --- /dev/null +++ b/src/org/ohdsi/whiteRabbit/vocabulary/InsertVocabularyInServer.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright 2014 Observational Health Data Sciences and Informatics + * + * This file is part of WhiteRabbit + * + * 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. + * + * @author Observational Health Data Sciences and Informatics + * @author Martijn Schuemie + ******************************************************************************/ +package org.ohdsi.whiteRabbit.vocabulary; + +import java.io.IOException; +import java.util.Iterator; +import java.util.zip.ZipFile; + +import javax.swing.JOptionPane; + +import org.ohdsi.databases.RichConnection; +import org.ohdsi.utilities.StringUtilities; +import org.ohdsi.utilities.files.ReadCSVFileWithHeader; +import org.ohdsi.utilities.files.Row; +import org.ohdsi.whiteRabbit.DbSettings; +import org.ohdsi.whiteRabbit.ObjectExchange; + +public class InsertVocabularyInServer { + + public static String VOCABULARY_DB_NAME = "vocabulary"; + + private static String[] tables = new String[] { "CONCEPT", "CONCEPT_ANCESTOR", "CONCEPT_RELATIONSHIP", "CONCEPT_SYNONYM", "RELATIONSHIP", + "SOURCE_TO_CONCEPT_MAP", "VOCABULARY" }; + + public void process(String sourceVocabDataFile, DbSettings dbSettings) { + RichConnection connection = new RichConnection(dbSettings.server, dbSettings.domain, dbSettings.user, dbSettings.password, dbSettings.dbType); + connection.setContext(this.getClass()); + connection.setVerbose(false); + + if (connection.getDatabaseNames().contains(VOCABULARY_DB_NAME)) { + if (ObjectExchange.frame == null) { + System.out.println("Vocab DB already exists. Exiting"); + } else { + String message = "A DB called '" + VOCABULARY_DB_NAME + "' alread exists. Do you want to remove it before proceding?"; + String title = "Vocabulary database already exists"; + int answer = JOptionPane.showConfirmDialog(ObjectExchange.frame, message, title, JOptionPane.YES_NO_OPTION); + if (answer == JOptionPane.YES_OPTION) { + StringUtilities.outputWithTime("Dropping database " + VOCABULARY_DB_NAME); + connection.dropDatabaseIfExists(VOCABULARY_DB_NAME); + } else { + System.out.println("Vocab DB already exists. Exiting"); + return; + } + } + } + + StringUtilities.outputWithTime("Creating vocabulary data structure"); + connection.executeResource("CreateVocabStructure.sql"); + connection.use("vocabulary"); + try { + ZipFile zipFile = new ZipFile(sourceVocabDataFile); + for (String table : tables) { + StringUtilities.outputWithTime("Inserting data for table " + table); + Iterator iterator = new ReadCSVFileWithHeader(zipFile.getInputStream(zipFile.getEntry(table + ".csv"))).iterator(); + connection.insertIntoTable(iterator, table, false); + } + } catch (IOException e) { + e.printStackTrace(); + } + StringUtilities.outputWithTime("Creating vocabulary indices"); + connection.executeResource("CreateVocabIndices.sql"); + StringUtilities.outputWithTime("Finished inserting vocabulary in server"); + } + +}