Skip to content
Open
98 changes: 98 additions & 0 deletions src/adapters/Cornerstone/Angle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import MeasurementReport from "./MeasurementReport.js";
import TID300Angle from "../../utilities/TID300/Angle.js";
import CORNERSTONE_4_TAG from "./cornerstone4Tag";
import GenericTool from "./GenericTool.js";

const ANGLE = "Angle";

class Angle extends GenericTool {
// TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
static getMeasurementData(MeasurementGroup) {
const toolState = super.getMeasurementData(MeasurementGroup);

const { ContentSequence } = MeasurementGroup;

const NUMGroup = this.getNumericContent(ContentSequence);

const SCOORDGroup = this.getScoordContent(ContentSequence);

let angleState = {
handles: {
start: {},
middle: {},
end: {},
textBox: {
hasMoved: false,
movesIndependently: false,
drawnIndependently: true,
allowedOutsideImage: true,
hasBoundingBox: true
}
},
rAngle: NUMGroup.MeasuredValueSequence.NumericValue,
toolName: ANGLE,
toolType: Angle.toolType
};

[
angleState.handles.start.x,
angleState.handles.start.y,
angleState.handles.middle.x,
angleState.handles.middle.y,
angleState.handles.end.x,
angleState.handles.end.y
] = SCOORDGroup.GraphicData;

angleState = Object.assign(toolState, angleState);

return angleState;
}

static getTID300RepresentationArguments(tool) {
const TID300Rep = super.getTID300RepresentationArguments(tool);
const { handles } = tool;
const point1 = handles.start;
const point2 = handles.middle;
const point3 = handles.end;
const rAngle = tool.rAngle;

const trackingIdentifierTextValue = CORNERSTONE_4_TAG + ":" + ANGLE;

return Object.assign(TID300Rep, {
point1,
point2,
point3,
rAngle,
trackingIdentifierTextValue
});
}

static checkMeasurementIntegrity(tool) {
if (tool.hasOwnProperty("rAngle")) {
return true;
} else {
return false;
}
}
}

Angle.toolType = ANGLE;
Angle.utilityToolType = ANGLE;
Angle.TID300Representation = TID300Angle;
Angle.isValidCornerstoneTrackingIdentifier = TrackingIdentifier => {
if (!TrackingIdentifier.includes(":")) {
return false;
}

const [cornerstone4Tag, toolType] = TrackingIdentifier.split(":");

if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
return false;
}

return toolType === ANGLE;
};

MeasurementReport.registerTool(Angle);

export default Angle;
71 changes: 33 additions & 38 deletions src/adapters/Cornerstone/ArrowAnnotate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,30 @@ import MeasurementReport from "./MeasurementReport.js";
import TID300Point from "../../utilities/TID300/Point.js";
import CORNERSTONE_4_TAG from "./cornerstone4Tag";
import { toArray } from "../helpers.js";
import GenericTool from "./GenericTool.js";

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

