int begin, int end, DrugMentionAnnotation recurseNER,
String [] relatedStatus, int countNER, List<DrugMentionAnnotation> globalDrugNER) throws Exception
{
Iterator<MedicationEventMention> uniqueNER = nerTokenList.iterator();
DrugMentionAnnotation drugTokenAnt = null;
MedicationEventMention tokenAnt = null;
List<DrugMentionAnnotation> holdDrugNERArr = new ArrayList<DrugMentionAnnotation>();
while (uniqueNER.hasNext())
{
tokenAnt = (MedicationEventMention) uniqueNER.next();
boolean isDrugNER = false;
FSArray ocArr = tokenAnt.getOntologyConceptArr();
if (ocArr != null)
{
for (int i = 0; i < ocArr.size() && !isDrugNER; i++)
{
OntologyConcept oc = (OntologyConcept) ocArr.get(i);
String scheme = oc.getCodingScheme();
if (scheme.compareTo("RXNORM") == 0)
{
isDrugNER = true;
}
}
}
if (tokenAnt != null && (isDrugNER || relatedStatus != null))
{
boolean keepNoChangeStatus = false;
boolean maxExists = false;
int maxOffsetEnd = 0;
int holdRightEnd = end + 1;
int holdLeftStart = begin;
drugTokenAnt = new DrugMentionAnnotation(jcas, tokenAnt.getBegin(),
tokenAnt.getEnd());
tokenAnt.setTypeID(NERTypeIdentifier);
holdDrugNERArr.add(drugTokenAnt);
Iterator statusChangeItr = FSUtil.getAnnotationsIteratorInSpan(jcas, DrugChangeStatusAnnotation.type, holdLeftStart, holdRightEnd);
List holdStatusChanges = new ArrayList();
// Separate the subsection from the change status elements
int[] localSpan = getNarrativeSpansContainingGivenSpanType(jcas, drugTokenAnt.getBegin(), iBoundaryAnnType);
while (statusChangeItr.hasNext())
{
Iterator findSubSection = FSUtil.getAnnotationsIteratorInSpan(jcas, SubSectionAnnotation.type, holdLeftStart, holdRightEnd);
// if there aren't subsection in the span add to the hold
// status changes list (unless Maximum special case)
boolean isolate = false;
if (!findSubSection.hasNext())
{
DrugChangeStatusAnnotation dsa = (DrugChangeStatusAnnotation) statusChangeItr.next();
// Maximum case means the drug mention elements should
// be overridden by this value
if (((dsa.getChangeStatus().compareTo(
DrugChangeStatusElement.MAXIMUM_STATUS) != 0)
&& dsa.getEnd() < holdRightEnd)
&& (localSpan[0]<dsa.getBegin() && localSpan[1]> dsa.getEnd()))
{
holdStatusChanges.add(dsa);
} else if (dsa.getChangeStatus().compareTo(
DrugChangeStatusElement.MAXIMUM_STATUS) == 0
&& dsa.getEnd() < holdRightEnd)
{
maxExists = true;
maxOffsetEnd = dsa.getEnd();
}
} else
{
statusChangeItr.next();// Added this line to make sure the the next DrugChangeStatusAnnotation in the event that there is no subsection to look at
boolean noWeirdError = true;
boolean pullOut = false;
while (!pullOut && !isolate && findSubSection.hasNext()
&& noWeirdError)
{
try
{
// each status change is checked against all
// available sub-spans in that range
SubSectionAnnotation sub = (SubSectionAnnotation) findSubSection.next();
Iterator findStartLF = FSUtil.getAnnotationsIteratorInSpan(
jcas, NewlineToken.type, holdLeftStart, sub.getBegin() + 1);
Iterator findEndLF = FSUtil.getAnnotationsIteratorInSpan(jcas,
NewlineToken.type, sub.getEnd(), holdRightEnd);
if (findStartLF.hasNext() && findEndLF.hasNext())
{
while (findStartLF.hasNext())
{
// int countSymbols = 0;
NewlineToken nta = (NewlineToken) findStartLF.next();
// Iterator findSymbols =
// FSUtil.getAnnotationsInSpanIterator(jcas,
// SymbolToken.type,
// nta.getEnd(), sub.getBegin());
//
// while (findSymbols.hasNext())
// {
// findSymbols.next();
// countSymbols++;
// }
int countSymbols = FSUtil.countAnnotationsInSpan(jcas,
SymbolToken.type, nta.getEnd(), sub.getBegin());
if ((nta.getEnd() + countSymbols + 1) >= sub.getBegin())
{
isolate = true;
holdRightEnd = sub.getBegin();
end = sub.getBegin();
}
}
if (!isolate)
{
DrugChangeStatusAnnotation dsa = (DrugChangeStatusAnnotation) statusChangeItr.next();
holdStatusChanges.add(dsa);
pullOut = true;
sub.removeFromIndexes();
}
} else if (findEndLF.hasNext())
{
// subsection is on a prior separate line than the rest
// of the content
holdLeftStart = sub.getEnd();
// sub.removeFromIndexes();
} else if (sub.getBegin() > tokenAnt.getEnd())
{
end = sub.getBegin();
holdRightEnd = sub.getBegin();
sub.removeFromIndexes();
} else
{
holdLeftStart = sub.getEnd();
holdRightEnd = tokenAnt.getBegin();
}
} catch (NoSuchElementException nsee)
{
noWeirdError = false;
iv_logger.info(nsee.getLocalizedMessage());
}
}
}
}
// handles cases like "then discontinue" so the two change status mentions are merged and the last
// value is used for the change status i.e. 'discontinue'
List modifiedOrderDrugStatusChanges = new ArrayList();
Iterator sortStatusChanges = sortAnnotations(holdStatusChanges.toArray()).iterator();
Iterator sortNextStatusChanges = sortAnnotations(holdStatusChanges.toArray()).iterator();
// increment sortNextStatusChanges
if (sortNextStatusChanges.hasNext()) sortNextStatusChanges.next();
boolean skipNext = false;
int checkSkippedOffsetBegin = 0, checkSkippedOffsetEnd = 0;
while (sortStatusChanges.hasNext()) {
DrugChangeStatusAnnotation hos1 = (DrugChangeStatusAnnotation) sortStatusChanges.next();
if (sortNextStatusChanges.hasNext()) {
DrugChangeStatusAnnotation hos2 = (DrugChangeStatusAnnotation) sortNextStatusChanges.next();
if (hos1.getBegin() == hos2.getBegin()) {
if (hos1.getEnd() >= hos2.getEnd()) {
skipNext = true;
checkSkippedOffsetBegin = hos2.getBegin();
checkSkippedOffsetEnd = hos2.getEnd();
hos2.removeFromIndexes();
modifiedOrderDrugStatusChanges.add(hos1);
} else {
iv_logger.info("found reverse case . . need to handle");
}
} else if (!skipNext) {
modifiedOrderDrugStatusChanges.add(hos1);
} else
skipNext = false;
}
else if (checkSkippedOffsetBegin == 0 || (checkSkippedOffsetBegin != hos1.getBegin() && checkSkippedOffsetEnd != hos1.getEnd())){
modifiedOrderDrugStatusChanges.add(hos1);
}
}
Iterator orderedStatusChanges = sortAnnotations(holdStatusChanges.toArray()).iterator();
Iterator orderedDrugStatusChanges = sortAnnotations(holdStatusChanges.toArray()).iterator();
if (modifiedOrderDrugStatusChanges.size() > 0 ) {
int [] newSpan = {begin, end};
newSpan = statusChangePhraseGenerator ( jcas, begin, end, maxExists, uniqueNER,
orderedStatusChanges, modifiedOrderDrugStatusChanges, relatedStatus, drugTokenAnt,
globalDrugNER, countNER );
begin = newSpan[0];
end = newSpan[1];
if ((drugTokenAnt.getDrugChangeStatus() != null && drugTokenAnt.getDrugChangeStatus().equals(DrugChangeStatusToken.NOCHANGE)) ||
(drugTokenAnt.getDrugChangeStatus() != null && drugTokenAnt.getDrugChangeStatus().equals(DrugChangeStatusToken.OTHER))) {
keepNoChangeStatus = true;
if (drugTokenAnt.getDrugChangeStatus().equals(DrugChangeStatusToken.OTHER))
drugTokenAnt.setDrugChangeStatus(DrugChangeStatusToken.NOCHANGE);
}
// No change is default state since the change state has been handled
}
DrugMention dm = new DrugMention(jcas, begin, end);
boolean overrideStatus = false;
boolean statusFound = false;
if (!keepNoChangeStatus) {
// All entries may not be appropriate, so some
// filtering
// may need to be implemented here
JFSIndexRepository indexes = jcas.getJFSIndexRepository();
Iterator subSectionItr = indexes.getAnnotationIndex(
SubSectionAnnotation.type).iterator();
String statusKey = null;
while (subSectionItr.hasNext() && !statusFound)
{
SubSectionAnnotation ssid = (SubSectionAnnotation) subSectionItr.next();
if (ssid.getSubSectionBodyBegin() <= tokenAnt.getBegin()
&& ssid.getSubSectionBodyEnd() >= tokenAnt.getEnd())
{
// Look for special case where date comes before the
// drug mention
// A better means to locate the beginning of the chunk
// is lacking here mainly due
// to the fact that the sentence annotator cannot be
// trusted to find the beginning
// accurately.
boolean overrideDate = false;
Iterator statusSpecialDateItr = FSUtil.getAnnotationsIteratorInSpan(jcas, DateAnnotation.type, ssid.getEnd(), drugTokenAnt.getBegin());
while (statusSpecialDateItr.hasNext() && !overrideDate)
{
DateAnnotation specialDate = (DateAnnotation) statusSpecialDateItr.next();
Iterator findLF = FSUtil.getAnnotationsIteratorInSpan(jcas,
NewlineToken.type, ssid.getEnd(), specialDate.getBegin());
if (!findLF.hasNext())
{
// if (specialDate.getEnd() <=
// drugTokenAnt.getBegin() ){
drugTokenAnt.setStartDate(specialDate.getCoveredText());
overrideDate = true;
}
}
DrugChangeStatusAnnotation dsa = null;
if (orderedDrugStatusChanges.hasNext())
{
dsa = (DrugChangeStatusAnnotation) orderedDrugStatusChanges.next();
}
if (dsa != null
&& (dsa.getChangeStatus().compareTo(DrugChangeStatusElement.START_STATUS) == 0 ||
dsa.getChangeStatus().compareTo(DrugChangeStatusElement.STOP_STATUS) == 0))
{
// Should we override here? Let's get only the first
// one as an override
drugTokenAnt.setDrugChangeStatus(dsa.getChangeStatus());
} else
{
statusKey = dm.convertToChangeStatus(ssid.getCoveredText());
if (ssid.getStatus() == 1)
{
// drugTokenAnt.setCertainty(-1);
statusKey = DrugChangeStatusToken.STOP;
}
if (statusKey.compareTo(DrugChangeStatusToken.NOCHANGE) == 0)
{
Iterator oneDrugChangeStatus = FSUtil.getAnnotationsIteratorInSpan(jcas,
DrugChangeStatusAnnotation.type, ssid.getBegin(), ssid.getEnd() + 1);
if (oneDrugChangeStatus.hasNext())
{
dsa = (DrugChangeStatusAnnotation) oneDrugChangeStatus.next();
drugTokenAnt.setDrugChangeStatus(dsa.getChangeStatus());
statusKey = dsa.getChangeStatus();
}
}
drugTokenAnt.setStatus(ssid.getStatus());
dm.setDrugChangeStatusElement(statusKey, begin, end);
statusFound = true;
}
}
}
// Look for special case where status comes before the drug
// mention
// A better means to locate the beginning of the chunk is
// lacking here mainly due
// to the fact that the sentence annotator cannot be trusted to
// find the beginning
// accurately.
Iterator statusSpecialChangeItr = FSUtil.getAnnotationsIteratorInSpan(jcas, DrugChangeStatusAnnotation.type, begin - 20, drugTokenAnt.getBegin() + 1);
while (statusSpecialChangeItr.hasNext())
{
DrugChangeStatusAnnotation specialDsa = (DrugChangeStatusAnnotation) statusSpecialChangeItr.next();
if (specialDsa.getEnd() + 1 == drugTokenAnt.getBegin()
&& relatedStatus == null)
{
drugTokenAnt.setDrugChangeStatus(specialDsa.getChangeStatus());
drugTokenAnt.setChangeStatusBegin(specialDsa.getBegin());
drugTokenAnt.setChangeStatusEnd(specialDsa.getEnd());
overrideStatus = true;
}
}
}
// If a strength token is discovered before the next
// distinguished
// drug mentions then the remaining sentence is scanned for
// DrugChangeStatus.
// Iterator strengthAllItr = FSUtil.getAnnotationsIteratorInSpan(
// jcas, StrengthAnnotation.type, begin, end + 1);
//
// List holdStrength = new ArrayList();
// while (strengthAllItr.hasNext()) {
// StrengthAnnotation sa = (StrengthAnnotation) strengthAllItr
// .next();
// holdStrength.add(sa);
// }
String strengthText = null;
boolean onlyNeedOneStrength = false;
if (!keepNoChangeStatus || (drugTokenAnt.getStrength() == null)) {
List holdStrength = getAnnotationsInSpan(jcas, StrengthAnnotation.type,
begin, end + 1);
Iterator strengthItr = findUniqueMentions(holdStrength.toArray()).iterator();
double strengthValue = 0;
int holdStrengthBeginOffset = 0, holdStrengthEndOffset = 0;
while (strengthItr.hasNext() && !onlyNeedOneStrength)
{
StrengthAnnotation sa = (StrengthAnnotation) strengthItr.next();
if (holdStrengthBeginOffset != sa.getBegin()
&& holdStrengthEndOffset != sa.getEnd()
&& (relatedStatus != null))
{
double curStrengthValue = 0;
int hyphenLocation = sa.getCoveredText().indexOf("-");
String holdStrengthValue = sa.getCoveredText();
if (hyphenLocation > 0)
{
holdStrengthValue = holdStrengthValue.substring(0, hyphenLocation);
}
int spaceLocation = holdStrengthValue.indexOf(" ");
if (spaceLocation > 0)
{
holdStrengthValue = holdStrengthValue.substring(0, spaceLocation);
}
if (holdStrengthValue != null
&& holdStrengthValue.compareTo("") != 0)
curStrengthValue = new Double(dm.parseDoubleValue(holdStrengthValue)).doubleValue();
boolean findLowValue = true;
if (relatedStatus[0].compareTo(DrugChangeStatusToken.INCREASE) == 0)
{
if (curStrengthValue > strengthValue)
{
strengthValue = curStrengthValue;
strengthText = dm.getStrengthElement();
}
} else if (relatedStatus[0].compareTo(DrugChangeStatusToken.DECREASE) == 0)
{
if (findLowValue)
strengthValue = curStrengthValue;
if (curStrengthValue <= strengthValue)
{
strengthValue = curStrengthValue;
strengthText = dm.getStrengthElement();
}
findLowValue = false;
} else if (relatedStatus[0].compareTo(DrugChangeStatusToken.SUM) == 0)
{
strengthValue = curStrengthValue;
strengthText = dm.getStrengthElement();
// get first value found
}
} else
{
strengthText = dm.getStrengthElement();
if (!maxExists)
onlyNeedOneStrength = true;
else if (maxOffsetEnd + 1 == sa.getBegin())
{
onlyNeedOneStrength = true;
strengthText = sa.getCoveredText();
}
}
holdStrengthBeginOffset = sa.getBegin();
holdStrengthEndOffset = sa.getEnd();
}
}
String doseText = null;
if (!keepNoChangeStatus || (drugTokenAnt.getDosage() == null)) {
Iterator dosageItr = FSUtil.getAnnotationsIteratorInSpan(jcas,
DosagesAnnotation.type, begin, end + 1);
List holdDosages = new ArrayList();
double doseValue = 0;
int holdDoseBeginOffset = 0, holdDoseEndOffset = 0;
boolean onlyNeedOneDose = false;
while (dosageItr.hasNext() && !onlyNeedOneDose)
{
DosagesAnnotation da = (DosagesAnnotation) dosageItr.next();
if (holdDoseBeginOffset != da.getBegin()
&& holdDoseEndOffset != da.getEnd() && relatedStatus != null)
{
int removeComma = da.getCoveredText().indexOf(',');
String doseTextCheck = da.getCoveredText();
if (removeComma > 0)
{
doseTextCheck = doseTextCheck.substring(0, removeComma);
}
double curDoseValue = new Double(dm.convertFromTextToNum(doseTextCheck)).doubleValue();
boolean findLowValue = true;
if (relatedStatus[0].compareTo(DrugChangeStatusToken.INCREASE) == 0)
{
if (curDoseValue > doseValue)
{
doseValue = curDoseValue;
doseText = dm.getDosageElement();
} else if (relatedStatus[0].compareTo(DrugChangeStatusToken.SUM) == 0)
{
doseValue = curDoseValue;
doseText = dm.getDosageElement();
}
} else if (relatedStatus[0].compareTo(DrugChangeStatusToken.DECREASE) == 0)
{
if (findLowValue)
doseValue = curDoseValue;
if (curDoseValue <= doseValue)
{
doseValue = curDoseValue;
doseText = dm.getDosageElement();
}
findLowValue = false;
}
holdDosages.add(da);
holdDoseBeginOffset = da.getBegin();
holdDoseEndOffset = da.getEnd();
} else
{
doseText = dm.getDosageElement();
if (!maxExists)
onlyNeedOneDose = true;
}
}
}
String frequencyText = null;
if (!keepNoChangeStatus || (drugTokenAnt.getFrequency() == null)) {
Iterator freqItr = FSUtil.getAnnotationsIteratorInSpan(jcas,
FrequencyAnnotation.type, begin, end + 1);
List holdFreqItr = new ArrayList();
while (freqItr.hasNext())
{
holdFreqItr.add(freqItr.next());
}
Iterator frequencyItr = sortAnnotations(holdFreqItr.toArray()).iterator();
List holdFrequency = new ArrayList();
double frequencyValue = 0;
int holdFrequencyBeginOffset = 0, holdFrequencyEndOffset = 0;
boolean onlyNeedOneFrequency = false;
while (frequencyItr.hasNext() && !onlyNeedOneFrequency)
{
FrequencyAnnotation fa = (FrequencyAnnotation) frequencyItr.next();
if (dm.frequency != null
&& dm.frequency.getFrequencyMention() == null)
{
double curFrequencyValue = new Double(dm.convertFromTextToNum(fa.getCoveredText())).doubleValue();
String curFreqValueText = new Double(curFrequencyValue).toString();
dm.setFrequencyElement(curFreqValueText, fa.getBegin(), fa.getEnd());
frequencyText = curFreqValueText;
}
onlyNeedOneFrequency = true;
holdFrequency.add(fa);
holdFrequencyBeginOffset = fa.getBegin();
holdFrequencyEndOffset = fa.getEnd();
}
}
boolean foundPRN = false;
String frequencyUnitText = null;
if (!keepNoChangeStatus || (drugTokenAnt.getFrequencyUnit() == null)) {
Iterator frequencyUnitItr = FSUtil.getAnnotationsIteratorInSpan(jcas,
FrequencyUnitAnnotation.type, begin, end + 1);
List holdFrequencyUnit = new ArrayList();
double frequencyUnitValue = 0;
int holdFrequencyUnitBeginOffset = 0, holdFrequencyUnitEndOffset = 0;
boolean onlyNeedOneFrequencyUnit = false;
while (frequencyUnitItr.hasNext() && !onlyNeedOneFrequencyUnit)
{
FrequencyUnitAnnotation fua = (FrequencyUnitAnnotation) frequencyUnitItr.next();
if (holdFrequencyUnitBeginOffset != fua.getBegin()
&& holdFrequencyUnitEndOffset != fua.getEnd()
&& relatedStatus != null)
{
double curFrequencyUnitValue = new Float(fua.getPeriod()).doubleValue();
boolean findLowValue = true;
if (relatedStatus[0].compareTo(DrugChangeStatusToken.INCREASE) == 0)
{
if (curFrequencyUnitValue > frequencyUnitValue)
{
frequencyUnitValue = curFrequencyUnitValue;
frequencyUnitText = dm.getFrequencyUnitElement();
}
} else if (relatedStatus[0] == null
|| relatedStatus[0].compareTo(DrugChangeStatusToken.DECREASE) == 0)
{
if (findLowValue)
frequencyUnitValue = curFrequencyUnitValue;
if (curFrequencyUnitValue <= frequencyUnitValue)
{
frequencyUnitValue = curFrequencyUnitValue;
frequencyUnitText = dm.getFrequencyUnitElement();
}
findLowValue = false;
}
} else
{
if (fua.getPeriod() == FrequencyUnitToken.QUANTITY_PRN)
foundPRN = true;
else
{
frequencyUnitText = dm.getFrequencyUnitElement();
if (!maxExists)
{
onlyNeedOneStrength = true;
}
}
}
holdFrequencyUnit.add(fua);
holdFrequencyUnitBeginOffset = fua.getBegin();
holdFrequencyUnitEndOffset = fua.getEnd();
}
}
if (recurseNER != null && recurseNER.getDrugChangeStatus() != null
&& relatedStatus[0] != null && dm.changeStatus == null)
drugTokenAnt.setDrugChangeStatus(relatedStatus[0]);
else if (keepNoChangeStatus || (dm.changeStatus != null &&
(dm.changeStatus.getDrugChangeStatus().equals(DrugChangeStatusToken.INCREASEFROM)
|| dm.changeStatus.getDrugChangeStatus().equals(DrugChangeStatusToken.DECREASEFROM)))) {
drugTokenAnt.setDrugChangeStatus(DrugChangeStatusToken.NOCHANGE);
}
else if (dm.getDrugChangeStatusElement() != null
&& dm.getDrugChangeStatusElement().compareTo("") != 0
&& dm.getDrugChangeStatusElement().compareTo(
DrugChangeStatusToken.NOCHANGE) != 0
/*
* && drugTokenAnt.getDrugChangeStatus() != null && drugTokenAnt
* .getDrugChangeStatus().compareTo(DrugChangeStatusToken .NOCHANGE)
* == 0
*/
&& !overrideStatus)
{
// Don't want subsections here
Iterator negateStatusChanges = FSUtil.getAnnotationsIteratorInSpan(
jcas, SubSectionAnnotation.type,
dm.changeStatus.getBeginOffset(),
dm.changeStatus.getEndOffset() + 2);
if ((!negateStatusChanges.hasNext() || statusFound) && !keepNoChangeStatus) {
drugTokenAnt.setDrugChangeStatus(dm.getDrugChangeStatusElement());
drugTokenAnt.setChangeStatusBegin(dm.getChangeStatusBegin());
drugTokenAnt.setChangeStatusEnd(dm.getChangeStatusEnd());
}
else
drugTokenAnt.setDrugChangeStatus(DrugChangeStatusToken.NOCHANGE);
} else if (relatedStatus != null && relatedStatus[0] != null) {
drugTokenAnt.setDrugChangeStatus(relatedStatus[0]);
drugTokenAnt.setChangeStatusBegin(new Integer (relatedStatus[1]).intValue());
drugTokenAnt.setChangeStatusEnd(new Integer (relatedStatus[2]).intValue());
} else if (drugTokenAnt.getDrugChangeStatus() == null
|| drugTokenAnt.getDrugChangeStatus().compareTo("") == 0)
drugTokenAnt.setDrugChangeStatus(DrugChangeStatusToken.NOCHANGE);
if (!keepNoChangeStatus) {
String relatedStatusString = null;
if (relatedStatus != null && relatedStatus[0] != null)
relatedStatusString = relatedStatus[0];
float confidenceScore = alignDrugMentionAttributes( strengthText, dm , drugTokenAnt, recurseNER, relatedStatusString, statusFound, overrideStatus,
maxExists, doseText, frequencyText, frequencyUnitText);
drugTokenAnt.setConfidence(confidenceScore);
}
if (foundPRN)
drugTokenAnt.setDrugChangeStatus(drugTokenAnt.getDrugChangeStatus());
ChunkAnnotation ca = new ChunkAnnotation(jcas, begin, end);
ca.addToIndexes();
ca.setSentenceID(tokenAnt.getSentenceID());
drugTokenAnt.addToIndexes();
globalDrugNER.add(drugTokenAnt);
}
if (isDrugNER)