edu.harvard.med.iccbl.screensaver.io.screens.MedicinalCompoundsStudyCreator.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.med.iccbl.screensaver.io.screens.MedicinalCompoundsStudyCreator.java

Source

// $HeadURL$
// $Id$
//
// Copyright  2006, 2010, 2011, 2012 by the President and Fellows of Harvard College.
//
// Screensaver is an open-source project developed by the ICCB-L and NSRB labs
// at Harvard Medical School. This software is distributed under the terms of
// the GNU General Public License.

package edu.harvard.med.iccbl.screensaver.io.screens;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.cli.OptionBuilder;
import org.apache.log4j.Logger;

import edu.harvard.med.screensaver.db.DAOTransaction;
import edu.harvard.med.screensaver.db.DAOTransactionRollbackException;
import edu.harvard.med.screensaver.db.GenericEntityDAO;
import edu.harvard.med.screensaver.db.LibrariesDAO;
import edu.harvard.med.screensaver.db.ScreenDAO;
import edu.harvard.med.screensaver.io.CommandLineApplication;
import edu.harvard.med.screensaver.io.FatalParseException;
import edu.harvard.med.screensaver.io.screens.StudyCreator;
import edu.harvard.med.screensaver.io.workbook2.Cell;
import edu.harvard.med.screensaver.io.workbook2.CellVocabularyParser;
import edu.harvard.med.screensaver.io.workbook2.Workbook;
import edu.harvard.med.screensaver.io.workbook2.WorkbookParseError;
import edu.harvard.med.screensaver.io.workbook2.Worksheet;
import edu.harvard.med.screensaver.model.libraries.Reagent;
import edu.harvard.med.screensaver.model.libraries.ReagentVendorIdentifier;
import edu.harvard.med.screensaver.model.libraries.Well;
import edu.harvard.med.screensaver.model.libraries.WellKey;
import edu.harvard.med.screensaver.model.screenresults.AnnotationType;
import edu.harvard.med.screensaver.model.screens.ProjectPhase;
import edu.harvard.med.screensaver.model.screens.Screen;
import edu.harvard.med.screensaver.model.screens.ScreenType;
import edu.harvard.med.screensaver.model.screens.StudyType;
import edu.harvard.med.screensaver.model.users.LabAffiliation;
import edu.harvard.med.screensaver.model.users.LabHead;
import edu.harvard.med.screensaver.model.users.ScreeningRoomUser;

public class MedicinalCompoundsStudyCreator extends CommandLineApplication {

    // static members

    private static Logger log = Logger.getLogger(MedicinalCompoundsStudyCreator.class);

    private static final String STUDY_NAME = "100002";
    private static final String TITLE = "Annotations on Suitability of Compounds: G. Cuny & K. Lee";
    private static final String SUMMARY = "Note for screeners regarding medchem annotation:\n"
            + "For historical reasons, the screening libraries contain many compounds that may be unsuitable for further study.  These include compounds that are unstable and/or reactive, the very properties that may have contributed to apparent activity upon screening.  Although experiments are needed to establish definitively whether compounds are false (or physiologically uninteresting) positives in a given screen, some compounds have obvious, chemically offensive functionalities from a structural point of view.  Those compounds can be de-prioritized, so that attention can be directed to compounds that are more likely to be true positives.  "
            + "The medicinal chemistry group evaluates the structures of library compounds on an ongoing basis, and the following annotations are applied:\n"
            + "'A': Compounds that have no obvious liabilities and that are deemed acceptable for initial follow-up work.\n"
            + "'B': Compounds that are deemed risky for follow-up and, if resources are limiting, should probably be given lower priority than Category A compounds.\n"
            + "'C': Compounds that are not recommended for follow-up, and, if resources are limiting, should be given lower priority than Category A and B compounds.\n"
            + "No flag: Compounds that have not yet been evaluated by the medicinal chemistry group.";
    private static final String A_NO_SPECIFIC_CONCERNS = "A: No specific concerns";
    private static final String B_POTENTIAL_LIABILITY = "B: Potential liability";
    private static final String C_SUBSTANTIAL_LIABILITY = "C: Substantial liability";
    private static final SortedMap<String, String> VALID_MEDCHEM_COMMENT_VALUES = new TreeMap<String, String>();
    static {
        VALID_MEDCHEM_COMMENT_VALUES.put("A", A_NO_SPECIFIC_CONCERNS);
        VALID_MEDCHEM_COMMENT_VALUES.put("a", A_NO_SPECIFIC_CONCERNS);
        VALID_MEDCHEM_COMMENT_VALUES.put("B", B_POTENTIAL_LIABILITY);
        VALID_MEDCHEM_COMMENT_VALUES.put("b", B_POTENTIAL_LIABILITY);
        VALID_MEDCHEM_COMMENT_VALUES.put("C", C_SUBSTANTIAL_LIABILITY);
        VALID_MEDCHEM_COMMENT_VALUES.put("c", C_SUBSTANTIAL_LIABILITY);
        VALID_MEDCHEM_COMMENT_VALUES.put("", null);
    }
    private static final String MECHEM_COMMENT_COLUMN_HEADER = "Medchem comment";
    private static final String VENDOR_ID_COLUMN_HEADER = "Vendor_ID";
    private static final String VENDOR_COLUMN_HEADER = "Vendor";
    private static final String PLATE_COLUMN_HEADER = "Plate";
    private static final String WELL_COLUMN_HEADER = "Well";
    private static final String LAB_AFFILIATION_NAME = "Brigham and Women's Hospital";