class ArrowAnnotate {
constructor() {}

class ArrowAnnotate extends GenericTool {
// TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
static getMeasurementData(MeasurementGroup) {
const toolState = super.getMeasurementData(MeasurementGroup);

const { ContentSequence } = MeasurementGroup;

const NUMGroup = toArray(ContentSequence).find(
group => group.ValueType === "NUM"
);

const SCOORDGroup = toArray(NUMGroup.ContentSequence).find(
group => group.ValueType === "SCOORD"
);
const SCOORDGroup = this.getScoordContent(ContentSequence);

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

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

const text = findingGroup.ConceptCodeSequence.CodeMeaning;

const { GraphicData } = SCOORDGroup;

const { ReferencedSOPSequence } = SCOORDGroup.ContentSequence;
const {
ReferencedSOPInstanceUID,
ReferencedFrameNumber
} = ReferencedSOPSequence;
const state = {
sopInstanceUid: ReferencedSOPInstanceUID,
frameIndex: ReferencedFrameNumber || 0,
toolType: ArrowAnnotate.toolType,
active: false,
let arrowState = {
handles: {
start: {
x: GraphicData[0],
Expand All @@ -55,8 +36,8 @@ class ArrowAnnotate {
// TODO: How do we choose where the end goes?
// Just put it pointing from the bottom right for now?
end: {
x: GraphicData[0] + 20,
y: GraphicData[1] + 20,
x: GraphicData[2],
y: GraphicData[3],
highlight: true,
active: false
},
Expand All @@ -68,28 +49,34 @@ class ArrowAnnotate {
hasBoundingBox: true
}
},
invalidated: true,
text,
visible: true,
finding: findingGroup
? findingGroup.ConceptCodeSequence
: undefined,
findingSites: findingSiteGroups.map(fsg => {
return { ...fsg.ConceptCodeSequence };
})
toolName: ARROW_ANNOTATE,
toolType: ArrowAnnotate.toolType
};

return state;
if (GraphicData.length === 6) {
arrowState.handles.start.x = GraphicData[0];
arrowState.handles.start.y = GraphicData[1];
arrowState.handles.start.z = GraphicData[2];
arrowState.handles.end.x = GraphicData[3];
arrowState.handles.end.y = GraphicData[4];
arrowState.handles.end.z = GraphicData[5];
}

arrowState = Object.assign(toolState, arrowState);

return arrowState;
}

static getTID300RepresentationArguments(tool) {
const points = [tool.handles.start];
const points = [tool.handles.start, tool.handles.end];

let { finding, findingSites } = tool;

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

Expand All @@ -106,6 +93,14 @@ class ArrowAnnotate {

return TID300RepresentationArguments;
}

static checkMeasurementIntegrity(tool) {
if (tool.hasOwnProperty("text")) {
return true;
} else {
return false;
}
}
}

ArrowAnnotate.toolType = ARROW_ANNOTATE;
Expand Down
72 changes: 24 additions & 48 deletions src/adapters/Cornerstone/Bidirectional.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,18 @@ import MeasurementReport from "./MeasurementReport";
import TID300Bidirectional from "../../utilities/TID300/Bidirectional";
import CORNERSTONE_4_TAG from "./cornerstone4Tag";
import { toArray } from "../helpers.js";
import GenericTool from "./GenericTool";

const BIDIRECTIONAL = "Bidirectional";
const LONG_AXIS = "Long Axis";
const SHORT_AXIS = "Short Axis";
const FINDING = "121071";
const FINDING_SITE = "G-C0E3";

class Bidirectional {
constructor() {}

class Bidirectional extends GenericTool {
// TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
static getMeasurementData(MeasurementGroup) {
const { ContentSequence } = MeasurementGroup;

const findingGroup = toArray(ContentSequence).find(
group => group.ConceptNameCodeSequence.CodeValue === FINDING
);
const toolState = super.getMeasurementData(MeasurementGroup);

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

const longAxisNUMGroup = toArray(ContentSequence).find(
group => group.ConceptNameCodeSequence.CodeMeaning === LONG_AXIS
Expand All @@ -40,12 +31,6 @@ class Bidirectional {
shortAxisNUMGroup.ContentSequence
).find(group => group.ValueType === "SCOORD");

const { ReferencedSOPSequence } = longAxisSCOORDGroup.ContentSequence;
const {
ReferencedSOPInstanceUID,
ReferencedFrameNumber
} = ReferencedSOPSequence;

// Long axis

const longestDiameter = String(
Expand All @@ -71,11 +56,7 @@ class Bidirectional {
)
};

const state = {
sopInstanceUid: ReferencedSOPInstanceUID,
frameIndex: ReferencedFrameNumber || 1,
toolType: Bidirectional.toolType,
active: false,
let bidirState = {
handles: {
start: {
x: longAxisSCOORDGroup.GraphicData[0],
Expand Down Expand Up @@ -125,42 +106,31 @@ class Bidirectional {
y: bottomRight.y + 10
}
},
invalidated: false,
isCreating: false,
longestDiameter,
shortestDiameter,
toolType: "Bidirectional",
toolName: "Bidirectional",
visible: true,
finding: findingGroup
? findingGroup.ConceptCodeSequence
: undefined,
findingSites: findingSiteGroups.map(fsg => {
return { ...fsg.ConceptCodeSequence };
})
toolName: BIDIRECTIONAL,
toolType: Bidirectional.toolType
};

return state;
bidirState = Object.assign(toolState, bidirState);

return bidirState;
}

static getTID300RepresentationArguments(tool) {
const TID300Rep = super.getTID300RepresentationArguments(tool);
const {
start,
end,
perpendicularStart,
perpendicularEnd
} = tool.handles;
const {
shortestDiameter,
longestDiameter,
finding,
findingSites
} = tool;
const { shortestDiameter, longestDiameter } = tool;

const trackingIdentifierTextValue =
"cornerstoneTools@^4.0.0:Bidirectional";
CORNERSTONE_4_TAG + ":" + BIDIRECTIONAL;

return {
return Object.assign(TID300Rep, {
longAxis: {
point1: start,
point2: end
Expand All @@ -171,10 +141,16 @@ class Bidirectional {
},
longAxisLength: longestDiameter,
shortAxisLength: shortestDiameter,
trackingIdentifierTextValue,
finding: finding,
findingSites: findingSites || []
};
trackingIdentifierTextValue
});
}

static checkMeasurementIntegrity(tool) {
if (tool.longestDiameter > 0 && tool.shortestDiameter > 0) {
return true;
} else {
return false;
}
}
}

Expand Down
Loading