Logo Search packages:      
Sourcecode: pixelmed version File versions  Download package

DemographicAndTechniqueAnnotations.java

/* Copyright (c) 2001-2009, David A. Clunie DBA Pixelmed Publishing. All rights reserved. */

package com.pixelmed.display;

import java.util.Iterator;
import java.util.TreeSet;
import java.util.Vector;

import java.text.DecimalFormat;
import java.text.NumberFormat;

import com.pixelmed.dicom.Attribute;
import com.pixelmed.dicom.AttributeList;
import com.pixelmed.dicom.AttributeTag;
import com.pixelmed.dicom.CodedSequenceItem;
import com.pixelmed.dicom.DateTimeAttribute;
import com.pixelmed.dicom.DescriptionFactory;
import com.pixelmed.dicom.LossyImageCompression;
import com.pixelmed.dicom.SequenceAttribute;
import com.pixelmed.dicom.SequenceItem;
import com.pixelmed.dicom.SOPClass;
import com.pixelmed.dicom.TagFromName;

import com.pixelmed.geometry.GeometryOfSlice;
import com.pixelmed.geometry.GeometryOfVolume;

/**
 * <p>A class to extract selected DICOM annotative attributes into defined displayed area relative positions.</p>
 *
 * @author  dclunie
 */
00032 public class DemographicAndTechniqueAnnotations {

      private static final String identString = "@(#) $Header: /userland/cvs/pixelmed/imgbook/com/pixelmed/display/DemographicAndTechniqueAnnotations.java,v 1.18 2009/04/06 16:10:48 dclunie Exp $";
      
      protected static final int NOSPECIAL = 0;
      protected static final int JUSTTIME = 1;
      protected static final int SLICESPACING = 2;
      protected static final int FRAMENUMBER = 3;
      //protected static final int CONTRAST = 4;
      protected static final int IMAGETYPE = 5;
      protected static final int PIXELREPN = 6;
      protected static final int CODEMEANING = 7;
      protected static final int ORIENTLABEL = 8;
      protected static final int ABBREVPHOTO = 9;
      protected static final int LOSSYCOMPRESSED = 10;
      protected static final int TEXTIFYESNO = 11;
      protected static final int CALLFUNCTION = 12;
      protected static final int DIRECTIONVECTOR = 13;
      protected static final int XRAYTUBECURRENT = 14;
      protected static final int EXPOSURETIME = 15;
      protected static final int EXPOSURE = 16;

      protected class AnnotationLayoutConfigurationEntry {
            String sopClassUID;           // the SOP Class to which is applicable, all SOP Classes if null
            AttributeTag tag;       // null if fixed text value is to be used
            AttributeTag functionalGroup; // null if not found nested in a per-frame or shared functional group
            AttributeTag nestedAttribute; // (e.g. tag is modifier within nestedAttribute) null if tag is not nested in another sequence item
            String text;                  // null if attribute value is to be used
            boolean fromLeft;
            boolean fromTop;
            int textRow;
            int orderInRow;               // the position, left to right, in the row, if multiple, starting from 0
            String decimalFormatPattern;  // to be feed to java.text.DecimalFormat, null if none or not a number
            int specialFunction;          // NOSPECIAL if none
            
            AnnotationLayoutConfigurationEntry(String sopClassUID,AttributeTag tag,AttributeTag functionalGroup,AttributeTag nestedAttribute,String text,
                        boolean fromLeft,boolean fromTop,int textRow,int orderInRow,String decimalFormatPattern,int specialFunction) {
                  this.sopClassUID=sopClassUID;
                  this.tag=tag;
                  this.functionalGroup=functionalGroup;
                  this.nestedAttribute=nestedAttribute;
                  this.text=text;
                  this.fromLeft=fromLeft;
                  this.fromTop=fromTop;
                  this.textRow=textRow;
                  this.orderInRow=orderInRow;
                  this.decimalFormatPattern=decimalFormatPattern;
                  this.specialFunction=specialFunction;
            }
      }
      
      protected Vector layout;                  // of AnnotationLayoutConfigurationEntry
      private int layoutTopLeftRows;            // number of rows used in top left corner
      private int layoutBottomLeftRows;
      private int layoutTopRightRows;
      private int layoutBottomRightRows;
      
      private boolean swapLeftRight;

      protected void initializeDefaultLayout() {
            layout=new Vector();
            
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.InstitutionName,null,null,null,true,true,0,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.Manufacturer,null,null,null,true,true,1,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,1,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ManufacturerModelName,null,null,null,true,true,1,2,null,NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,"[",true,true,2,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PatientID,null,null,null,true,true,2,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,"] ",true,true,2,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PatientName,null,null,null,true,true,2,3,null,NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PatientSex,null,null,null,true,true,3,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,3,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PatientBirthDate,null,null,null,true,true,3,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," [",true,true,3,3,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PatientAge,null,null,null,true,true,3,4,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,"]",true,true,3,5,null,NOSPECIAL));

            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",TagFromName.FrameLaterality,TagFromName.FrameAnatomySequence,null,null,true,true,4,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("NOTENH",TagFromName.Laterality,null,null,null,true,true,4,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("NOTENH",TagFromName.ImageLaterality,null,null,null,true,true,4,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,4,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.BodyPartExamined,null,null,null,true,true,4,3,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,4,4,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.AnatomicRegionSequence,TagFromName.FrameAnatomySequence,null,null,true,true,4,5,null,CODEMEANING));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.AnatomicRegionSequence,null,null,null,true,true,4,5,null,CODEMEANING));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,4,6,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ViewPosition,null,null,null,true,true,4,7,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,4,8,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ViewCodeSequence,null,null,null,true,true,4,9,null,CODEMEANING));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,4,10,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ViewModifierCodeSequence,null,TagFromName.ViewCodeSequence,null,true,true,4,11,null,CODEMEANING));
            
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PatientSpeciesDescription,null,null,null,true,true,5,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,5,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PatientSpeciesCodeSequence,null,null,null,true,true,5,2,null,CODEMEANING));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,5,3,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ResponsiblePersonRole,null,null,null,true,true,5,4,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,5,5,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ResponsiblePerson,null,null,null,true,true,5,6,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,5,7,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ResponsibleOrganization,null,null,null,true,true,5,8,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",true,true,5,9,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PatientSexNeutered,null,null,null,true,true,5,10,null,NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.StudyDescription,null,null,null,false,true,0,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.SeriesDescription,null,null,null,false,true,1,0,null,NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.StudyID,null,null,null,false,true,2,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," [",false,true,2,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.AccessionNumber,null,null,null,false,true,2,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,"]",false,true,2,3,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.StudyDate,null,null,null,false,true,3,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,"Series #",false,true,4,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.SeriesNumber,null,null,null,false,true,4,1,null,NOSPECIAL));
            
            
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.FrameComments,TagFromName.FrameContentSequence,null,null,false,false,0,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",false,false,0,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedMRImageStorage,TagFromName.FrameType,TagFromName.MRImageFrameTypeSequence,null,null,false,false,0,2,null,IMAGETYPE));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedCTImageStorage,TagFromName.FrameType,TagFromName.CTImageFrameTypeSequence,null,null,false,false,0,2,null,IMAGETYPE));

            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ImageComments,null,null,null,false,false,1,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",false,false,1,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ImageType,null,null,null,false,false,1,2,null,IMAGETYPE));

            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",TagFromName.FrameAcquisitionDateTime,TagFromName.FrameContentSequence,null,null,false,false,2,0,null,JUSTTIME));
            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",null,null,null," ",false,false,2,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.AcquisitionDateTime,null,null,null,false,false,2,2,null,JUSTTIME));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",false,false,2,3,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.AcquisitionTime,null,null,null,false,false,2,4,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",false,false,2,5,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.ContentTime,null,null,null,false,false,2,6,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",null,null,null," [",false,false,2,7,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",TagFromName.TemporalPositionIndex,TagFromName.FrameContentSequence,null,null,false,false,2,8,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",null,null,null,"]",false,false,2,9,null,NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,"F #",false,false,3,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,null,false,false,3,1,null,FRAMENUMBER));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," I #",false,false,3,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.InstanceNumber,null,null,null,false,false,3,3,null,NOSPECIAL));

            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.Columns,null,null,null,false,false,4,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,"x",false,false,4,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.Rows,null,null,null,false,false,4,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,"x",false,false,4,3,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.NumberOfFrames,null,null,null,false,false,4,4,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",false,false,4,5,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PixelRepresentation,null,null,null,false,false,4,6,null,PIXELREPN));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.BitsStored,null,null,null,false,false,4,7,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",false,false,4,8,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.PhotometricInterpretation,null,null," ",false,false,4,9,null,ABBREVPHOTO));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null," ",false,false,4,10,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(null,null,null,null,null,false,false,4,11,null,LOSSYCOMPRESSED));
            
            layout.add(new AnnotationLayoutConfigurationEntry(null,TagFromName.DerivationDescription,null,null,null,false,false,5,0,null,NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",null,null,null,"[",true,false,0,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",TagFromName.StackID,TagFromName.FrameContentSequence,null,null,true,false,0,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",null,null,null,":",true,false,0,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",TagFromName.InStackPositionNumber,TagFromName.FrameContentSequence,null,null,true,false,0,3,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",null,null,null,"] ",true,false,0,4,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",TagFromName.ImagePositionPatient,TagFromName.PlanePositionSequence,null,null,true,false,0,5,"###.#",NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedCTImageStorage,null,null,null," [",true,false,0,6,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedCTImageStorage,TagFromName.TablePosition,TagFromName.CTPositionSequence,null,null,true,false,0,7,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedCTImageStorage,null,null,null,"]",true,false,0,8,null,NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry("XCOLD",null,null,null," [",true,false,0,6,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCOLD",TagFromName.SliceLocation,null,null,null,true,false,0,7,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCOLD",null,null,null,"]",true,false,0,8,null,NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",null,null,null," mm",true,false,0,9,null,NOSPECIAL));
            
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",TagFromName.ImageOrientationPatient,TagFromName.PlaneOrientationSequence,null,null,true,false,1,0,"#.##",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",null,null,null," ",true,false,1,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",TagFromName.ImageOrientationPatient,TagFromName.PlaneOrientationSequence,null,null,true,false,1,2,null,ORIENTLABEL));
            
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",TagFromName.PixelSpacing,TagFromName.PixelMeasuresSequence,null,null,true,false,2,0,"#.###",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",null,null,null,"\\",true,false,2,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",null,null,null,null,true,false,2,3,"#.###",SLICESPACING));
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",null,null,null," ",true,false,2,4,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",TagFromName.SliceThickness,TagFromName.PixelMeasuresSequence,null,null,true,false,2,5,"##.##",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",null,null,null," ",true,false,2,6,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",TagFromName.ReconstructionDiameter,TagFromName.CTReconstructionSequence,null,null,true,false,2,7,"###.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedCTImageStorage,TagFromName.ReconstructionFieldOfView,TagFromName.CTReconstructionSequence,null,null,true,false,2,7,"###.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XCIMAGE",null,null,null," mm",true,false,2,8,null,NOSPECIAL));

            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",TagFromName.FlipAngle,TagFromName.MRTimingAndRelatedParametersSequence,null,null,true,false,3,0,"#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",null,null,null,"\u00b0 ETL ",true,false,3,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedMRImageStorage,TagFromName.GradientEchoTrainLength,TagFromName.MRTimingAndRelatedParametersSequence,null,null,true,false,3,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedMRImageStorage,null,null,null,"+",true,false,3,3,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedMRImageStorage,TagFromName.RFEchoTrainLength,TagFromName.MRTimingAndRelatedParametersSequence,null,null,true,false,3,4,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedMRImageStorage,null,null,null,"=",true,false,3,5,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",TagFromName.EchoTrainLength,TagFromName.MRTimingAndRelatedParametersSequence,null,null,true,false,3,6,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",null,null,null," Avg ",true,false,3,7,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",TagFromName.NumberOfAverages,TagFromName.MRAveragesSequence,null,null,true,false,3,8,"#.#",NOSPECIAL));

            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",TagFromName.KVP,TagFromName.CTXRayDetailsSequence,null,null,true,false,3,0,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",null,null,null," kVP ",true,false,3,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedCTImageStorage,TagFromName.ExposureInmAs,TagFromName.CTExposureSequence,null,null,true,false,3,2,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.CTImageStorage,null,null,null,null,true,false,3,2,"#.#",EXPOSURE));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",null,null,null," mAs",true,false,3,3,null,NOSPECIAL));

            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",null,null,null,"TE ",true,false,4,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedMRImageStorage,TagFromName.EffectiveEchoTime,TagFromName.MREchoSequence,null,null,true,false,4,1,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.MRImageStorage,TagFromName.EchoTime,null,null,null,true,false,4,1,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",null,null,null," TR ",true,false,4,2,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",TagFromName.RepetitionTime,TagFromName.MRTimingAndRelatedParametersSequence,null,null,true,false,4,3,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",null,null,null," TI ",true,false,4,4,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedMRImageStorage,TagFromName.InversionTimes,TagFromName.MRModifierSequence,null,null,true,false,4,5,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.MRImageStorage,TagFromName.InversionTime,null,null,null,true,false,4,5,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",null,null,null," mS",true,false,4,6,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",null,null,null," B ",true,false,4,7,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",TagFromName.DiffusionBValue,TagFromName.MRDiffusionSequence,null,null,true,false,4,8,"#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",null,null,null," ",true,false,4,10,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("MRIMAGE",TagFromName.DiffusionGradientOrientation,TagFromName.MRDiffusionSequence,TagFromName.DiffusionGradientDirectionSequence,null,true,false,4,11,null,DIRECTIONVECTOR));

            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",TagFromName.AcquisitionType,TagFromName.CTAcquisitionTypeSequence,null,null,true,false,4,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",null,null,null," ",true,false,4,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",TagFromName.SpiralPitchFactor,TagFromName.CTTableDynamicsSequence,null,null,true,false,4,2,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",null,null,null,":1 ",true,false,4,3,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",TagFromName.TableSpeed,TagFromName.CTTableDynamicsSequence,null,null,true,false,4,4,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",null,null,null," mm/s",true,false,4,5,null,NOSPECIAL));

            layout.add(new AnnotationLayoutConfigurationEntry(SOPClass.EnhancedMRImageStorage,TagFromName.AcquisitionContrast,TagFromName.MRImageFrameTypeSequence,null,null,true,false,5,0,null,NOSPECIAL));

            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",TagFromName.ConvolutionKernel,TagFromName.CTReconstructionSequence,null,null,true,false,5,0,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",null,null,null," ",true,false,5,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("CTIMAGE",TagFromName.ConvolutionKernelGroup,TagFromName.CTReconstructionSequence,null,null,true,false,5,2,null,NOSPECIAL));

            layout.add(new AnnotationLayoutConfigurationEntry("XCENH",TagFromName.ContrastBolusAgentPhase,TagFromName.ContrastBolusUsageSequence,null,null,true,false,6,0,null,NOSPECIAL));

            layout.add(new AnnotationLayoutConfigurationEntry("XRAYOLD",TagFromName.KVP,null,null,null,true,false,0,0,"#.#",NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XRAYOLD",null,null,null," kVP ",true,false,0,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XRAYOLD",null,null,null,null,true,false,1,0,"#.#",EXPOSURE));
            layout.add(new AnnotationLayoutConfigurationEntry("XRAYOLD",null,null,null," mAs",true,false,1,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XRAYOLD",null,null,null,null,true,false,2,0,"#.#",EXPOSURETIME));
            layout.add(new AnnotationLayoutConfigurationEntry("XRAYOLD",null,null,null," ms",true,false,2,1,null,NOSPECIAL));
            layout.add(new AnnotationLayoutConfigurationEntry("XRAYOLD",null,null,null,null,true,false,3,0,"#.#",XRAYTUBECURRENT));
            layout.add(new AnnotationLayoutConfigurationEntry("XRAYOLD",null,null,null," mA",true,false,3,1,null,NOSPECIAL));
      }

      private Vector[] annotations; // an array[number of frames] of TextAnnotationPositioned
      
      private class AnnotationComponentEntry implements Comparable {
            String string;
            int textRow;
            int orderInRow;
            
            AnnotationComponentEntry(String string,int textRow,int orderInRow) {
                  this.string=string;
                  this.textRow=textRow;
                  this.orderInRow=orderInRow;
            }

            public int compareTo(Object o) {
                  AnnotationComponentEntry e = (AnnotationComponentEntry)o;
                  if (textRow == e.textRow) {
                        return orderInRow-e.orderInRow;
                  }
                  else {
                        return textRow-e.textRow;
                  }
            }
      }
      
      // array index
      // 0 - top left
      // 1 - bottom left
      // 2 - top right
      // 3 - bottom right
      
      private static final int getArrayIndexFromLeftTop(boolean isLeft,boolean isTop) {
            return isLeft ? (isTop ? 0 : 1) : (isTop ? 2 : 3);
      }
      
      private static final boolean isLeftFromArrayIndex(int index) {
            return index == 0 || index == 1;
      }
      
      private static final boolean isTopFromArrayIndex(int index) {
            return index == 0 || index == 2;
      }
      
      protected static final String multipleCodeMeaningDelimiter = " ";
      
      private static final String getFormattedValue(Attribute a,int specialFunction,NumberFormat formatter) {
            String value = null;
            if (a != null) {
                  if (specialFunction == CODEMEANING && a instanceof SequenceAttribute) {
                        //CodedSequenceItem csi = CodedSequenceItem.getSingleCodedSequenceItemOrNull(a);
                        //if (csi != null) {
                        //    value=csi.getCodeMeaning();
                        //}
                        
                        // concatentate possibly multiple sequence items
                        Iterator sitems = ((SequenceAttribute)a).iterator();
                        while (sitems.hasNext()) {
                              SequenceItem sitem = (SequenceItem)sitems.next();
                              AttributeList slist = sitem.getAttributeList();
                              if (slist != null) {
                                    String nextValue = Attribute.getSingleStringValueOrNull(slist,TagFromName.CodeMeaning);
                                    if (nextValue != null && nextValue.length() > 0) {
                                          value = value == null || value.length() == 0 ?  nextValue : (value + multipleCodeMeaningDelimiter + nextValue);
                                    }
                              }
                        }
                  }
                  else if (specialFunction == ORIENTLABEL && a.getVM() == 6) {
                        try {
                              double v[] = a.getDoubleValues();
                              value = DescriptionFactory.makeImageOrientationLabelFromImageOrientationPatient(v[0],v[1],v[2],v[3],v[4],v[5]);
                        }
                        catch (Exception e) {
                              e.printStackTrace(System.err);
                        }
                  }
                  else if (specialFunction == DIRECTIONVECTOR) {
//System.err.println("DemographicAndTechniqueAnnotations.getFormattedValue(): specialFunction == DIRECTIONVECTOR for attribute "+a);
                        try {
                              double v[] = a.getDoubleValues();
                              value = GeometryOfSlice.getOrientation(v);
//System.err.println("DemographicAndTechniqueAnnotations.getFormattedValue(): specialFunction == DIRECTIONVECTOR value "+value);
                        }
                        catch (Exception e) {
                              e.printStackTrace(System.err);
                        }
                  }
                  else if (specialFunction == JUSTTIME && a instanceof DateTimeAttribute) {
                        try {
                              String[] v = a.getOriginalStringValues();
                              StringBuffer sb = new StringBuffer();
                              if (v != null) {
                                    char delimiter=0;
                                    for (int j=0; j<v.length; ++j) {
                                          String justTime = null;
                                          if (v[j] != null && v[j].length() > 8) {
                                                justTime = v[j].substring(8);
                                          }
                                          if (delimiter != 0) {
                                                sb.append(delimiter);
                                          }
                                          if (justTime != null) {
                                                sb.append(justTime);
                                          }
                                          delimiter='\\';
                                    }
                                    value=sb.toString();
                              }
                        }
                        catch (Exception e) {
                              e.printStackTrace(System.err);
                        }
                  }
                  else if (specialFunction == IMAGETYPE) {
                        try {
                              String[] v = a.getStringValues();
                              StringBuffer sb = new StringBuffer();
                              if (v != null) {
                                    char delimiter=0;
                                    for (int j=0; j<v.length; ++j) {
                                          String s = v[j];
                                          if (s != null) {
                                                if (j == 0 && s.equals("ORIGINAL")
                                                 || j == 1 && s.equals("PRIMARY")
                                                 || j == 3 && s.equals("NONE")
                                                 ) {
                                                }
                                                else {
                                                      if (delimiter != 0) {
                                                            sb.append(delimiter);
                                                      }
                                                      sb.append(s);
                                                      delimiter='\\';
                                                }
                                          }
                                    }
                                    value=sb.toString();
                              }
                        }
                        catch (Exception e) {
                              e.printStackTrace(System.err);
                        }
                  }
                  else if (specialFunction == ABBREVPHOTO && a.getTag().equals(TagFromName.PhotometricInterpretation)) {
                        value = a.getSingleStringValueOrNull();
                        if (value != null) {
                              if (value.equals("MONOCHROME2")) {
                                    value="M2";
                              }
                              else if (value.equals("MONOCHROME1")) {
                                    value="M1";
                              }
                              else if (value.equals("PALETTE COLOR")) {
                                    value="PAL";
                              }
                              // else leave alone
                        }
                  }
                  else if (specialFunction == PIXELREPN && a.getTag().equals(TagFromName.PixelRepresentation)) {
                        value = a.getSingleIntegerValueOrDefault(0) == 0 ? "+" : "-";
                  }
                  else {
                        value = a.getDelimitedStringValuesOrNull(formatter);
                  }
            }
            return value;
      }
      
      private static final String getOneOfThreeNumericAttributesOrNull(
                  AttributeList list,NumberFormat formatter,
                  AttributeTag tag1,double multiplier1,
                  AttributeTag tag2,double multiplier2,
                  AttributeTag tag3,double multiplier3) {
            String value = null;
            double multiplier;
            Attribute a = list.get(tag1);
            if (a != null && a.getVM() > 0) {
                  multiplier = multiplier1;
            }
            else {
                  a = list.get(tag2);
                  if (a != null && a.getVM() > 0) {
                        multiplier = multiplier2;
                  }
                  else {
                        a = list.get(tag3);
                        multiplier = multiplier3;
                  }
            }
            if (a != null && a.getVM() > 0) {
                  value=formatter.format(a.getSingleDoubleValueOrDefault(0)*multiplier);
            }
            return value;
      }
                                          
      /**
       * @param   list              the DICOM attributes of a single or multi-frame image
       */
00473       public DemographicAndTechniqueAnnotations(AttributeList list) {
            this(list,null,false);
      }
      
      /**
       * @param   list              the DICOM attributes of a single or multi-frame image
       * @param   geometry          the geometry of a single or multi-frame image (or null if no 3D coordinate system)
       */
00481       public DemographicAndTechniqueAnnotations(AttributeList list,GeometryOfVolume geometry) {
            this(list,geometry,false);
      }
      
      /**
       * @param   list              the DICOM attributes of a single or multi-frame image
       * @param   geometry          the geometry of a single or multi-frame image (or null if no 3D coordinate system)
       * @param   swapLeftRight     whether the sides (left and right) to annotate are to be swapped
       */
00490       public DemographicAndTechniqueAnnotations(AttributeList list,GeometryOfVolume geometry,boolean swapLeftRight) {
            this.swapLeftRight = swapLeftRight;
            if (list != null) {
                  String sopClassUID = Attribute.getSingleStringValueOrNull(list,TagFromName.SOPClassUID);
                  int numberOfFrames = Attribute.getSingleIntegerValueOrDefault(list,TagFromName.NumberOfFrames,1);
                  if (sopClassUID != null && numberOfFrames > 0) {
                        initializeDefaultLayout();
                        annotations = new Vector[numberOfFrames];
                        
                        // for each frame, build individual components of rows, then flatten components sorted within each row into single string per row
                        
                        SequenceAttribute sharedFunctionalGroupsSequence = (SequenceAttribute)(list.get(TagFromName.SharedFunctionalGroupsSequence));
                        SequenceAttribute perFrameFunctionalGroupsSequence = (SequenceAttribute)(list.get(TagFromName.PerFrameFunctionalGroupsSequence));

                        for (int f=0; f<numberOfFrames; ++f) {
                              TreeSet set[] = new TreeSet[4];
                              for (int s=0; s<4; ++s) {
                                    set[s] = new TreeSet();       // of sorted AnnotationComponentEntry
                              }
                              
                              Iterator i = layout.iterator();
                              while (i.hasNext()) {
                                    AnnotationLayoutConfigurationEntry le = (AnnotationLayoutConfigurationEntry)i.next();
                                    if ( le.sopClassUID == null
                                     ||  le.sopClassUID.equals(sopClassUID)
                                     || (le.sopClassUID.equals("MRIMAGE") && (sopClassUID.equals(SOPClass.EnhancedMRImageStorage) || sopClassUID.equals(SOPClass.MRImageStorage)) )
                                     || (le.sopClassUID.equals("CTIMAGE") && (sopClassUID.equals(SOPClass.EnhancedCTImageStorage) || sopClassUID.equals(SOPClass.CTImageStorage)) )
                                     || (le.sopClassUID.equals("XCIMAGE") && (sopClassUID.equals(SOPClass.EnhancedMRImageStorage) || sopClassUID.equals(SOPClass.MRImageStorage)
                                                                   || sopClassUID.equals(SOPClass.EnhancedCTImageStorage) || sopClassUID.equals(SOPClass.CTImageStorage)) )
                                     || (le.sopClassUID.equals("XCENH")   && (sopClassUID.equals(SOPClass.EnhancedMRImageStorage) || sopClassUID.equals(SOPClass.EnhancedCTImageStorage)) )
                                     || (le.sopClassUID.equals("NOTENH")  && !(sopClassUID.equals(SOPClass.EnhancedMRImageStorage) || sopClassUID.equals(SOPClass.EnhancedCTImageStorage)) )
                                     || (le.sopClassUID.equals("XCOLD")   && (sopClassUID.equals(SOPClass.MRImageStorage) || sopClassUID.equals(SOPClass.CTImageStorage)) )
                                     || (le.sopClassUID.equals("XRAYOLD")
                                          && (
                                                   sopClassUID.equals(SOPClass.ComputedRadiographyImageStorage)
                                                || sopClassUID.equals(SOPClass.DigitalXRayImageStorageForPresentation)
                                                || sopClassUID.equals(SOPClass.DigitalXRayImageStorageForProcessing)
                                                || sopClassUID.equals(SOPClass.DigitalMammographyXRayImageStorageForPresentation)
                                                || sopClassUID.equals(SOPClass.DigitalMammographyXRayImageStorageForProcessing)
                                                || sopClassUID.equals(SOPClass.DigitalIntraoralXRayImageStorageForPresentation)
                                                || sopClassUID.equals(SOPClass.DigitalIntraoralXRayImageStorageForProcessing)
                                                || sopClassUID.equals(SOPClass.XRayAngiographicImageStorage)
                                                || sopClassUID.equals(SOPClass.XRayRadioFlouroscopicImageStorage)
                                                ) )
                                     || (le.sopClassUID.equals("XRAYENH")
                                          && (
                                                   sopClassUID.equals(SOPClass.EnhancedXAImageStorage)
                                                || sopClassUID.equals(SOPClass.EnhancedXRFImageStorage)
                                                || sopClassUID.equals(SOPClass.XRay3DAngiographicImageStorage)
                                                || sopClassUID.equals(SOPClass.XRay3DCraniofacialImageStorage)
                                                ) )
                                     ) {
                                          NumberFormat formatter = null;
                                          if (le.decimalFormatPattern != null) {
                                                try {
                                                      formatter = new DecimalFormat(le.decimalFormatPattern);
                                                }
                                                catch (Exception e) {
                                                      e.printStackTrace(System.err);
                                                      formatter=null;
                                                }
                                          }
                                          String value = null;

                                          if (le.specialFunction == XRAYTUBECURRENT) {
                                                // want in mA
                                                value = getOneOfThreeNumericAttributesOrNull(list,formatter,
                                                      TagFromName.XRayTubeCurrentInuA,0.001,
                                                      TagFromName.XRayTubeCurrentInmA,1,
                                                      TagFromName.XRayTubeCurrent,1);
                                          }
                                          else if (le.specialFunction == EXPOSURETIME) {
                                                // want in mS
                                                value = getOneOfThreeNumericAttributesOrNull(list,formatter,
                                                      TagFromName.ExposureTimeInuS,0.001,
                                                      TagFromName.ExposureTimeInms,1,
                                                      TagFromName.ExposureTime,1);
                                          }
                                          else if (le.specialFunction == EXPOSURE) {
                                                // want in mAs
                                                value = getOneOfThreeNumericAttributesOrNull(list,formatter,
                                                      TagFromName.ExposureInuAs,0.001,
                                                      TagFromName.ExposureInmAs,1,
                                                      TagFromName.Exposure,1);
                                          }
                                          else if (le.specialFunction == SLICESPACING) {
                                                if (geometry != null && geometry.isVolumeSampledRegularlyAlongFrameDimension()) {
                                                      GeometryOfSlice sliceGeometries[] = geometry.getGeometryOfSlices();
                                                      if (sliceGeometries != null && sliceGeometries.length > 0) {
                                                            double voxelSpacing[] = sliceGeometries[0].getVoxelSpacingArray();
                                                            if (voxelSpacing != null && voxelSpacing.length == 3) {
                                                                  if (formatter == null) {
                                                                        formatter = new DecimalFormat("###.#");
                                                                  }
                                                                  value=formatter.format(voxelSpacing[2]);
                                                            }
                                                      }
                                                }
                                          }
                                          else if (le.specialFunction == FRAMENUMBER) {
                                                value = Integer.toString(f+1);
                                          }
                                          else if (le.specialFunction == LOSSYCOMPRESSED) {
                                                value = LossyImageCompression.describeLossyCompression(list);
                                          }
                                          else if (le.specialFunction == CALLFUNCTION) {
                                                value = getValueByCallingFunction(list);
                                          }
                                          else if (le.tag == null) {
                                                value = le.text;
                                          }
                                          else {
                                                Attribute a = null;
                                                AttributeTag lookingFor = le.nestedAttribute == null ? le.tag : le.nestedAttribute;
                                                // look first into functional groups
                                                if (le.functionalGroup != null && sharedFunctionalGroupsSequence != null && perFrameFunctionalGroupsSequence != null) {
                                                      SequenceAttribute sa = null;
                                                      //SequenceAttribute sa = (SequenceAttribute)(sharedFunctionalGroupsSequence.getItem(0).getAttributeList().get(le.functionalGroup));
                                                      {
                                                            SequenceItem item = sharedFunctionalGroupsSequence.getItem(0);
                                                            if (item != null) {
                                                                  AttributeList al = item.getAttributeList();
                                                                  if (al != null) {
                                                                        sa = (SequenceAttribute)(al.get(le.functionalGroup));
                                                                  }
                                                            }
                                                      }
                                                      if (sa == null) {
                                                            //sa = (SequenceAttribute)(perFrameFunctionalGroupsSequence.getItem(f).getAttributeList().get(le.functionalGroup));
                                                            SequenceItem item = perFrameFunctionalGroupsSequence.getItem(f);
                                                            if (item != null) {
                                                                  AttributeList al = item.getAttributeList();
                                                                  if (al != null) {
                                                                        sa = (SequenceAttribute)(al.get(le.functionalGroup));
                                                                  }
                                                            }
                                                      }
                                                      if (sa != null) {
                                                            a = SequenceAttribute.getNamedAttributeFromWithinSequenceWithSingleItem(sa,lookingFor);
                                                      }
                                                }
                                                if (a == null) {
                                                      // was not in a functional group ... check top level data set
                                                       a = list.get(lookingFor);
                                                }
                                                if (a != null) {
//System.err.println("Looking for and found "+a.getTag());
                                                      if (le.nestedAttribute != null) {
//System.err.println("Want nestedAttribute "+le.nestedAttribute);
                                                            if (le.nestedAttribute.equals(a.getTag()) && a instanceof SequenceAttribute) {
//System.err.println("Is the nestedAttribute; now looking for "+le.tag);
                                                                  SequenceAttribute sa = (SequenceAttribute)a;
                                                                  //a = SequenceAttribute.getNamedAttributeFromWithinSequenceWithSingleItem(sa,le.tag); // could return null
                                                                  // concatenate possibly multiple sequence item values
                                                                  Iterator sitems = sa.iterator();
                                                                  while (sitems.hasNext()) {
                                                                        SequenceItem sitem = (SequenceItem)sitems.next();
                                                                        AttributeList slist = sitem.getAttributeList();
                                                                        if (slist != null) {
                                                                              a=slist.get(le.tag);
                                                                              if (a != null) {
//System.err.println("Looking for and found within item of nestedAttribute "+a.getTag());
                                                                                    String nextValue = getFormattedValue(a,le.specialFunction,formatter);
                                                                                    if (nextValue != null && nextValue.length() > 0) {
                                                                                          value = value == null || value.length() == 0 ?  nextValue : (value + multipleCodeMeaningDelimiter + nextValue);
                                                                                    }
                                                                              }
                                                                        }
                                                                  }
                                                                  a=null;           // done, so stop further actions
                                                            }
                                                            else {
//System.err.println("Was not a sequence attribute");
                                                                  a = null;   // something went wrong so give up
                                                            }
                                                      }
                                                      if (a != null) {
                                                            value=getFormattedValue(a,le.specialFunction,formatter);
                                                      }
                                                }
                                          }
                                          if (value != null && value.length() > 0) {
                                                if (le.specialFunction == TEXTIFYESNO) {
                                                      value = value.toUpperCase().indexOf("Y") == -1 ? "" : le.text;
                                                }
                                                AnnotationComponentEntry ace = new AnnotationComponentEntry(value,le.textRow,le.orderInRow);
                                                set[getArrayIndexFromLeftTop(le.fromLeft,le.fromTop)].add(ace);
                                          }
                                    }
                              }
                              
                              Vector thisFramesAnnotations = new Vector();
                              annotations[f] = thisFramesAnnotations;
                              
                              for (int s=0; s<4; ++s) {
                                    boolean isLeft = isLeftFromArrayIndex(s);
                                    isLeft = (isLeft && !swapLeftRight) || (!isLeft && swapLeftRight);      // there is no XOR operator in Java :(
                                    boolean isTop  = isTopFromArrayIndex(s);
                                    int lastRow = -1;
                                    StringBuffer lastValue = null;
                                    Iterator ia = set[s].iterator();
                                    while (ia.hasNext()) {
                                          AnnotationComponentEntry ace = (AnnotationComponentEntry)ia.next();
                                          if (ace.textRow != lastRow) {
                                                if (lastValue != null) {
                                                      thisFramesAnnotations.add(new TextAnnotationPositioned(lastValue.toString(),isLeft,isTop,lastRow));
                                                }
                                                lastValue = new StringBuffer();
                                          }
                                          lastValue.append(ace.string);       // assume already ordered by orderInRow; should be since TreeSet is sorted
                                          lastRow=ace.textRow;
                                    }
                                    if (lastValue != null) {
                                          thisFramesAnnotations.add(new TextAnnotationPositioned(lastValue.toString(),isLeft,isTop,lastRow));
                                    }
                              }
                        }
                  }
            }
      }
      
      /**
       * <p>Return a string value from the supplied list of attributes.</p>
       *
       * <p>Overridden by children of this class when specific functionality is needed.</p>
       *
       * @param   list  ignored, unless the method is overriden in a child class
       * @return              a string value, of zero length unless the method is overriden in a child class
       */
00719       protected String getValueByCallingFunction(AttributeList list) {
            return "";
      }

      /**
       * <p>Get the annotations for the selected frame.</p>
       *
       * @param   frameIndex  which frame
       * @return              an iterator of annotations of {@link com.pixelmed.display.TextAnnotationPositioned TextAnnotationPositioned}
       */
00729       public Iterator iterator(int frameIndex) { return annotations[frameIndex].iterator(); }
}


Generated by  Doxygen 1.6.0   Back to index