    private GenericEntityDAO _dao = null;
    private ScreenDAO _screenDao = null;
    private LibrariesDAO _librariesDao = null;

    public MedicinalCompoundsStudyCreator(String[] args) {
        super(args);
        _dao = (GenericEntityDAO) getSpringBean("genericEntityDao");
        _screenDao = (ScreenDAO) getSpringBean("screenDao");
        _librariesDao = (LibrariesDAO) getSpringBean("librariesDao");
    }

    public static void main(String[] args) {
        final MedicinalCompoundsStudyCreator app = new MedicinalCompoundsStudyCreator(args);
        app.addCommandLineOption(OptionBuilder.isRequired().hasArg().withArgName("workbook file")
                .withLongOpt("input-file").create("f"));
        app.processOptions(true, true);
        app.run();
    }

    public void run() {
        _dao.doInTransaction(new DAOTransaction() {
            public void runTransaction() {
                try {
                    Screen study = _dao.findEntityByProperty(Screen.class, Screen.facilityId.getPath(), STUDY_NAME);
                    if (study != null) {
                        _screenDao.deleteStudy(study);
                    }

                    LabAffiliation labAffiliation = _dao.findEntityByProperty(LabAffiliation.class,
                            "affiliationName", LAB_AFFILIATION_NAME);
                    if (labAffiliation == null) {
                        throw new RuntimeException(
                                "expected lab affiliation " + LAB_AFFILIATION_NAME + " to exist");
                    }
                    LabHead labHead = (LabHead) StudyCreator.findOrCreateScreeningRoomUser(_dao, "Gregory", "Cuny",
                            "gcuny@rics.bwh.harvard.edu", true, labAffiliation);
                    ScreeningRoomUser leadScreener = StudyCreator.findOrCreateScreeningRoomUser(_dao, "Kyungae",
                            "Lee", "kyungae_lee@hms.harvard.edu", false, null);

                    study = new Screen(findAdministratorUser(), STUDY_NAME, leadScreener, labHead,
                            ScreenType.SMALL_MOLECULE, StudyType.IN_SILICO, ProjectPhase.ANNOTATION, TITLE);
                    study.setSummary(SUMMARY);

                    AnnotationType annotType = study.createAnnotationType("Notes on Suitability",
                            A_NO_SPECIFIC_CONCERNS + ". " + B_POTENTIAL_LIABILITY + ". " + C_SUBSTANTIAL_LIABILITY
                                    + ". "
                                    + "No value indicates the compound has not yet been reviewed by this study.",
                            false);
                    int n = loadAndCreateReagents(getCommandLineOptionValue("f", File.class), annotType);
                    _dao.saveOrUpdateEntity(study);
                    log.info("created " + n + " annotations");
                } catch (Exception e) {
                    throw new DAOTransactionRollbackException(e);
                }
            }
        });
        log.info("study successfully added to database");
    }

