Skip to content

Commit

Permalink
feat: 🎸 Read/right findings in cornerstone SR
Browse files Browse the repository at this point in the history
* feat: 🎸 Read/right findings in cornerstone SR

If a cornerstone measurement has findings or findingSites, encode these
in the SR. If an SR has findings, attached these to the cornerstone
measurements when the cornerstone adapter is used.
  • Loading branch information
JamesAPetts authored Jul 9, 2020
1 parent fcdf445 commit 08df2e6
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 40 deletions.
46 changes: 34 additions & 12 deletions src/adapters/Cornerstone/ArrowAnnotate.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import CORNERSTONE_4_TAG from "./cornerstone4Tag";
import { toArray } from "../helpers.js";

const ARROW_ANNOTATE = "ArrowAnnotate";
const FINDING = "Finding";
const FINDING = "121071";
const FINDING_SITE = "G-C0E3";
const CORNERSTONEFREETEXT = "CORNERSTONEFREETEXT";

class ArrowAnnotate {
constructor() {}
Expand All @@ -21,11 +23,15 @@ class ArrowAnnotate {
group => group.ValueType === "SCOORD"
);

const findingsGroup = toArray(ContentSequence).find(
group => group.ConceptNameCodeSequence.CodeMeaning === FINDING
const findingGroup = toArray(ContentSequence).find(
group => group.ConceptNameCodeSequence.CodeValue === FINDING
);

const text = findingsGroup.ConceptCodeSequence.CodeMeaning;
const findingSiteGroups = toArray(ContentSequence).filter(
group => group.ConceptNameCodeSequence.CodeValue === FINDING_SITE
);

const text = findingGroup.ConceptCodeSequence.CodeMeaning;

const { GraphicData } = SCOORDGroup;

Expand Down Expand Up @@ -64,25 +70,41 @@ class ArrowAnnotate {
},
invalidated: true,
text,
visible: true
visible: true,
finding: findingGroup
? findingGroup.ConceptCodeSequence
: undefined,
findingSites: findingSiteGroups.map(fsg => {
return { ...fsg.ConceptCodeSequence };
})
};

return state;
}

static getTID300RepresentationArguments(tool) {
const points = [tool.handles.start];
const trackingIdentifierTextValue = `cornerstoneTools@^4.0.0:ArrowAnnotate`;

const findings = [
{
CodeValue: "CORNERSTONEFREETEXT",
let { finding, findingSites } = tool;

const TID300RepresentationArguments = {
points,
trackingIdentifierTextValue: `cornerstoneTools@^4.0.0:ArrowAnnotate`,
findingSites: findingSites || []
};

// If freetext finding isn't present, add it from the tool text.
if (!finding || f.CodeValue !== CORNERSTONEFREETEXT) {
finding = {
CodeValue: CORNERSTONEFREETEXT,
CodingSchemeDesignator: "CST4",
CodeMeaning: tool.text
}
];
};
}

TID300RepresentationArguments.finding = finding;

return { points, trackingIdentifierTextValue, findings };
return TID300RepresentationArguments;
}
}

Expand Down
32 changes: 26 additions & 6 deletions src/adapters/Cornerstone/Bidirectional.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { toArray } from "../helpers.js";
const BIDIRECTIONAL = "Bidirectional";
const LONG_AXIS = "Long Axis";
const SHORT_AXIS = "Short Axis";
const FINDING = "121071";
const FINDING_SITE = "G-C0E3";

class Bidirectional {
constructor() {}
Expand All @@ -14,6 +16,14 @@ class Bidirectional {
static getMeasurementData(MeasurementGroup) {
const { ContentSequence } = MeasurementGroup;

const findingGroup = toArray(ContentSequence).find(
group => group.ConceptNameCodeSequence.CodeValue === FINDING
);

const findingSiteGroups = toArray(ContentSequence).filter(
group => group.ConceptNameCodeSequence.CodeValue === FINDING_SITE
);

const longAxisNUMGroup = toArray(ContentSequence).find(
group => group.ConceptNameCodeSequence.CodeMeaning === LONG_AXIS
);
Expand Down Expand Up @@ -121,12 +131,15 @@ class Bidirectional {
shortestDiameter,
toolType: "Bidirectional",
toolName: "Bidirectional",
visible: true
visible: true,
finding: findingGroup
? findingGroup.ConceptCodeSequence
: undefined,
findingSites: findingSiteGroups.map(fsg => {
return { ...fsg.ConceptCodeSequence };
})
};

// TODO: To be implemented!
// Needs to add longAxis, shortAxis, longAxisLength, shortAxisLength

return state;
}

Expand All @@ -137,7 +150,12 @@ class Bidirectional {
perpendicularStart,
perpendicularEnd
} = tool.handles;
const { shortestDiameter, longestDiameter } = tool;
const {
shortestDiameter,
longestDiameter,
finding,
findingSites
} = tool;

const trackingIdentifierTextValue =
"cornerstoneTools@^4.0.0:Bidirectional";
Expand All @@ -153,7 +171,9 @@ class Bidirectional {
},
longAxisLength: longestDiameter,
shortAxisLength: shortestDiameter,
trackingIdentifierTextValue
trackingIdentifierTextValue,
finding: finding,
findingSites: findingSites || []
};
}
}
Expand Down
24 changes: 21 additions & 3 deletions src/adapters/Cornerstone/EllipticalRoi.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import CORNERSTONE_4_TAG from "./cornerstone4Tag";
import { toArray } from "../helpers.js";

const ELLIPTICALROI = "EllipticalRoi";
const FINDING = "121071";
const FINDING_SITE = "G-C0E3";

