/** * Read a DICOM image input format file encoded in a compressed transfer syntax and extract the * compressed bitstreams into a file for each frame. * * <p>The output file will be named with the specified prefix to which will be appended a 6 digit * zero padded frame number starting from 1, followed by an appropriate file name extension for * the transfer syntax. * * @param arg two parameters, the inputFile, the outputFile prefix */ public static void main(String arg[]) { try { if (arg.length == 2) { DecimalFormat sixDigitZeroPaddedFormat = new DecimalFormat("000000"); AttributeList list = new AttributeList(); list.setDecompressPixelData(false); list.read(arg[0]); String fileNameExtension = getFileNameExtensionForCompressedPixelData(list); OtherByteAttributeMultipleCompressedFrames aPixelData = (OtherByteAttributeMultipleCompressedFrames) (list.getPixelData()); byte[][] frames = aPixelData.getFrames(); for (int f = 0; f < frames.length; ++f) { String outputFilename = arg[1] + sixDigitZeroPaddedFormat.format(f + 1) + "." + fileNameExtension; System.err.println("Writing " + outputFilename); FileOutputStream o = new FileOutputStream(outputFilename); o.write(frames[f]); o.close(); } } else { System.err.println("Error: Incorrect number of arguments"); System.err.println("Usage: UnencapsulateCompressedPixelData inputFile outputFilePrefix"); System.exit(1); } } catch (Exception e) { e.printStackTrace(); } }
public void TestSafePrivateGEPACSRelated_CreatorFromList() throws Exception { AttributeList list = new AttributeList(); { Attribute a = new LongStringAttribute(new AttributeTag(0x0903, 0x0010)); a.addValue("GEIIS PACS"); list.put(a); } assertTrue( "Checking Reject Image Flag is safe", ClinicalTrialsAttributes.isSafePrivateAttribute(new AttributeTag(0x0903, 0x1010), list)); }
protected void setCurrentRemoteQuerySelection( AttributeList uniqueKeys, Attribute uniqueKey, AttributeList identifier) { currentRemoteQuerySelectionUniqueKeys = uniqueKeys; currentRemoteQuerySelectionUniqueKey = uniqueKey; currentRemoteQuerySelectionRetrieveAE = null; if (identifier != null) { Attribute aRetrieveAETitle = identifier.get(TagFromName.RetrieveAETitle); if (aRetrieveAETitle != null) currentRemoteQuerySelectionRetrieveAE = aRetrieveAETitle.getSingleStringValueOrNull(); } if (currentRemoteQuerySelectionRetrieveAE == null) { // it is legal for RetrieveAETitle to be zero length at all but the lowest levels of // the query model :( (See PS 3.4 C.4.1.1.3.2) // (so far the Leonardo is the only one that doesn't send it at all levels) // we could recurse down to the lower levels and get the union of the value there // but lets just keep it simple and ... // default to whoever it was we queried in the first place ... if (currentRemoteQueryInformationModel != null) { currentRemoteQuerySelectionRetrieveAE = currentRemoteQueryInformationModel.getCalledAETitle(); } } currentRemoteQuerySelectionLevel = null; if (identifier != null) { Attribute a = identifier.get(TagFromName.QueryRetrieveLevel); if (a != null) { currentRemoteQuerySelectionLevel = a.getSingleStringValueOrNull(); } } if (currentRemoteQuerySelectionLevel == null) { // QueryRetrieveLevel must have been (erroneously) missing in query response ... see with Dave // Harvey's code on public server // so try to guess it from unique key in tree record // Fixes [bugs.mrmf] (000224) Missing query/retrieve level in C-FIND response causes tree // select and retrieve to fail if (uniqueKey != null) { AttributeTag tag = uniqueKey.getTag(); if (tag != null) { if (tag.equals(TagFromName.PatientID)) { currentRemoteQuerySelectionLevel = "PATIENT"; } else if (tag.equals(TagFromName.StudyInstanceUID)) { currentRemoteQuerySelectionLevel = "STUDY"; } else if (tag.equals(TagFromName.SeriesInstanceUID)) { currentRemoteQuerySelectionLevel = "SERIES"; } else if (tag.equals(TagFromName.SOPInstanceUID)) { currentRemoteQuerySelectionLevel = "IMAGE"; } } } log.warning( "RemotePACs.setCurrentRemoteQuerySelection(): Guessed missing currentRemoteQuerySelectionLevel to be " + currentRemoteQuerySelectionLevel); } }
public void TestSafePrivatePhilipsPETRelated_ScaleFactors_FromList() throws Exception { AttributeList list = new AttributeList(); { Attribute a = new LongStringAttribute(new AttributeTag(0x7053, 0x0010)); a.addValue("Philips PET Private Group"); list.put(a); } assertTrue( "Checking SUV Factor is safe", ClinicalTrialsAttributes.isSafePrivateAttribute(new AttributeTag(0x7053, 0x1000), list)); assertTrue( "Checking Activity Concentration Factor is safe", ClinicalTrialsAttributes.isSafePrivateAttribute(new AttributeTag(0x7053, 0x1009), list)); }
public void TestSafePrivateGEPACSRelated_FromFile() throws Exception { AttributeList list = new AttributeList(); String testFilePath = System.getProperty("com.pixelmed.test.filepath"); // System.err.println("TestSafePrivateGEPACSRelated.TestSafePrivateGEPACSRelated_FromFile(): // testFilePath = "+testFilePath); list.read(new java.io.File(testFilePath, "philipsctwithgepacsprivateattributes.dcm")); // System.err.print("TestSafePrivateGEPACSRelated.TestSafePrivateGEPACSRelated():\n"+list); list.removeUnsafePrivateAttributes(); assertTrue( "Checking Creator is not removed", list.get(new AttributeTag(0x0903, 0x0010)) != null); assertTrue( "Checking Reject Image Flag is not removed", list.get(new AttributeTag(0x0903, 0x1010)) != null); }
// should be extracted to a utility class ... also used in DoseUtility and // DoseReporterWithLegacyOCRAndAutoSendToRegistry :( public static String getQueryRetrieveLevel(AttributeList identifier, Attribute uniqueKey) { String level = null; if (identifier != null) { Attribute a = identifier.get(TagFromName.QueryRetrieveLevel); if (a != null) { level = a.getSingleStringValueOrNull(); } } if (level == null) { // QueryRetrieveLevel must have been (erroneously) missing in query response ... see with Dave // Harvey's code on public server // so try to guess it from unique key in tree record // Fixes [bugs.mrmf] (000224) Missing query/retrieve level in C-FIND response causes tree // select and retrieve to fail if (uniqueKey != null) { AttributeTag tag = uniqueKey.getTag(); if (tag != null) { if (tag.equals(TagFromName.PatientID)) { level = "PATIENT"; } else if (tag.equals(TagFromName.StudyInstanceUID)) { level = "STUDY"; } else if (tag.equals(TagFromName.SeriesInstanceUID)) { level = "SERIES"; } else if (tag.equals(TagFromName.SOPInstanceUID)) { level = "IMAGE"; } } } log.warning( "DownloadOrTransmit.getQueryRetrieveLevel(): Guessed missing Query Retrieve Level to be " + level); } return level; }
/** * Do something with the referenced DICOM file that has been encountered. * * <p>This method needs to be implemented in a sub-class to do anything useful. The default method * does nothing. * * <p>This method does not define any exceptions and hence must handle any errors locally. * * @param mediaFileName the fully qualified path name to a DICOM file */ protected void doSomethingWithDicomFileOnMedia(String mediaFileName) { logLn("MediaImporter.doSomethingWithDicomFile(): " + mediaFileName); try { AttributeList list = new AttributeList(); list.readOnlyMetaInformationHeader(mediaFileName); String outputFileName = Attribute.getSingleStringValueOrEmptyString(list, TagFromName.MediaStorageSOPInstanceUID); if (outputFileName.length() > 0) { CopyStream.copy(new File(mediaFileName), new File(outputPath, outputFileName)); } else { throw new DicomException( "Cannot extract SOP Instance UID from \"" + mediaFileName + "\" to create output file name - ignoring"); } } catch (Exception e) { e.printStackTrace(System.err); } }
public void TestSafePrivateGEPACSRelated_AddedToList() throws Exception { AttributeList list = new AttributeList(); { Attribute a = new LongStringAttribute(new AttributeTag(0x0903, 0x0010)); a.addValue("GEIIS PACS"); list.put(a); } { Attribute a = new UnsignedShortAttribute(new AttributeTag(0x0903, 0x1010)); a.addValue(0); list.put(a); } list.removeUnsafePrivateAttributes(); assertTrue( "Checking Creator is not removed", list.get(new AttributeTag(0x0903, 0x0010)) != null); assertTrue( "Checking Reject Image Flag is not removed", ClinicalTrialsAttributes.isSafePrivateAttribute(new AttributeTag(0x0903, 0x1010), list)); }
protected CompositeInstanceContext mergePatientContext( Group group, CompositeInstanceContext newContext) { if (group.context == null) { // System.err.println("mergePatientContext(): creating new context for group"); group.context = newContext; } else { AttributeList groupList = group.context.getAttributeList(); Iterator<Attribute> newListIterator = newContext.getAttributeList().values().iterator(); while (newListIterator.hasNext()) { Attribute a = newListIterator.next(); AttributeTag tag = a.getTag(); String groupValue = Attribute.getSingleStringValueOrEmptyString(groupList, tag); String newValue = a.getSingleStringValueOrEmptyString(); if (!newValue.equals(groupValue)) { String describeTag = tag + " " + groupList.getDictionary().getFullNameFromTag(tag); System.err.println( "mergePatientContext(): in group " + group.identity + " for " + describeTag + " values differ between existing group value <" + groupValue + "> and new value <" + newValue + ">"); if (newValue.length() > 0 && (groupValue.length() == 0 || isNonZeroLengthDummyValue(groupValue))) { System.err.println( "mergePatientContext(): in group " + group.identity + " for " + describeTag + " replacing absent/empty/dummy existing group value with new value <" + newValue + ">"); groupList.put(a); } } } } return group.context; }
/** * @param arg the underlying image file name, the superimposed segmentation object file name, and * optionally the file name basis for a consumer format image rendering */ public static void main(String arg[]) { try { String underlyingFileName = arg[0]; String superimposedFileName = arg[1]; SuperimposedDicomSegments superimposedSegments = new SuperimposedDicomSegments(superimposedFileName); Vector<SuperimposedImage> superimposedImages = superimposedSegments.getSuperimposedImages(); if (arg.length > 2) { String outputFileName = arg[2]; ConsumerFormatImageMaker.convertFileToEightBitImage( underlyingFileName, outputFileName, "jpeg", 0 /*windowCenter*/, 0 /*windowWidth*/, 0 /*imageWidth*/, 0 /*imageHeight*/, 100 /*imageQuality*/, ConsumerFormatImageMaker.ALL_ANNOTATIONS, superimposedImages, null /*arrayOfPerFrameShapes*/, 0 /*debugLevel*/); } else { AttributeList underlyingList = new AttributeList(); underlyingList.read(underlyingFileName); SourceImage underlyingSourceImage = new SourceImage(underlyingList); GeometryOfVolume underlyingGeometry = new GeometryOfVolumeFromAttributeList(underlyingList); SingleImagePanel ip = new SingleImagePanel(underlyingSourceImage, null, underlyingGeometry); ip.setSuperimposedImages(superimposedImages); javax.swing.JFrame frame = new javax.swing.JFrame(); frame.add(ip); frame.setSize(underlyingSourceImage.getWidth(), underlyingSourceImage.getHeight()); frame.setVisible(true); } } catch (Exception e) { e.printStackTrace(System.err); } }
/** * @exception IOException * @exception DicomException */ public CEchoRequestCommandMessage() throws DicomException, IOException { commandField = MessageServiceElementCommand.C_ECHO_RQ; messageID = super.getNextAvailableMessageID(); int dataSetType = 0x0101; // none // NB. The Affected SOP Class UID should have no extra trailing padding, otherwise the // SCP may fail and send an A-ABORT :) (Part 5 says one null (not space) is allowed) // This is taken care of by the Attribute.write() AttributeList list = new AttributeList(); { AttributeTag t = groupLengthTag; Attribute a = new UnsignedLongAttribute(t); a.addValue(0); list.put(t, a); } { AttributeTag t = TagFromName.AffectedSOPClassUID; Attribute a = new UniqueIdentifierAttribute(t); a.addValue(SOPClass.Verification); list.put(t, a); } { AttributeTag t = TagFromName.CommandField; Attribute a = new UnsignedShortAttribute(t); a.addValue(commandField); list.put(t, a); } { AttributeTag t = TagFromName.MessageID; Attribute a = new UnsignedShortAttribute(t); a.addValue(messageID); list.put(t, a); } { AttributeTag t = TagFromName.CommandDataSetType; Attribute a = new UnsignedShortAttribute(t); a.addValue(dataSetType); list.put(t, a); } ByteArrayOutputStream bout = new ByteArrayOutputStream(); DicomOutputStream dout = new DicomOutputStream( bout, null /* no meta-header */, TransferSyntax.ImplicitVRLittleEndian); list.write(dout); bytes = bout.toByteArray(); groupLength = bytes.length - 12; bytes[8] = (byte) groupLength; // little endian bytes[9] = (byte) (groupLength >> 8); bytes[10] = (byte) (groupLength >> 16); bytes[11] = (byte) (groupLength >> 24); // System.err.println("CEchoRequestCommandMessage: bytes="+HexDump.dump(bytes)); }
protected void performRetrieve( AttributeList uniqueKeys, String selectionLevel, String retrieveAE) { try { AttributeList identifier = new AttributeList(); if (uniqueKeys != null) { identifier.putAll(uniqueKeys); { AttributeTag t = TagFromName.QueryRetrieveLevel; Attribute a = new CodeStringAttribute(t); a.addValue(selectionLevel); identifier.put(t, a); } currentRemoteQueryInformationModel.performHierarchicalMoveFrom(identifier, retrieveAE); } else { // else do nothing, since no unique key to specify what to retrieve log.warning("UniqueKeys for retrieval are null"); } } catch (Exception e) { e.printStackTrace(System.err); } }
private void testIsNotRemovedAndRetainsValue( String description, AttributeTag creatorTag, String creator, Attribute privateAttribute, String expectValue) throws DicomException { AttributeList list = new AttributeList(); { Attribute a = new LongStringAttribute(creatorTag); a.addValue(creator); list.put(a); } list.put(privateAttribute); AttributeTag privateTag = privateAttribute.getTag(); list.removeUnsafePrivateAttributes(); assertTrue("Checking Creator is not removed", list.get(creatorTag) != null); assertEquals( "Checking Creator retains value", creator, Attribute.getDelimitedStringValuesOrEmptyString(list, creatorTag)); assertTrue("Checking " + description + " is not removed", list.get(privateTag) != null); assertEquals( "Checking " + description + " retains value", expectValue, Attribute.getDelimitedStringValuesOrEmptyString(list, privateTag)); }
public void TestSafePrivateGEMRRelated_CreatorFromList() throws Exception { { AttributeList list = new AttributeList(); { Attribute a = new LongStringAttribute(new AttributeTag(0x0019, 0x0010)); a.addValue("GEMS_ACQU_01"); list.put(a); } assertTrue( "Internal Pulse Sequence Name is safe", ClinicalTrialsAttributes.isSafePrivateAttribute(new AttributeTag(0x0019, 0x109E), list)); } { AttributeList list = new AttributeList(); { Attribute a = new LongStringAttribute(new AttributeTag(0x0025, 0x0010)); a.addValue("GEMS_SERS_01"); list.put(a); } assertTrue( "Images In Series is safe", ClinicalTrialsAttributes.isSafePrivateAttribute(new AttributeTag(0x0025, 0x1007), list)); } { AttributeList list = new AttributeList(); { Attribute a = new LongStringAttribute(new AttributeTag(0x0043, 0x0010)); a.addValue("GEMS_PARM_01"); list.put(a); } assertTrue( "Scanner Table Entry + Gradient Coil Selected", ClinicalTrialsAttributes.isSafePrivateAttribute(new AttributeTag(0x0043, 0x106F), list)); } }
protected void doSomethingWithDicomFileOnMedia(String mediaFileName) { // logLn("OurFirstPassMediaImporter.doSomethingWithDicomFile(): "+mediaFileName); try { DicomInputStream i = new DicomInputStream(new File(mediaFileName)); AttributeList list = new AttributeList(); list.read(i); i.close(); String sopInstanceUID = Attribute.getSingleStringValueOrEmptyString(list, TagFromName.SOPInstanceUID); if (sopInstanceUID.length() > 0) { String studyInstanceUID = Attribute.getSingleStringValueOrEmptyString(list, TagFromName.StudyInstanceUID); if (studyInstanceUID.length() > 0) { mapOfSOPInstanceUIDToStudyInstanceUID.put(sopInstanceUID, studyInstanceUID); } else { throw new DicomException("Missing StudyInstanceUID"); } { CompositeInstanceContext cic = new CompositeInstanceContext(list, false /*forSR*/); // remove all except patient context ... cic.removeStudy(); cic.removeSeries(); cic.removeEquipment(); cic.removeFrameOfReference(); cic.removeInstance(); cic.removeSRDocumentGeneral(); Group group = addToGroups(list); // System.err.println("group = "+group); mergePatientContext(group, cic); } } else { throw new DicomException("Missing SOPInstanceUID"); } } catch (Exception e) { logLn("Error: File " + mediaFileName + " exception " + e); } }
/** * @param list * @return array of two String values, row then column orientation, else array of two nulls if * cannot be obtained */ private static String[] getPatientOrientation(AttributeList list) { String[] vPatientOrientation = null; Attribute aPatientOrientation = list.get(TagFromName.PatientOrientation); if (aPatientOrientation != null && aPatientOrientation.getVM() == 2) { try { vPatientOrientation = aPatientOrientation.getStringValues(); if (vPatientOrientation != null && vPatientOrientation.length != 2) { vPatientOrientation = null; } } catch (DicomException e) { vPatientOrientation = null; } } if (vPatientOrientation == null) { vPatientOrientation = new String[2]; } return vPatientOrientation; }
public void TestSafePrivatePhilipsPETRelated_ScaleFactors_FromFile() throws Exception { AttributeList list = new AttributeList(); String testFilePath = System.getProperty("com.pixelmed.test.filepath"); // System.err.println("TestSafePrivatePhilipsPETRelated.TestSafePrivatePhilipsPETRelated_ScaleFactors_FromFile(): testFilePath = "+testFilePath); list.read(new java.io.File(testFilePath, "philipssuvandactivityscalefactors.dcm")); // System.err.print("TestSafePrivatePhilipsPETRelated.TestSafePrivatePhilipsPETRelated_ScaleFactors():\n"+list); list.removeUnsafePrivateAttributes(); assertTrue( "Checking Creator is not removed", list.get(new AttributeTag(0x7053, 0x0010)) != null); assertTrue( "Checking SUV Factor is not removed", list.get(new AttributeTag(0x7053, 0x1000)) != null); assertTrue( "Checking Activity Concentration Factor is not removed", list.get(new AttributeTag(0x7053, 0x1009)) != null); }
/** * Generate commomn attributes for converted images. * * <p>Does NOT add ManufacturerModelName ... that should be added by caller. * * <p>Does NOT call * CodingSchemeIdentification.replaceCodingSchemeIdentificationSequenceWithCodingSchemesUsedInAttributeList * ... that should be done by caller. * * @param list * @param patientName * @param patientID * @param studyID * @param seriesNumber * @param instanceNumber * @param modality may be null * @param sopClass may be null * @throws DicomException * @throws NumberFormatException */ public static void generateCommonAttributes( AttributeList list, String patientName, String patientID, String studyID, String seriesNumber, String instanceNumber, String modality, String sopClass) throws DicomException { UIDGenerator u = new UIDGenerator(); { Attribute a = new UniqueIdentifierAttribute(TagFromName.SOPInstanceUID); a.addValue(u.getAnotherNewUID()); list.put(a); } { Attribute a = new UniqueIdentifierAttribute(TagFromName.SeriesInstanceUID); a.addValue(u.getAnotherNewUID()); list.put(a); } { Attribute a = new UniqueIdentifierAttribute(TagFromName.StudyInstanceUID); a.addValue(u.getAnotherNewUID()); list.put(a); } { Attribute a = new UniqueIdentifierAttribute(TagFromName.FrameOfReferenceUID); a.addValue(u.getAnotherNewUID()); list.put(a); } { Attribute a = new PersonNameAttribute(TagFromName.PatientName); a.addValue(patientName); list.put(a); } { Attribute a = new LongStringAttribute(TagFromName.PatientID); a.addValue(patientID); list.put(a); } { Attribute a = new DateAttribute(TagFromName.PatientBirthDate); list.put(a); } { Attribute a = new CodeStringAttribute(TagFromName.PatientSex); list.put(a); } { Attribute a = new ShortStringAttribute(TagFromName.StudyID); a.addValue(studyID); list.put(a); } { Attribute a = new PersonNameAttribute(TagFromName.ReferringPhysicianName); a.addValue("^^^^"); list.put(a); } { Attribute a = new ShortStringAttribute(TagFromName.AccessionNumber); list.put(a); } { Attribute a = new IntegerStringAttribute(TagFromName.SeriesNumber); a.addValue(seriesNumber); list.put(a); } { Attribute a = new IntegerStringAttribute(TagFromName.InstanceNumber); a.addValue(instanceNumber); list.put(a); } { Attribute a = new LongStringAttribute(TagFromName.Manufacturer); a.addValue("PixelMed"); list.put(a); } { Attribute a = new LongStringAttribute(TagFromName.DeviceSerialNumber); a.addValue(new java.rmi.dgc.VMID().toString()); list.put(a); } { Attribute a = new LongStringAttribute(TagFromName.SoftwareVersions); a.addValue(VersionAndConstants.getBuildDate()); list.put(a); } { Attribute a = new CodeStringAttribute(TagFromName.PatientOrientation); list.put(a); } { Attribute a = new CodeStringAttribute(TagFromName.BurnedInAnnotation); a.addValue("NO"); list.put(a); } { Attribute a = new CodeStringAttribute(TagFromName.RecognizableVisualFeatures); a.addValue("NO"); list.put(a); } { Attribute a = new CodeStringAttribute(TagFromName.ContentQualification); a.addValue("RESEARCH"); list.put(a); } { Attribute a = new CodeStringAttribute(TagFromName.LossyImageCompression); a.addValue("00"); list.put(a); } { Attribute a = new LongStringAttribute(TagFromName.PositionReferenceIndicator); list.put(a); } { java.util.Date currentDateTime = new java.util.Date(); String currentDate = new java.text.SimpleDateFormat("yyyyMMdd").format(currentDateTime); String currentTime = new java.text.SimpleDateFormat("HHmmss.SSS").format(currentDateTime); { Attribute a = new DateAttribute(TagFromName.StudyDate); a.addValue(currentDate); list.put(a); } { Attribute a = new TimeAttribute(TagFromName.StudyTime); a.addValue(currentTime); list.put(a); } { Attribute a = new DateAttribute(TagFromName.SeriesDate); a.addValue(currentDate); list.put(a); } { Attribute a = new TimeAttribute(TagFromName.SeriesTime); a.addValue(currentTime); list.put(a); } { Attribute a = new DateAttribute(TagFromName.ContentDate); a.addValue(currentDate); list.put(a); } { Attribute a = new TimeAttribute(TagFromName.ContentTime); a.addValue(currentTime); list.put(a); } { Attribute a = new DateAttribute(TagFromName.InstanceCreationDate); a.addValue(currentDate); list.put(a); } { Attribute a = new TimeAttribute(TagFromName.InstanceCreationTime); a.addValue(currentTime); list.put(a); } { Attribute a = new ShortStringAttribute(TagFromName.TimezoneOffsetFromUTC); a.addValue(DateTimeAttribute.getTimeZone(java.util.TimeZone.getDefault(), currentDateTime)); list.put(a); } } { Attribute a = new UniqueIdentifierAttribute(TagFromName.InstanceCreatorUID); a.addValue(VersionAndConstants.instanceCreatorUID); list.put(a); } int numberOfFrames = Attribute.getSingleIntegerValueOrDefault(list, TagFromName.NumberOfFrames, 1); int samplesPerPixel = Attribute.getSingleIntegerValueOrDefault(list, TagFromName.SamplesPerPixel, 1); if (sopClass == null) { // if modality were not null, could actually attempt to guess SOP Class based on modality here // :( sopClass = SOPClass.SecondaryCaptureImageStorage; if (numberOfFrames > 1) { if (samplesPerPixel == 1) { int bitsAllocated = Attribute.getSingleIntegerValueOrDefault(list, TagFromName.BitsAllocated, 1); if (bitsAllocated == 8) { sopClass = SOPClass.MultiframeGrayscaleByteSecondaryCaptureImageStorage; } else if (bitsAllocated == 16) { sopClass = SOPClass.MultiframeGrayscaleWordSecondaryCaptureImageStorage; } else { Attribute aPixelData = list.getPixelData(); if (aPixelData instanceof OtherFloatAttribute || aPixelData instanceof OtherDoubleAttribute) { sopClass = SOPClass.ParametricMapStorage; } } } else if (samplesPerPixel == 3) { sopClass = SOPClass.MultiframeTrueColorSecondaryCaptureImageStorage; } } } if (sopClass.equals(SOPClass.ParametricMapStorage)) { addParametricMapFrameTypeSharedFunctionalGroup(list); { Attribute a = new CodeStringAttribute(TagFromName.ContentLabel); a.addValue("LABEL1"); list.put(a); } { Attribute a = new LongStringAttribute(TagFromName.ContentDescription); list.put(a); } { Attribute a = new PersonNameAttribute(TagFromName.ContentCreatorName); list.put(a); } } if (SOPClass.isEnhancedMultiframeImageStorage(sopClass)) { if (samplesPerPixel == 1) { double windowWidth = Attribute.getSingleDoubleValueOrDefault(list, TagFromName.WindowWidth, 0); if (windowWidth > 0) { double windowCenter = Attribute.getSingleDoubleValueOrDefault(list, TagFromName.WindowCenter, 0); String voiLUTFunction = Attribute.getSingleStringValueOrDefault(list, TagFromName.VOILUTFunction, "LINEAR"); FunctionalGroupUtilities.generateVOILUTFunctionalGroup( list, numberOfFrames, windowWidth, windowCenter, voiLUTFunction); list.remove(TagFromName.WindowCenter); list.remove(TagFromName.WindowWidth); list.remove(TagFromName.VOILUTFunction); } } double rescaleSlope = Attribute.getSingleDoubleValueOrDefault(list, TagFromName.RescaleSlope, 0); if (rescaleSlope > 0) { double rescaleIntercept = Attribute.getSingleDoubleValueOrDefault(list, TagFromName.RescaleIntercept, 0); String rescaleType = Attribute.getSingleStringValueOrDefault(list, TagFromName.RescaleType, "US"); FunctionalGroupUtilities.generatePixelValueTransformationFunctionalGroup( list, numberOfFrames, rescaleSlope, rescaleIntercept, rescaleType); list.remove(TagFromName.RescaleSlope); list.remove(TagFromName.RescaleIntercept); list.remove(TagFromName.RescaleType); } // four values required { Attribute a = new CodeStringAttribute(TagFromName.ImageType); a.addValue("DERIVED"); a.addValue("PRIMARY"); a.addValue(""); a.addValue(""); list.put(a); } } else { // two values will usually do { Attribute a = new CodeStringAttribute(TagFromName.ImageType); a.addValue("DERIVED"); a.addValue("PRIMARY"); list.put(a); } } if (SOPClass.isMultiframeSecondaryCaptureImageStorage(sopClass)) { if (list.get(TagFromName.PerFrameFunctionalGroupsSequence) != null) { { AttributeTagAttribute a = new AttributeTagAttribute(TagFromName.FrameIncrementPointer); a.addValue(TagFromName.PerFrameFunctionalGroupsSequence); list.put(a); } } else { if (numberOfFrames > 1) { { AttributeTagAttribute a = new AttributeTagAttribute(TagFromName.FrameIncrementPointer); a.addValue(TagFromName.PageNumberVector); list.put(a); } { Attribute a = new IntegerStringAttribute(TagFromName.PageNumberVector); for (int page = 1; page <= numberOfFrames; ++page) { a.addValue(page); } list.put(a); } } } } System.err.println( "CommonConvertedAttributeGeneration.generateCommonAttributes(): SOP Class = " + sopClass); { Attribute a = new UniqueIdentifierAttribute(TagFromName.SOPClassUID); a.addValue(sopClass); list.put(a); } if (SOPClass.isSecondaryCaptureImageStorage(sopClass)) { { Attribute a = new CodeStringAttribute(TagFromName.ConversionType); a.addValue("WSD"); list.put(a); } } if (modality == null) { // could actually attempt to guess modality based on SOP Class here :( modality = "OT"; } { Attribute a = new CodeStringAttribute(TagFromName.Modality); a.addValue(modality); list.put(a); } { Attribute a = new SequenceAttribute(TagFromName.AcquisitionContextSequence); list.put(a); } }
protected Group addToGroups(AttributeList list) throws DicomException { Group group = null; String studyInstanceUID = Attribute.getSingleStringValueOrEmptyString(list, TagFromName.StudyInstanceUID); String sopInstanceUID = Attribute.getSingleStringValueOrEmptyString(list, TagFromName.SOPInstanceUID); if (sopInstanceUID.length() > 0) { // System.err.println("addToGroups(): checking "+sopInstanceUID); group = mapOfSOPInstanceUIDToGroup.get(sopInstanceUID); // System.err.println("addToGroups(): mapOfSOPInstanceUIDToGroup.get() = "+group); Set<String> referencedSOPInstanceUIDs = list.findAllNestedReferencedSOPInstanceUIDs(); if (group == null) { // not already there, so before creating a new group ... if (studyInstanceUID.length() > 0) { group = mapOfStudyInstanceUIDToGroup.get(studyInstanceUID); // System.err.println("addToGroups(): mapOfStudyInstanceUIDToGroup.get() = "+group); if (group == null) { // no group with instance in same study, so now try to put it in the same group as any // referenced instances if (referencedSOPInstanceUIDs != null) { for (String referencedSOPInstanceUID : referencedSOPInstanceUIDs) { group = mapOfSOPInstanceUIDToGroup.get(referencedSOPInstanceUID); // System.err.println("addToGroups(): mapOfSOPInstanceUIDToGroup.get() = "+group); if (group != null) { System.err.println( "Adding SOP Instance UID " + sopInstanceUID + " of StudyInstanceUID " + studyInstanceUID + " based on contained Referenced SOP Instance UID " + referencedSOPInstanceUID + " to group " + group.identity); break; } } } } else { System.err.println( "Adding SOP Instance UID " + sopInstanceUID + " based on StudyInstanceUID " + studyInstanceUID + " to group " + group.identity); } } else { throw new DicomException("Missing StudyInstanceUID"); } if (group == null) { // i.e., no references or did not find any of the references in existing // groups // System.err.println("addToGroups(): creating new group"); group = new Group(); System.err.println( "Creating new group for SOP Instance UID " + sopInstanceUID + " based on StudyInstanceUID " + studyInstanceUID + " group " + group.identity); groups.add(group); } } if (studyInstanceUID.length() > 0) { Group studyGroup = mapOfStudyInstanceUIDToGroup.get(studyInstanceUID); if (studyGroup == null) { System.err.println( "addToGroups(): mapOfStudyInstanceUIDToGroup.put(studyInstanceUID " + studyInstanceUID + ")"); mapOfStudyInstanceUIDToGroup.put(studyInstanceUID, group); } else if (studyGroup != group) { System.err.println( "addToGroups(): mapOfStudyInstanceUIDToGroup.get(studyInstanceUID " + studyInstanceUID + ") != null and != current group"); mergeGroups(group, studyGroup); } } group.add(sopInstanceUID); Group instanceGroup = mapOfSOPInstanceUIDToGroup.get(sopInstanceUID); if (instanceGroup == null) { mapOfSOPInstanceUIDToGroup.put(sopInstanceUID, group); } else if (instanceGroup != group) { System.err.println( "addToGroups(): mapOfSOPInstanceUIDToGroup.get(sopInstanceUID " + sopInstanceUID + ") != null and != current group"); mergeGroups(group, instanceGroup); } if (referencedSOPInstanceUIDs != null) { // group.addAll(referencedSOPInstanceUIDs); for (String referencedSOPInstanceUID : referencedSOPInstanceUIDs) { group.add(referencedSOPInstanceUID); instanceGroup = mapOfSOPInstanceUIDToGroup.get(referencedSOPInstanceUID); if (instanceGroup == null) { mapOfSOPInstanceUIDToGroup.put(referencedSOPInstanceUID, group); } else if (instanceGroup != group) { System.err.println( "addToGroups(): mapOfSOPInstanceUIDToGroup.get(referencedSOPInstanceUID " + referencedSOPInstanceUID + ") != null and != current group"); mergeGroups(group, instanceGroup); } } } } else { throw new DicomException("Missing SOPInstanceUID"); } return group; }
/** * @param filenames * @exception Exception if internal error */ public void loadMultiPanelFromSpecifiedFiles(String filenames[]) throws Exception { int nFiles = filenames.length; SingleImagePanel imagePanels[] = new SingleImagePanel[nFiles]; String orientations[][] = new String[nFiles][]; String views[] = new String[nFiles]; String lateralityViewAndModifiers[] = new String[nFiles]; String lateralities[] = new String[nFiles]; int widths[] = new int[nFiles]; int heights[] = new int[nFiles]; PixelSpacing spacing[] = new PixelSpacing[nFiles]; String rowOrientations[] = new String[nFiles]; String columnOrientations[] = new String[nFiles]; HashMap eventContexts = new HashMap(); double maximumHorizontalExtentInMm = 0; double maximumVerticalExtentInMm = 0; StructuredReport sr[] = new StructuredReport[nFiles]; int nImages = 0; int nCAD = 0; ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); for (int f = 0; f < nFiles; ++f) { try { String filename = filenames[f]; DicomInputStream distream = null; InputStream in = classLoader.getResourceAsStream(filename); if (in != null) { distream = new DicomInputStream(in); } else { distream = new DicomInputStream(new File(filename)); } AttributeList list = new AttributeList(); list.read(distream); if (list.isImage()) { int i = nImages++; System.err.println("IMAGE [" + i + "] is file " + f + " (" + filenames[f] + ")"); orientations[i] = getPatientOrientation(list); // System.err.println("IMAGE ["+i+"] orientation="+(orientations[i] == null && // orientations[i].length == 2 ? "" : (orientations[i][0] + " " + orientations[i][1]))); views[i] = getView(list); // System.err.println("IMAGE ["+i+"] view="+views[i]); lateralityViewAndModifiers[i] = getImageLateralityViewModifierAndViewModifier(list); // System.err.println("IMAGE ["+i+"] // lateralityViewAndModifiers="+lateralityViewAndModifiers[i]); // System.err.println("File "+filenames[f]+": "+lateralityViewAndModifiers[i]); lateralities[i] = getLaterality(list); // System.err.println("IMAGE ["+i+"] laterality="+lateralities[i]); spacing[i] = new PixelSpacing(list); // System.err.println("IMAGE ["+i+"] spacing="+spacing[i]); SourceImage sImg = new SourceImage(list); BufferedImage img = sImg.getBufferedImage(); widths[i] = sImg.getWidth(); heights[i] = sImg.getHeight(); boolean shareVOIEventsInStudy = false; // does not seem to work anyway, since adding VOITransform to panel constructor // :( EventContext eventContext = new EventContext(Integer.toString(i)); SingleImagePanel imagePanel = makeNewImagePanel(sImg, eventContext); imagePanel.setDemographicAndTechniqueAnnotations( new DemographicAndTechniqueAnnotations(list), "SansSerif", Font.PLAIN, 10, Color.pink); imagePanel.setOrientationAnnotations( new OrientationAnnotations(rowOrientations[i], columnOrientations[i]), "SansSerif", Font.PLAIN, 20, Color.pink); imagePanel.setPixelSpacingInSourceImage( spacing[i].getSpacing(), spacing[i].getDescription()); if (Attribute.getSingleStringValueOrEmptyString(list, TagFromName.VOILUTFunction) .equals("SIGMOID")) { imagePanel.setVOIFunctionToLogistic(); } imagePanels[i] = imagePanel; } else { throw new DicomException("Unsupported SOP Class in file " + filenames[f]); } } catch (Exception e) { // FileNotFoundException,IOException,DicomException e.printStackTrace(System.err); } } // int imagesPerRow = nImages; // i.e., 1 -> 1, 2 -> 1, 4 -> 4, 5 -> 4, 8 -> 4 // int imagesPerCol = 1; int imagesPerRow = nImages >= 8 ? 8 : nImages; // i.e., 1 -> 1, 2 -> 1, 4 -> 4, 5 -> 4, 8 -> 4 int imagesPerCol = (nImages - 1) / imagesPerRow + 1; // i.e., 1 -> 1, 2 -> 2, 4 -> 1, 5 -> 2, 8 -> 2 int singleWidth = frameWidth / imagesPerRow; int singleHeight = frameHeight / imagesPerCol; if (nImages == 1 && singleWidth > singleHeight) { singleWidth = singleWidth / 2; // use only half the screen for a single view and a landscape monitor } for (int i = 0; i < nImages; ++i) { DisplayedAreaSelection displayedAreaSelection = null; displayedAreaSelection = new DisplayedAreaSelection( widths[i], heights[i], 0, 0, widths[i], heights[i], true, // in case spacing was not supplied 0, 0, 0, 0, 0, false /*crop*/); imagePanels[i].setDisplayedAreaSelection(displayedAreaSelection); imagePanels[i].setPreTransformImageRelativeCoordinates(null); } SingleImagePanel.deconstructAllSingleImagePanelsInContainer(multiPanel); multiPanel.removeAll(); multiPanel.setLayout(new GridLayout(imagesPerCol, imagesPerRow)); multiPanel.setBackground(Color.black); for (int x = 0; x < imagesPerCol; ++x) { for (int y = 0; y < imagesPerRow; ++y) { int i = x * imagesPerRow + y; if (i < nImages) { imagePanels[i].setPreferredSize(new Dimension(singleWidth, singleHeight)); multiPanel.add(imagePanels[i]); } } } frame.getContentPane().validate(); frame.getContentPane().repaint(); }
/** @param list */ private void doCommonConstructorStuff(AttributeList list) throws DicomException { String sopClassUID = Attribute.getSingleStringValueOrEmptyString(list, TagFromName.SOPClassUID); if (SOPClass.isImageStorage(sopClassUID)) { // System.err.println("SuperimposedDicomSegments.doCommonConstructorStuff(): is an image"); SourceImage allFramesImage = new SourceImage(list); Attribute aSegmentSequence = list.get(TagFromName.SegmentSequence); Attribute aSharedFunctionalGroupsSequence = list.get(TagFromName.SharedFunctionalGroupsSequence); Attribute aPerFrameFunctionalGroupsSequence = list.get(TagFromName.PerFrameFunctionalGroupsSequence); int numberOfFrames = allFramesImage.getNumberOfBufferedImages(); if (allFramesImage != null && numberOfFrames > 0 && aSegmentSequence != null && aSegmentSequence instanceof SequenceAttribute && aSharedFunctionalGroupsSequence != null && aSharedFunctionalGroupsSequence instanceof SequenceAttribute && aPerFrameFunctionalGroupsSequence != null && aPerFrameFunctionalGroupsSequence instanceof SequenceAttribute) { System.err.println( "SuperimposedDicomSegments.doCommonConstructorStuff(): have a segmentation object with one or more frames"); SequenceAttribute saSegmentSequence = (SequenceAttribute) aSegmentSequence; int numberOfSegments = saSegmentSequence.getNumberOfItems(); if (numberOfSegments > 0) { for (int i = 0; i < numberOfSegments; ++i) { AttributeList itemList = saSegmentSequence.getItem(i).getAttributeList(); String segmentNumber = Attribute.getSingleStringValueOrEmptyString( itemList, TagFromName .SegmentNumber); // theoretically supposed to start at 1 and increase by 1, // but don't trust it if (segmentNumber.length() > 0) { int[] recommendedDisplayCIELabValues = Attribute.getIntegerValues(itemList, TagFromName.RecommendedDisplayCIELabValue); SegmentInformation si = segmentInformationBySegmentNumber.get(segmentNumber); if (si == null) { si = new SegmentInformation(segmentNumber, recommendedDisplayCIELabValues); segmentInformationBySegmentNumber.put(segmentNumber, si); } else { throw new DicomException("Duplicate segment number"); } } else { throw new DicomException("Missing segment number"); } } } else { System.err.println( "SuperimposedDicomSegments.doCommonConstructorStuff(): Error: No segments in segmentation object"); } SequenceAttribute saSharedFunctionalGroupsSequence = (SequenceAttribute) aSharedFunctionalGroupsSequence; SequenceAttribute saPerFrameFunctionalGroupsSequence = (SequenceAttribute) aPerFrameFunctionalGroupsSequence; SequenceAttribute sharedSegmentIdentificationSequence = (SequenceAttribute) (SequenceAttribute.getNamedAttributeFromWithinSequenceWithSingleItem( saSharedFunctionalGroupsSequence, TagFromName.SegmentIdentificationSequence)); int nPerFrameFunctionalGroupsSequence = saPerFrameFunctionalGroupsSequence.getNumberOfItems(); if (nPerFrameFunctionalGroupsSequence == numberOfFrames) { for (int f = 0; f < numberOfFrames; ++f) { SequenceAttribute useSegmentIdentificationSequence = sharedSegmentIdentificationSequence; if (useSegmentIdentificationSequence == null) { useSegmentIdentificationSequence = (SequenceAttribute) (saPerFrameFunctionalGroupsSequence .getItem(f) .getAttributeList() .get(TagFromName.SegmentIdentificationSequence)); } if (useSegmentIdentificationSequence != null) { Attribute aReferencedSegmentNumber = SequenceAttribute.getNamedAttributeFromWithinSequenceWithSingleItem( useSegmentIdentificationSequence, TagFromName.ReferencedSegmentNumber); String referencedSegmentNumber = aReferencedSegmentNumber == null ? "" : aReferencedSegmentNumber.getSingleStringValueOrEmptyString(); if (referencedSegmentNumber.length() > 0) { SortedSet<Integer> framesForSegment = framesForSegmentBySegmentNumber.get(referencedSegmentNumber); if (framesForSegment == null) { framesForSegment = new TreeSet<Integer>(); framesForSegmentBySegmentNumber.put(referencedSegmentNumber, framesForSegment); } framesForSegment.add(new Integer(f)); } else { throw new DicomException("Missing ReferencedSegmentNumber for frame " + f); } } else { throw new DicomException("Missing SegmentIdentificationSequence for frame " + f); } } } else { throw new DicomException( "Number of frames " + numberOfFrames + " does not match number of PerFrameFunctionalGroupsSequence items " + nPerFrameFunctionalGroupsSequence); } // SortedMap<String,SortedSet<Integer>> framesForSegmentBySegmentNumber for (String segmentNumber : framesForSegmentBySegmentNumber.keySet()) { // System.err.println("SuperimposedDicomSegments.doCommonConstructorStuff(): Making // SourceImageSubset for segmentNumber "+segmentNumber); SortedSet<Integer> framesForSegment = framesForSegmentBySegmentNumber.get(segmentNumber); int[] parentFrameNumbers = new int[framesForSegment.size()]; { int childFrameNumber = 0; for (Integer parentFrameNumber : framesForSegment) { // System.err.println("SuperimposedDicomSegments.doCommonConstructorStuff(): // parentFrameNumber["+childFrameNumber+"] = "+parentFrameNumber); parentFrameNumbers[childFrameNumber++] = parentFrameNumber.intValue(); } } SourceImage sourceImageForSegment = new SourceImageSubset(allFramesImage, parentFrameNumbers); GeometryOfVolume geometryForSegment = new GeometryOfVolumeFromAttributeList(list, parentFrameNumbers); if (!geometryForSegment.isVolumeSampledRegularlyAlongFrameDimension()) { System.err.println( "SuperimposedDicomSegments.doCommonConstructorStuff(): Warning: superimposed geometry is not a single regularly sampled volume for segment " + segmentNumber); } superimposedImagesBySegmentNumber.put( segmentNumber, new SuperimposedImage( sourceImageForSegment, geometryForSegment, segmentInformationBySegmentNumber.get(segmentNumber) .recommendedDisplayCIELabValues)); } // superimposedGeometry = new GeometryOfVolumeFromAttributeList(list); // if (!superimposedGeometry.isVolumeSampledRegularlyAlongFrameDimension()) { // System.err.println("SuperimposedDicomSegments.doCommonConstructorStuff(): Warning: // superimposed geometry is not a single regularly sampled volume"); // } } else { System.err.println( "SuperimposedDicomSegments.doCommonConstructorStuff(): Error: Not a valid segmentation object"); } } }
/** @param filename */ public SuperimposedDicomSegments(String filename) throws DicomException, IOException { // no need to call super(), does nothing AttributeList list = new AttributeList(); list.read(filename); doCommonConstructorStuff(list); }
protected void doSomethingWithDicomFileOnMedia(String mediaFileName) { // logLn("OurFirstPassMediaImporter.doSomethingWithDicomFile(): "+mediaFileName); try { DicomInputStream i = new DicomInputStream(new File(mediaFileName)); AttributeList list = new AttributeList(); list.read(i); i.close(); String sopInstanceUID = Attribute.getSingleStringValueOrEmptyString(list, TagFromName.SOPInstanceUID); if (sopInstanceUID.length() > 0) { Group group = mapOfSOPInstanceUIDToGroup.get(sopInstanceUID); // System.err.println("group = "+group); // System.err.println("Groups size = "+groups.size()); if (group == null) { if (groups.size() == 1) { group = groups.toArray(singleGroupArray)[0]; } else { throw new DicomException( "Cannot merge context for second set if more than one group"); } } if (group != null) { logLn("In group " + group.identity); if (group.context != null) { CompositeInstanceContext.removePatient( list); // remove anything hanging around, such as empty attributes list.putAll( group.context .getAttributeList()); // overwrite all patient context in list that was read // in } else { throw new DicomException( "Missing group context for SOPInstanceUID on second pass"); // should not be // possible } ClinicalTrialsAttributes.addContributingEquipmentSequence( list, true, new CodedSequenceItem("109103", "DCM", "Modifying Equipment"), "PixelMed", // Manufacturer "PixelMed", // Institution Name "Software Development", // Institutional Department Name "Bangor, PA", // Institution Address null, // Station Name "com.pixelmed.apps.MergeCompositeContext", // Manufacturer's Model Name null, // Device Serial Number "Vers. " + VersionAndConstants.getBuildDate(), // Software Version(s) "Merged patient context"); list.removeGroupLengthAttributes(); list.removeMetaInformationHeaderAttributes(); list.remove(TagFromName.DataSetTrailingPadding); FileMetaInformation.addFileMetaInformation( list, TransferSyntax.ExplicitVRLittleEndian, ourAETitle); File dstFile = new File( dstFolderName, MoveDicomFilesIntoHierarchy.makeHierarchicalPathFromAttributes(list)); if (dstFile.exists()) { throw new DicomException( "\"" + mediaFileName + "\": new file \"" + dstFile + "\" already exists - not overwriting"); } else { File dstParentDirectory = dstFile.getParentFile(); if (!dstParentDirectory.exists()) { if (!dstParentDirectory.mkdirs()) { throw new DicomException( "\"" + mediaFileName + "\": parent directory creation failed for \"" + dstFile + "\""); } } logLn("Writing with new context file " + dstFile); list.write(dstFile, TransferSyntax.ExplicitVRLittleEndian, true, true); } } else { throw new DicomException( "Missing group for SOPInstanceUID on second pass"); // should not be possible for // single set case } } else { throw new DicomException("Missing SOPInstanceUID"); } } catch (Exception e) { logLn("Error: File " + mediaFileName + " exception " + e); } }