    protected int loadAndCreateReagents(File workbookFile, AnnotationType annotType) throws FileNotFoundException {
        int n = 0;
        Workbook workbook = new Workbook(workbookFile);

        for (int iSheet = 0; iSheet < workbook.getWorkbook().getNumberOfSheets(); ++iSheet) {
            Worksheet sheet = workbook.getWorksheet(iSheet);
            n += loadAndCreateReagentsFromSheet(sheet, annotType);
        }
        if (workbook.getHasErrors()) {
            log.error("Encountered " + workbook.getErrors().size() + " error(s).");
            for (WorkbookParseError error : workbook.getErrors()) {
                log.error(error.toString());
            }
        }
        return n;
    }

    private int loadAndCreateReagentsFromSheet(Worksheet sheet, AnnotationType annotType) {
        int n = 0;
        try {
            short iVendorColumn = (short) findColumnForHeader(sheet, VENDOR_COLUMN_HEADER);
            short iVendorIdColumn = (short) findColumnForHeader(sheet, VENDOR_ID_COLUMN_HEADER);
            short iMedChemCommentColumn = (short) findColumnForHeader(sheet, MECHEM_COMMENT_COLUMN_HEADER);
            short iPlateColumn = (short) findColumnForHeader(sheet, PLATE_COLUMN_HEADER);
            short iWellColumn = (short) findColumnForHeader(sheet, WELL_COLUMN_HEADER);
            if (iVendorColumn >= 0 && iVendorIdColumn >= 0 && iMedChemCommentColumn >= 0) {
                for (int iRow = 1; iRow < sheet.getRows(); ++iRow) { // TODO: use iterator
                    if (!sheet.getCell(iVendorColumn, iRow, true).isEmpty()
                            && !sheet.getCell(iVendorIdColumn, iRow, true).isEmpty()) {
                        Reagent reagent = findReagent(sheet.getCell(iPlateColumn, iRow, true).getInteger(),
                                sheet.getCell(iWellColumn, iRow, true).getString(),
                                sheet.getCell(iVendorIdColumn, iRow, true).getAsString(),
                                sheet.getCell(iVendorIdColumn, iRow, true).getAsString());
                        if (reagent != null) {
                            Cell medChemCommentCell = (Cell) sheet.getCell(iMedChemCommentColumn, iRow, false)
                                    .clone();
                            CellVocabularyParser<String> MEDCHEM_COMMENT_CELL_PARSER = new CellVocabularyParser<String>(
                                    VALID_MEDCHEM_COMMENT_VALUES, null, "bad annotation value");
                            String value = MEDCHEM_COMMENT_CELL_PARSER.parse(medChemCommentCell);
                            if (annotType.createAnnotationValue(reagent, value) != null) {
                                ++n;
                            }
                        }
                    }
                }
            }
            return n;
        } catch (FatalParseException e) {
            sheet.addWorkbookError(e.getClass().getName() + ":" + e.getMessage());
            return 0;
        }
    }

    private Reagent findReagent(Integer plateNumber, String wellName, String vendorName, String reagentIdentifier) {
        ReagentVendorIdentifier rvi = new ReagentVendorIdentifier(vendorName, reagentIdentifier);
        Set<Reagent> set = _librariesDao.findReagents(rvi, false);
        Reagent reagent = null;
        //Reagent reagent = _dao.findEntityById(Reagent.class, rvi);
        if (set.isEmpty()) {
            log.warn("no library contains reagent " + rvi);
        } else if (set.size() > 1) {
            throw new RuntimeException("more than one reagent found for RVI: " + rvi + ", reagents: " + set);
        } else {
            reagent = set.iterator().next();
        }

        if (reagent == null) {
            WellKey wellKey = new WellKey(plateNumber, wellName);
            //log.warn("reagent does not exist with ID " + rvi);
            Well well = _dao.findEntityById(Well.class, wellKey.toString());
            if (well == null) {
                log.error("unknown reagent " + rvi + "; looking for reagent in well, but no such well " + wellKey);
            } else {
                reagent = well.<Reagent>getLatestReleasedReagent();
                if (reagent == null) {
                    log.error("unknown reagent " + rvi + " and no reagent in well " + wellKey);
                }
            }
        }
        return reagent;
    }

    private static int findColumnForHeader(Worksheet sheet, String headerName) {
        for (Cell cell : sheet.getRow(0)) {
            if (cell.getAsString().equals(headerName))
                return cell.getColumn();
        }
        return -1;
    }
}