class EllipticalRoi {
constructor() {}
Expand All @@ -12,6 +14,14 @@ class EllipticalRoi {
static getMeasurementData(MeasurementGroup) {
const { ContentSequence } = MeasurementGroup;

const findingGroup = toArray(ContentSequence).find(
group => group.ConceptNameCodeSequence.CodeValue === FINDING
);

const findingSiteGroups = toArray(ContentSequence).filter(
group => group.ConceptNameCodeSequence.CodeValue === FINDING_SITE
);

const NUMGroup = toArray(ContentSequence).find(
group => group.ValueType === "NUM"
);
Expand Down Expand Up @@ -92,14 +102,20 @@ class EllipticalRoi {
}
},
invalidated: true,
visible: true
visible: true,
finding: findingGroup
? findingGroup.ConceptCodeSequence
: undefined,
findingSites: findingSiteGroups.map(fsg => {
return { ...fsg.ConceptCodeSequence };
})
};

return state;
}

static getTID300RepresentationArguments(tool) {
const { cachedStats, handles } = tool;
const { cachedStats, handles, finding, findingSites } = tool;
const { start, end } = handles;
const { area } = cachedStats;

Expand Down Expand Up @@ -134,7 +150,9 @@ class EllipticalRoi {
return {
area,
points,
trackingIdentifierTextValue
trackingIdentifierTextValue,
finding,
findingSites: findingSites || []
};
}
}
Expand Down
52 changes: 39 additions & 13 deletions src/adapters/Cornerstone/Length.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import CORNERSTONE_4_TAG from "./cornerstone4Tag";
import { toArray } from "../helpers.js";

const LENGTH = "Length";
const FINDING = "121071";
const FINDING_SITE = "G-C0E3";

class Length {
constructor() {}
Expand All @@ -12,6 +14,14 @@ class Length {
static getMeasurementData(MeasurementGroup) {
const { ContentSequence } = MeasurementGroup;

const findingGroup = toArray(ContentSequence).find(
group => group.ConceptNameCodeSequence.CodeValue === FINDING
);

const findingSiteGroups = toArray(ContentSequence).filter(
group => group.ConceptNameCodeSequence.CodeValue === FINDING_SITE
);

const NUMGroup = toArray(ContentSequence).find(
group => group.ValueType === "NUM"
);
Expand All @@ -29,36 +39,52 @@ class Length {
sopInstanceUid: ReferencedSOPInstanceUID,
frameIndex: ReferencedFrameNumber || 1,
length: NUMGroup.MeasuredValueSequence.NumericValue,
toolType: Length.toolType
toolType: Length.toolType,
handles: {
start: {},
end: {},
textBox: {
hasMoved: false,
movesIndependently: false,
drawnIndependently: true,
allowedOutsideImage: true,
hasBoundingBox: true
}
},
finding: findingGroup
? findingGroup.ConceptCodeSequence
: undefined,
findingSites: findingSiteGroups.map(fsg => {
return { ...fsg.ConceptCodeSequence };
})
};

lengthState.handles = { start: {}, end: {} };
[
lengthState.handles.start.x,
lengthState.handles.start.y,
lengthState.handles.end.x,
lengthState.handles.end.y
] = SCOORDGroup.GraphicData;

lengthState.handles.textBox = {
hasMoved: false,
movesIndependently: false,
drawnIndependently: true,
allowedOutsideImage: true,
hasBoundingBox: true
};

return lengthState;
}

static getTID300RepresentationArguments(tool) {
const point1 = tool.handles.start;
const point2 = tool.handles.end;
const { handles, finding, findingSites } = tool;
const point1 = handles.start;
const point2 = handles.end;
const distance = tool.length;

const trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:Length";

return { point1, point2, distance, trackingIdentifierTextValue };
return {
point1,
point2,
distance,
trackingIdentifierTextValue,
finding,
findingSites: findingSites || []
};
}
}

Expand Down
44 changes: 38 additions & 6 deletions src/utilities/TID300/TID300Measurement.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export default class TID300Measurement {
getMeasurement(contentSequenceEntries) {
return [
...this.getTrackingGroups(),
...this.getFindingGroups(),
...this.getFindingGroup(),
...this.getFindingSiteGroups(),
...contentSequenceEntries
];
}
Expand Down Expand Up @@ -41,12 +42,17 @@ export default class TID300Measurement {
];
}

getFindingGroups() {
let findings = this.props.findings || [];
getFindingGroup() {
let finding = this.props.finding;

return findings.map(finding => {
const { CodeValue, CodingSchemeDesignator, CodeMeaning } = finding;
return {
if (!finding) {
return [];
}

const { CodeValue, CodingSchemeDesignator, CodeMeaning } = finding;

return [
{
RelationshipType: "CONTAINS",
ValueType: "CODE",
ConceptNameCodeSequence: {
Expand All @@ -59,6 +65,32 @@ export default class TID300Measurement {
CodingSchemeDesignator, //: "99dcmjs",
CodeMeaning //: "Sample Finding"
}
}
];
}

getFindingSiteGroups() {
let findingSites = this.props.findingSites || [];

return findingSites.map(findingSite => {
const {
CodeValue,
CodingSchemeDesignator,
CodeMeaning
} = findingSite;
return {
RelationshipType: "CONTAINS",
ValueType: "CODE",
ConceptNameCodeSequence: {
CodeValue: "G-C0E3",
CodingSchemeDesignator: "SRT",
CodeMeaning: "Finding Site"
},
ConceptCodeSequence: {
CodeValue, //: "SAMPLE FINDING SITE",
CodingSchemeDesignator, //: "99dcmjs",
CodeMeaning //: "Sample Finding Site"
}
};
});
}
Expand Down

0 comments on commit 08df2e6

Please sign in to comment.