Created
May 12, 2012 18:54
-
-
Save tomafc330/2668191 to your computer and use it in GitHub Desktop.
Amira DICOM converter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package converter; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.text.SimpleDateFormat; | |
import java.util.Date; | |
import java.util.regex.Matcher; | |
import java.util.regex.Pattern; | |
import com.archimed.dicom.DicomException; | |
import domain.Metadata; | |
import domain.Mode; | |
/** | |
* File that takes an Amira file (.am) and turn it into a DICOM image | |
* | |
* @author tchan | |
* | |
*/ | |
public class AmiraToDicomConverter { | |
private final String inputFile; | |
private final String outputFile; | |
private final String referenceFile; | |
public static void main(String[] args) throws IOException, DicomException { | |
//String inputFile = "/home/tchan/Documents/ubc-reading-center/OCT_FILE_Samples/Amira_Export/024680_20120214_162423_3DOCT00_L_01.am"; | |
String inputFile = "/home/tchan/Dropbox/RawFiles/256x256x128.am"; | |
String referenceFile = "/home/tchan/Dropbox/RawFiles/DICOM/single.dcm"; | |
SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MMM-dd-HH-mm-ss"); | |
String dateNow = formatter.format(new Date().getTime()); | |
String outputFile = "amira" + dateNow + ".dcm"; | |
new AmiraToDicomConverter(inputFile, outputFile, referenceFile).convert(); | |
} | |
public AmiraToDicomConverter(String inputFile, String outputFile, String referenceFile) { | |
this.inputFile = inputFile; | |
this.outputFile = outputFile; | |
this.referenceFile = referenceFile; | |
} | |
private void convert() throws IOException, DicomException { | |
File file = new File(inputFile); | |
Metadata header = getHeaderInformation(file); | |
long startPostToReadRaw = getRawDataStartOffset(file, header); | |
System.out.println(startPostToReadRaw); | |
byte[] rawData = getRawBytes(file, startPostToReadRaw, file.length()); | |
System.out.println(rawData); | |
new DicomConverter(referenceFile, outputFile).convert(header, rawData); | |
} | |
/** | |
* Gets the start position of the raw data to read from. | |
* | |
* @param header | |
*/ | |
private long getRawDataStartOffset(File file, Metadata header) { | |
return file.length() - getHeaderSize(header) - 1; | |
} | |
private long getHeaderSize(Metadata header) { | |
return Integer.parseInt(header.getWidth()) | |
* Integer.parseInt(header.getHeight()) | |
* Integer.parseInt(header.getFrames()) * 2; | |
} | |
private Metadata getHeaderInformation(File file) throws IOException { | |
byte[] rawHeader = getRawBytes(file, 0, 2048); | |
String str = getDimensionAndType(getContentString(rawHeader)); // ie. | |
// 512x885x128 | |
// ushort, | |
// uniform | |
// coordinates | |
String[] parts = str.split(" "); | |
return new Metadata(parts[0], parts[1].replace(",", "")); | |
} | |
/** | |
* Will extract the raw data into a metadata class | |
*/ | |
private String getDimensionAndType(String contentString) { | |
Pattern pattern = Pattern.compile("(?s)\\\"(.*?)\\\""); | |
Matcher matcher = pattern.matcher(contentString); | |
if (matcher.find()) { | |
return matcher.group(1).trim(); | |
} else { | |
throw new RuntimeException("Cannot parse Amira Header file."); | |
} | |
} | |
/** | |
* Gets the Content string that looks something like this: | |
* | |
* Content "512x885x128 ushort, uniform coordinates", BoundingBox 0 511 0 | |
* 884 0 127, CoordType "uniform" | |
* | |
*/ | |
private String getContentString(byte[] rawHeader) { | |
Pattern pattern = Pattern.compile("(?s)Parameters \\{(.*?)\\}"); | |
Matcher matcher = pattern.matcher(new String(rawHeader)); | |
if (matcher.find()) { | |
return matcher.group(1).trim(); | |
} else { | |
throw new RuntimeException("Cannot parse Amira Header file."); | |
} | |
} | |
private byte[] getRawBytes(File file, long start, long end) throws IOException { | |
InputStream is = new FileInputStream(file); | |
byte[] bytes = new byte[(int) (end - start)]; | |
int offset = 0; | |
int numRead = 0; | |
while (offset < bytes.length | |
&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { | |
offset += numRead; | |
} | |
// Ensure all the bytes have been read in | |
if (offset < bytes.length) { | |
throw new IOException("Could not completely read file " | |
+ file.getName()); | |
} | |
is.close(); | |
return bytes; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package converter; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
import com.archimed.dicom.DDict; | |
import com.archimed.dicom.DicomException; | |
import com.archimed.dicom.DicomObject; | |
import com.archimed.dicom.DicomReader; | |
import com.archimed.dicom.DicomWriter; | |
import com.archimed.dicom.IllegalValueException; | |
import domain.Metadata; | |
public class DicomConverter { | |
private String referenceFileName; | |
private String outputFileLoc; | |
public static void main(String[] args) throws IOException, DicomException, | |
IllegalValueException { | |
String inputFileLoc = "/home/tchan/Dropbox/RawFiles/DICOM/7line.dcm"; | |
String outputFileLoc = "example7.dcm"; | |
new DicomConverter(inputFileLoc, outputFileLoc).convert(new Metadata( | |
"512x885x128", "ushort"), retrieveRawData()); | |
} | |
/** | |
* | |
* @param referenceFileName The reference file name where we grab the header information from | |
* @param outputFileName | |
*/ | |
public DicomConverter(String referenceFileName, String outputFileName) { | |
this.referenceFileName = referenceFileName; | |
outputFileLoc = outputFileName; | |
} | |
public void convert(Metadata metadata, byte[] rawData) throws IOException, | |
DicomException { | |
DicomObject sampleInObj = read(referenceFileName); | |
DicomObject outObj = new DicomObject(); | |
sampleInObj.dumpVRs(System.err, true); | |
// dump out example object | |
// sampleInObj.dumpVRs(System.out, true); | |
outObj.setFileMetaInformation(sampleInObj.getFileMetaInformation()); | |
// outObj.set(DDict.dFileMetaInformationVersion, new byte[] {0, 1}); | |
// outObj.set(DDict.dSOPClassUID, "1.2.840.10008.5.1.4.1.1.77.1.5.4"); | |
// outObj.set(DDict.dSOPInstanceUID, | |
// "1.3.6.1.4.1.33437.11.4.5604041.12963093945.145.4.1"); | |
// outObj.set(DDict.dTransferSyntaxUID, "1.2.840.10008.1.2.1"); | |
// outObj.set_ge(0x0002, 0x0010, "1.2.840.10008.1.2.1"); | |
// outObj.set(DDict.dMediaStorageSOPClassUID, | |
// "1.2.840.10008.5.1.4.1.1.77.1.5.4"); | |
// outObj.set(DDict.dMediaStorageSOPInstanceUID, | |
// "1.3.6.1.4.1.33437.11.4.5604041.12963173613.145.4.0.1"); | |
// outObj.set(DDict.dImplementationClassUID, | |
// "1.2.276.0.7230010.3.0.3.5.4"); | |
// outObj.set(DDict.dImplementationVersionName, "OFFIS_DCMTK_354 "); | |
/** | |
* Image related data attrs. | |
*/ | |
outObj.set(DDict.dPixelData, rawData); | |
outObj.set(DDict.dImageType, "ORIGINAL\\PRIMARY"); | |
outObj.set(DDict.dSpecificCharacterSet, "ISO_IR 100"); | |
outObj.set(DDict.dColumns, metadata.getWidth()); | |
outObj.set(DDict.dRows, metadata.getHeight()); | |
// outObj.set(DDict.dBitsAllocated, "8"); | |
// outObj.set(DDict.dBitsStored, "8"); | |
// outObj.set(DDict.dHighBit, "7"); | |
outObj.set(DDict.dBitsAllocated, "16"); | |
outObj.set(DDict.dBitsStored, "16"); | |
outObj.set(DDict.dHighBit, "15"); | |
outObj.set(DDict.dPixelRepresentation, "0"); | |
// outObj.set(DDict.dSharedFunctionalGroupsSequence, | |
// createSharedGroupSequence()); | |
outObj.set(DDict.dSamplesPerPixel, "1"); | |
outObj.set(DDict.dPhotometricInterpretation, "MONOCHROME2 "); | |
outObj.set(DDict.dNumberOfFrames, metadata.getFrames()); | |
// outObj.set(DDict.dImageLaterality, "R "); | |
/** | |
* General equipment module attrs | |
*/ | |
outObj.set(DDict.dManufacturer, "TopCon"); | |
outObj.set(DDict.dInstitutionName, ""); | |
outObj.set(DDict.dInstitutionAddress, ""); | |
outObj.set(DDict.dStationName, ""); | |
outObj.set(DDict.dInstitutionalDepartmentName, ""); | |
outObj.set(DDict.dManufacturerModelName, "OCT"); | |
outObj.set(DDict.dDeviceSerialNumber, ""); | |
outObj.set(DDict.dSoftwareVersion, | |
"FW-CAM 1.5.0.0\\FW-PWS 1.4.2.0\\FW-TSP 1.5.1.0\\SW-AQM 5.0.1.1 "); | |
/** | |
* General series module attrs | |
*/ | |
outObj.set(DDict.dModality, "OPT "); | |
outObj.set(DDict.dSeriesInstanceUID, | |
"1.3.6.1.4.1.33437.11.3.5604041.12963093945.145.3.1"); | |
outObj.set(DDict.dSeriesNumber, "2429001 "); | |
outObj.set(DDict.dImageLaterality, "L "); | |
outObj.set(DDict.dSeriesDate, "L "); | |
/** | |
* General study module attrs | |
*/ | |
outObj.set(DDict.dStudyID, "1767592277"); | |
outObj.set(DDict.dStudyDate, "20090212"); | |
outObj.set(DDict.dStudyTime, "152300"); | |
outObj.set(DDict.dPatientName, "test"); | |
outObj.set(DDict.dPatientID, "HRA, Vol, OCT, PROG "); | |
outObj.set(DDict.dStudyInstanceUID, | |
"1.3.6.1.4.1.33437.11.2.5604041.12963093944.145.2"); | |
outObj.set(DDict.dReferringPhysiciansName, ""); | |
outObj.set(DDict.dContentDate, "20090212"); | |
outObj.dumpVRs(System.out, true); | |
OutputStream outStream = new FileOutputStream(outputFileLoc); | |
new DicomWriter().write(outObj, outStream, true); | |
} | |
private static byte[] retrieveRawData() throws FileNotFoundException, | |
IOException { | |
File rawFile = new File("/home/tchan/Dropbox/RawFiles/3DOCT.raw"); | |
FileInputStream fin = new FileInputStream(rawFile); | |
byte[] rawData = new byte[(int) rawFile.length()]; | |
fin.read(rawData); | |
return rawData; | |
} | |
private static Object createSharedGroupSequence() throws DicomException { | |
// create a first sequence item | |
DicomObject sharedGroupSequence = new DicomObject(); | |
sharedGroupSequence.set(DDict.dReferencedImageSequence, | |
createReferencedImageSequence()); | |
sharedGroupSequence.set(DDict.dFrameAnatomySequence, | |
createFrameAnatomySequence()); | |
sharedGroupSequence.set(DDict.dPlaneOrientationSequence, | |
createPlaneOrientationSequence()); | |
sharedGroupSequence.set(DDict.dPixelMeasuresSequence, | |
createPixelMeasuresSequence()); | |
return sharedGroupSequence; | |
} | |
private static Object createFrameAnatomySequence() throws DicomException { | |
DicomObject item = new DicomObject(); | |
item.set(DDict.dAnatomicRegionSequence, createAnatomicRegionSequence()); | |
item.set(DDict.dFrameLaterality, "L "); | |
return item; | |
} | |
private static Object createAnatomicRegionSequence() throws DicomException { | |
DicomObject item = new DicomObject(); | |
item.set(DDict.dCodeValue, "T-AA610 "); | |
item.set(DDict.dCodingSchemeDesignator, "SRT "); | |
item.set(DDict.dCodeMeaning, "Retina"); | |
return item; | |
} | |
private static Object createPlaneOrientationSequence() | |
throws DicomException { | |
DicomObject item = new DicomObject(); | |
// item.set(DDict.dImageOrientationPatient, | |
// "1.000000\\0.000000\\0.000000\\0.000000\\1.000000\\0.000000 "); | |
return item; | |
} | |
private static Object createPixelMeasuresSequence() throws DicomException { | |
DicomObject item = new DicomObject(); | |
item.set(DDict.dSliceThickness, "0.252057"); | |
item.set(DDict.dPixelSpacing, "0.003867\\0.005911 "); | |
return item; | |
} | |
private static DicomObject createReferencedImageSequence() | |
throws DicomException { | |
DicomObject item = new DicomObject(); | |
item.set(DDict.dReferencedSOPClassUID, | |
"1.2.840.10008.5.1.4.1.1.77.1.5.1"); | |
item.set(DDict.dReferencedSOPInstanceUID, | |
"1.3.6.1.4.1.33437.11.4.5604041.12963093945.145.4.0.0"); | |
return item; | |
} | |
public DicomObject read(String location) throws IOException, DicomException { | |
FileInputStream fin = new FileInputStream(location); | |
DicomReader dcmReader = new DicomReader(); | |
DicomObject dcm = dcmReader.read(fin, true); | |
return dcm; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment