Ejemplo n.º 1
0
 /**
  * Copy a set of DICOM files, if they match specified criteria.
  *
  * <p>Does not actually check the Modality value in the file, but matches the SOP Class against
  * what is returned from {@link
  * com.pixelmed.dicom.SOPClass#getPlausibleStandardSOPClassUIDsForModality(String)
  * SOPClass.getPlausibleStandardSOPClassUIDsForModality(String)}.
  *
  * @param arg array of four strings - the input path, the output path, and the SOP Class UID or
  *     Modality
  */
 public static void main(String arg[]) {
   try {
     if (arg.length == 3) {
       FindAndCopySelectedDicomFiles importer =
           new FindAndCopySelectedDicomFiles(new PrintStreamMessageLogger(System.err));
       importer.outputPath = arg[1];
       importer.sopClasses = new HashSet();
       if (arg[2].startsWith("1")) {
         // System.err.println("main(): importer.sopClasses.add = \""+arg[2]+"\"");
         importer.sopClasses.add(arg[2]);
       } else {
         String[] sopClasses = SOPClass.getPlausibleStandardSOPClassUIDsForModality(arg[2]);
         if (sopClasses == null) {
           throw new DicomException(
               "Cannot find plausible SOP Standard Classes for modality \"" + arg[2] + "\"");
         } else {
           for (String sopClass : sopClasses) {
             // System.err.println("main(): importer.sopClasses.add = \""+sopClass+"\"");
             importer.sopClasses.add(sopClass);
           }
         }
       }
       importer.importDicomFiles(arg[0]);
     } else {
       System.err.println(
           "Usage: java -cp ./pixelmed.jar com.pixelmed.apps.FindAndCopySelectedDicomFiles srcdir dstdir sopclass|modality");
     }
   } catch (Exception e) {
     e.printStackTrace(System.err);
     System.exit(0);
   }
 }
  /**
   * 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);
    }
  }
Ejemplo n.º 3
0
  /** @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");
      }
    }
  }