diff --git a/cadc-data-ops-fits/build.gradle b/cadc-data-ops-fits/build.gradle index c61750d5..d467ef85 100644 --- a/cadc-data-ops-fits/build.gradle +++ b/cadc-data-ops-fits/build.gradle @@ -12,21 +12,21 @@ repositories { sourceCompatibility = 1.8 group = 'org.opencadc' -version = '0.2.9' +version = '0.3.0' description = 'OpenCADC FITS cutout library' def git_url = 'https://github.com/opencadc/dal' dependencies { - compile 'org.opencadc:cadc-dali:[1.2.10,2.0.0)' - compile 'org.opencadc:cadc-util:[1.6,2.0)' - compile 'org.opencadc:cadc-soda-server:[1.2.1,2.0)' - compile 'org.opencadc:cadc-wcs:[2.0,3.0)' - compile 'org.opencadc:jsky:[1.0.0,2.0.0)' - compile 'org.opencadc:nom-tam-fits:[1.16.8,1.17.0)' + implementation 'org.opencadc:cadc-dali:[1.2.10,2.0.0)' + implementation 'org.opencadc:cadc-util:[1.6,2.0)' + implementation 'org.opencadc:cadc-soda-server:[1.2.1,2.0)' + implementation 'org.opencadc:cadc-wcs:[2.1.4,3.0)' + implementation 'org.opencadc:jsky:[1.0.0,2.0.0)' + implementation 'gov.nasa.gsfc.heasarc:nom-tam-fits:1.18.0' // Use JUnit test framework - testCompile 'junit:junit:[4.13,5.0)' + testImplementation 'junit:junit:[4.13,5.0)' } apply from: '../opencadc.gradle' diff --git a/cadc-data-ops-fits/src/main/java/org/opencadc/fits/FitsOperations.java b/cadc-data-ops-fits/src/main/java/org/opencadc/fits/FitsOperations.java index ff46cdcf..15485c5a 100644 --- a/cadc-data-ops-fits/src/main/java/org/opencadc/fits/FitsOperations.java +++ b/cadc-data-ops-fits/src/main/java/org/opencadc/fits/FitsOperations.java @@ -83,7 +83,7 @@ import nom.tam.fits.Header; import nom.tam.fits.HeaderCard; import nom.tam.util.Cursor; -import nom.tam.util.RandomAccessDataObject; +import nom.tam.util.RandomAccessFileIO; import org.apache.log4j.Logger; import org.opencadc.fits.slice.NDimensionalSlicer; import org.opencadc.soda.server.Cutout; @@ -96,9 +96,9 @@ public class FitsOperations { private static final Logger log = Logger.getLogger(FitsOperations.class); - private final RandomAccessDataObject src; + private final RandomAccessFileIO src; - public FitsOperations(RandomAccessDataObject src) { + public FitsOperations(RandomAccessFileIO src) { this.src = src; } diff --git a/cadc-data-ops-fits/src/main/java/org/opencadc/fits/RandomAccessStorageObject.java b/cadc-data-ops-fits/src/main/java/org/opencadc/fits/RandomAccessStorageObject.java new file mode 100644 index 00000000..84b291fc --- /dev/null +++ b/cadc-data-ops-fits/src/main/java/org/opencadc/fits/RandomAccessStorageObject.java @@ -0,0 +1,93 @@ +/* + ************************************************************************ + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** + * + * (c) 2023. (c) 2023. + * Government of Canada Gouvernement du Canada + * National Research Council Conseil national de recherches + * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 + * All rights reserved Tous droits réservés + * + * NRC disclaims any warranties, Le CNRC dénie toute garantie + * expressed, implied, or énoncée, implicite ou légale, + * statutory, of any kind with de quelque nature que ce + * respect to the software, soit, concernant le logiciel, + * including without limitation y compris sans restriction + * any warranty of merchantability toute garantie de valeur + * or fitness for a particular marchande ou de pertinence + * purpose. NRC shall not be pour un usage particulier. + * liable in any event for any Le CNRC ne pourra en aucun cas + * damages, whether direct or être tenu responsable de tout + * indirect, special or general, dommage, direct ou indirect, + * consequential or incidental, particulier ou général, + * arising from the use of the accessoire ou fortuit, résultant + * software. Neither the name de l'utilisation du logiciel. Ni + * of the National Research le nom du Conseil National de + * Council of Canada nor the Recherches du Canada ni les noms + * names of its contributors may de ses participants ne peuvent + * be used to endorse or promote être utilisés pour approuver ou + * products derived from this promouvoir les produits dérivés + * software without specific prior de ce logiciel sans autorisation + * written permission. préalable et particulière + * par écrit. + * + * This file is part of the Ce fichier fait partie du projet + * OpenCADC project. OpenCADC. + * + * OpenCADC is free software: OpenCADC est un logiciel libre ; + * you can redistribute it and/or vous pouvez le redistribuer ou le + * modify it under the terms of modifier suivant les termes de + * the GNU Affero General Public la “GNU Affero General Public + * License as published by the License” telle que publiée + * Free Software Foundation, par la Free Software Foundation + * either version 3 of the : soit la version 3 de cette + * License, or (at your option) licence, soit (à votre gré) + * any later version. toute version ultérieure. + * + * OpenCADC is distributed in the OpenCADC est distribué + * hope that it will be useful, dans l’espoir qu’il vous + * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE + * without even the implied GARANTIE : sans même la garantie + * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ + * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF + * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence + * General Public License for Générale Publique GNU Affero + * more details. pour plus de détails. + * + * You should have received Vous devriez avoir reçu une + * a copy of the GNU Affero copie de la Licence Générale + * General Public License along Publique GNU Affero avec + * with OpenCADC. If not, see OpenCADC ; si ce n’est + * . pas le cas, consultez : + * . + * + * + ************************************************************************ + */ + +package org.opencadc.fits; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + +import nom.tam.util.RandomAccessFileIO; + + +public class RandomAccessStorageObject extends RandomAccessFile implements RandomAccessFileIO { + public RandomAccessStorageObject(File file, String mode) throws FileNotFoundException { + super(file, mode); + } + + @Override + public long position() throws IOException { + return super.getFilePointer(); + } + + @Override + public void position(long n) throws IOException { + super.seek(n); + } +} diff --git a/cadc-data-ops-fits/src/main/java/org/opencadc/fits/slice/FITSHeaderWCSKeywords.java b/cadc-data-ops-fits/src/main/java/org/opencadc/fits/slice/FITSHeaderWCSKeywords.java index 5e2aae89..c84c9871 100644 --- a/cadc-data-ops-fits/src/main/java/org/opencadc/fits/slice/FITSHeaderWCSKeywords.java +++ b/cadc-data-ops-fits/src/main/java/org/opencadc/fits/slice/FITSHeaderWCSKeywords.java @@ -78,6 +78,7 @@ import java.util.Iterator; import java.util.Map; +import nom.tam.fits.FitsFactory; import nom.tam.fits.Header; import nom.tam.fits.HeaderCard; import nom.tam.fits.HeaderCardException; @@ -407,39 +408,54 @@ private Header cloneHeader(final Header source) throws HeaderCardException { return destination; } + /** + * Copy a header card with some potential modifications. COMMENT and HISTORY cards are truncated to the + * maximum length. + * @param destination The Header to write to. + * @param headerCardKey The current key. + * @param valueType The class type of the value. + * @param comment The comment value for COMMENT or HISTORY values. + * @param value The string value. + * @throws HeaderCardException + */ private void cloneHeaderCard(final Header destination, final String headerCardKey, final Class valueType, final String comment, final String value) throws HeaderCardException { // Check for blank lines or just plain comments that are not standard FITS comments. if (!StringUtil.hasText(headerCardKey)) { destination.addValue(headerCardKey, (String) null, comment); } else if (Standard.COMMENT.key().equals(headerCardKey)) { - destination.insertComment(comment); + if (StringUtil.hasText(comment) && comment.length() > HeaderCard.MAX_COMMENT_CARD_COMMENT_LENGTH) { + destination.insertComment(comment.substring(0, HeaderCard.MAX_COMMENT_CARD_COMMENT_LENGTH)); + } else { + destination.insertComment(comment); + } } else if (Standard.HISTORY.key().equals(headerCardKey)) { - destination.insertHistory(comment); + if (StringUtil.hasText(comment) && comment.length() > HeaderCard.MAX_COMMENT_CARD_COMMENT_LENGTH) { + destination.insertHistory(comment.substring(0, HeaderCard.MAX_COMMENT_CARD_COMMENT_LENGTH)); + } else { + destination.insertHistory(comment); + } } else if (headerCardKey.startsWith(CADCExt.CDELT.key())) { // CDELT values cannot be zero. final double cdeltValue = Double.parseDouble(value); - destination.addValue(headerCardKey, cdeltValue == 0.0D ? 1.0D : cdeltValue, - comment); + destination.addValue(headerCardKey, cdeltValue == 0.0D ? 1.0D : cdeltValue, comment); } else { if (valueType == String.class || valueType == null) { destination.addValue(headerCardKey, value, comment); } else if (valueType == Boolean.class) { destination.addValue(headerCardKey, Boolean.parseBoolean(value) || value.equals("T"), comment); } else if (valueType == Integer.class) { - destination.addValue(headerCardKey, Integer.parseInt(value), - comment); + destination.addValue(headerCardKey, Integer.parseInt(value), comment); } else if (valueType == BigInteger.class) { destination.addValue(headerCardKey, new BigInteger(value), comment); } else if (valueType == Long.class) { - destination.addValue(headerCardKey, Long.parseLong(value), - comment); + destination.addValue(headerCardKey, Long.parseLong(value), comment); } else if (valueType == Double.class) { - destination.addValue(headerCardKey, Double.parseDouble(value), - comment); + destination.addValue(headerCardKey, Double.parseDouble(value), comment); } else if (valueType == BigDecimal.class) { - destination.addValue(headerCardKey, new BigDecimal(value), - comment); + destination.addValue(headerCardKey, new BigDecimal(value), comment); + } else if (valueType == Float.class) { + destination.addValue(headerCardKey, Float.parseFloat(value), comment); } } } diff --git a/cadc-data-ops-fits/src/main/java/org/opencadc/fits/slice/NDimensionalSlicer.java b/cadc-data-ops-fits/src/main/java/org/opencadc/fits/slice/NDimensionalSlicer.java index efcd7233..7d1257c4 100644 --- a/cadc-data-ops-fits/src/main/java/org/opencadc/fits/slice/NDimensionalSlicer.java +++ b/cadc-data-ops-fits/src/main/java/org/opencadc/fits/slice/NDimensionalSlicer.java @@ -96,21 +96,24 @@ import nom.tam.fits.HeaderCardException; import nom.tam.fits.ImageData; import nom.tam.fits.ImageHDU; -import nom.tam.fits.StreamingImageData; import nom.tam.fits.header.DataDescription; +import nom.tam.fits.header.IFitsHeader; import nom.tam.fits.header.Standard; +import nom.tam.image.StreamingTileImageData; +import nom.tam.image.compression.CompressedImageTiler; import nom.tam.image.compression.hdu.CompressedImageHDU; import nom.tam.util.ArrayDataOutput; -import nom.tam.util.BufferedDataOutputStream; -import nom.tam.util.RandomAccessDataObject; -import nom.tam.util.RandomAccessFileExt; +import nom.tam.util.FitsOutputStream; +import nom.tam.util.RandomAccessFileIO; import org.apache.log4j.Logger; import org.opencadc.fits.HDUIterator; import org.opencadc.fits.NoOverlapException; +import org.opencadc.fits.RandomAccessStorageObject; import org.opencadc.soda.ExtensionSlice; import org.opencadc.soda.PixelRange; import org.opencadc.soda.server.Cutout; + /** * Slice out a portion of an image. This class will support the SODA Shapes and will delegate each cutout to its * appropriate handler (e.g. CircleCutout, EnergyCutout, etc.). @@ -142,7 +145,7 @@ public NDimensionalSlicer() { */ public void slice(final File fitsFile, final Cutout cutout, final OutputStream outputStream) throws FitsException, IOException, NoSuchKeywordException, NoOverlapException { - slice(new RandomAccessFileExt(fitsFile, "r"), cutout, outputStream); + slice(new RandomAccessStorageObject(fitsFile, "r"), cutout, outputStream); } /** @@ -165,14 +168,14 @@ public void slice(final File fitsFile, final Cutout cutout, final OutputStream o * @throws NoOverlapException Client error to inform that the supplied cutout is valid but yields no results. * @throws NoSuchKeywordException Reading the FITS file failed. */ - public void slice(final RandomAccessDataObject randomAccessDataObject, final Cutout cutout, + public void slice(final RandomAccessFileIO randomAccessDataObject, final Cutout cutout, final OutputStream outputStream) throws FitsException, IOException, NoOverlapException, NoSuchKeywordException { - final ArrayDataOutput output = new BufferedDataOutputStream(outputStream); + final ArrayDataOutput output = new FitsOutputStream(outputStream); slice(randomAccessDataObject, cutout, output); } - private void slice(final RandomAccessDataObject randomAccessDataObject, final Cutout cutout, + private void slice(final RandomAccessFileIO randomAccessDataObject, final Cutout cutout, final ArrayDataOutput output) throws FitsException, IOException, NoOverlapException, NoSuchKeywordException { if (isEmpty(cutout)) { @@ -181,7 +184,6 @@ private void slice(final RandomAccessDataObject randomAccessDataObject, final Cu // Single Fits object for the slice. It maintains state about itself such as the current read offset. final Fits fitsInput = new Fits(randomAccessDataObject); - fitsInput.setStreamWrite(true); // Reduce the requested extensions to only those that overlap. final Map> overlapHDUs = getOverlap(fitsInput, cutout); @@ -216,7 +218,6 @@ private void slice(final RandomAccessDataObject randomAccessDataObject, final Cu // Will write out to an ArrayDataOutput stream at the end. final Fits fitsOutput = new Fits(); - fitsOutput.setStreamWrite(true); LOGGER.debug("\nMEF Output: " + mefOutput + "\nMEF Input: " + mefInput); @@ -265,43 +266,80 @@ private void slice(final RandomAccessDataObject randomAccessDataObject, final Cu fitsOutput.write(output); } - private void setupPrimaryHeader(final Header headerCopy, final int nextEndSize) throws HeaderCardException { - final HeaderCard nextEndCard = headerCopy.findCard(DataDescription.NEXTEND); + private void setupPrimaryHeader(final Header header, final int nextEndSize) throws HeaderCardException { + final HeaderCard nextEndCard = header.findCard(DataDescription.NEXTEND); // Adjust the NEXTEND appropriately. if (nextEndCard == null) { - headerCopy.addValue(DataDescription.NEXTEND, nextEndSize); + header.addValue(DataDescription.NEXTEND, nextEndSize); } else { nextEndCard.setValue(nextEndSize); } - final HeaderCard extendFlagCard = headerCopy.findCard(Standard.EXTEND); + final HeaderCard extendFlagCard = header.findCard(Standard.EXTEND); // Adjust the EXTEND appropriately. if (extendFlagCard == null) { - headerCopy.addValue(Standard.EXTEND, true); + header.addValue(Standard.EXTEND, true); } else { extendFlagCard.setValue(true); } } + private void setupImageHeader(final Header header, final boolean mefOutput, final boolean firstHDUAlreadyWritten, + final int nextEndSize, final int[] dimensions) + throws FitsException { + header.deleteKey(Standard.SIMPLE); + header.deleteKey(Standard.XTENSION); + header.deleteKey(Standard.EXTEND); + header.deleteKey(Standard.TFIELDS); + + if (mefOutput) { + if (firstHDUAlreadyWritten) { + header.addValue(Standard.XTENSION, Standard.XTENSION_IMAGE); + } else { + header.addValue(Standard.SIMPLE, Boolean.TRUE); + setupPrimaryHeader(header, nextEndSize); + } + } else { + // MEF input to simple output. + header.addValue(Standard.SIMPLE, Boolean.TRUE); + } + + // Values set as per FITS standard for IMAGE and SIMPLE extensions. + header.addValue(Standard.PCOUNT, 0); + header.addValue(Standard.GCOUNT, 1); + } + private void writeSlices(final BasicHDU hdu, List extensionSliceList, final Fits fitsOutput, final boolean mefOutput, final boolean firstHDUAlreadyWritten, final int nextEndSize) throws FitsException, NoOverlapException { final int[] dimensions; + final Header header; if (hdu instanceof CompressedImageHDU) { + final CompressedImageHDU compressedImageHDU = (CompressedImageHDU) hdu; // Follow the ZNAXISn values, if present. - dimensions = ((CompressedImageHDU) hdu).getOriginalAxes(); + dimensions = compressedImageHDU.getImageAxes(); + header = compressedImageHDU.getImageHeader(); + + final Header originalHeader = compressedImageHDU.getHeader(); + + // EXTNAME and EXTVER aren't copied for some reason. + if (originalHeader.containsKey(Standard.EXTNAME) + && !originalHeader.getStringValue(Standard.EXTNAME).equals("COMPRESSED_IMAGE")) { + header.addValue(Standard.EXTNAME, originalHeader.getStringValue(Standard.EXTNAME)); + } + + if (originalHeader.containsKey(Standard.EXTVER)) { + header.addValue(Standard.EXTVER, originalHeader.getIntValue(Standard.EXTNAME)); + } } else { dimensions = hdu.getAxes(); + header = hdu.getHeader(); } LOGGER.debug("Writing slices with dimensions of " + Arrays.toString(dimensions)); - final ImageHDU imageHDU = (hdu instanceof CompressedImageHDU) - ? ((CompressedImageHDU) hdu).asImageHDU(true) : (ImageHDU) hdu; - final Header header = imageHDU.getHeader(); - for (final ExtensionSlice extensionSliceValue : extensionSliceList) { if (extensionSliceValue.getPixelRanges().isEmpty()) { fitsOutput.addHDU(hdu); @@ -313,6 +351,7 @@ private void writeSlices(final BasicHDU hdu, List extensionSl final int[] lengths = new int[dimensionLength]; final int[] steps = new int[dimensionLength]; + // We copy the header to preserve as much as we can, then we'll remove whatever is inappropriate. final Header headerCopy = copyHeader(header); fillCornersAndLengths(dimensions, headerCopy, extensionSliceValue, corners, lengths, steps); @@ -347,35 +386,20 @@ private void writeSlices(final BasicHDU hdu, List extensionSl } } - if (mefOutput) { - if (firstHDUAlreadyWritten) { - headerCopy.setXtension(Standard.XTENSION_IMAGE); - final HeaderCard pcountHeaderCard = headerCopy.findCard(Standard.PCOUNT); - final HeaderCard gcountHeaderCard = headerCopy.findCard(Standard.GCOUNT); + setupImageHeader(headerCopy, mefOutput, firstHDUAlreadyWritten, nextEndSize, dimensions); - if (pcountHeaderCard == null) { - headerCopy.addValue(Standard.PCOUNT, 0); - } - - if (gcountHeaderCard == null) { - headerCopy.addValue(Standard.GCOUNT, 1); - } - } else { - headerCopy.setSimple(true); - setupPrimaryHeader(headerCopy, nextEndSize); - } + final StreamingTileImageData streamingTileImageData; + if (hdu instanceof CompressedImageHDU) { + final CompressedImageHDU compressedImageHDU = (CompressedImageHDU) hdu; + final CompressedImageTiler compressedImageTiler = new CompressedImageTiler(compressedImageHDU); + streamingTileImageData = new StreamingTileImageData(headerCopy, compressedImageTiler, corners, + lengths, steps); } else { - // MEF input to simple output. - headerCopy.setSimple(true); + // Assume ImageHDU + streamingTileImageData = new StreamingTileImageData(headerCopy, ((ImageHDU) hdu).getTiler(), + corners, lengths, steps); } - - final StreamingImageData newImageData = - (StreamingImageData) FitsFactory.dataFactory(headerCopy, true); - // The tiler is where the source data comes from. - newImageData.setTiler(imageHDU.getTiler()); - newImageData.setTile(corners, lengths, steps); - - fitsOutput.addHDU(FitsFactory.hduFactory(headerCopy, newImageData)); + fitsOutput.addHDU(new ImageHDU(headerCopy, streamingTileImageData)); } } } @@ -399,7 +423,8 @@ private boolean isEmpty(final Cutout cutout) { */ private void fillCornersAndLengths(final int[] dimensions, final Header header, final ExtensionSlice extensionSliceValue, final int[] corners, - final int[] lengths, final int[] steps) { + final int[] lengths, final int[] steps) + throws FitsException { LOGGER.debug("Full dimensions are " + Arrays.toString(dimensions)); final int dimensionLength = dimensions.length; @@ -439,7 +464,8 @@ private void fillCornersAndLengths(final int[] dimensions, final Header header, // Adjust the NAXISn header appropriately. If the step value does not divide perfectly into the length, // then there will be an extra write, so add 1 where necessary. - header.setNaxis(i + 1, (nextLength / step) + ((nextLength % step) == 0 ? 0 : 1)); + header.addValue(Standard.NAXISn.n(i + 1), + (nextLength / step) + ((nextLength % step) == 0 ? 0 : 1)); // Need to set the values backwards (reverse order) to match the dimensions. corners[corners.length - i - 1] = lowerBound; @@ -476,21 +502,24 @@ private Header copyHeader(final Header source) throws HeaderCardException { destination.insertHistory(headerCard.getComment()); } else { if (valueType == String.class || valueType == null) { - destination.addValue(headerCard.getKey(), headerCard.getValue(), headerCard.getComment()); + destination.addValue(headerCardKey, headerCard.getValue(), headerCard.getComment()); } else if (valueType == Boolean.class) { - destination.addValue(headerCard.getKey(), Boolean.parseBoolean(headerCard.getValue()), + destination.addValue(headerCardKey, Boolean.parseBoolean(headerCard.getValue()), headerCard.getComment()); } else if (valueType == Integer.class || valueType == BigInteger.class) { - destination.addValue(headerCard.getKey(), new BigInteger(headerCard.getValue()), + destination.addValue(headerCardKey, new BigInteger(headerCard.getValue()), headerCard.getComment()); } else if (valueType == Long.class) { - destination.addValue(headerCard.getKey(), Long.parseLong(headerCard.getValue()), + destination.addValue(headerCardKey, Long.parseLong(headerCard.getValue()), headerCard.getComment()); } else if (valueType == Double.class) { - destination.addValue(headerCard.getKey(), Double.parseDouble(headerCard.getValue()), + destination.addValue(headerCardKey, Double.parseDouble(headerCard.getValue()), headerCard.getComment()); } else if (valueType == BigDecimal.class) { - destination.addValue(headerCard.getKey(), new BigDecimal(headerCard.getValue()), + destination.addValue(headerCardKey, new BigDecimal(headerCard.getValue()), + headerCard.getComment()); + } else if (valueType == Float.class) { + destination.addValue(headerCardKey, Float.parseFloat(headerCard.getValue()), headerCard.getComment()); } } @@ -499,6 +528,43 @@ private Header copyHeader(final Header source) throws HeaderCardException { return destination; } + private void addHeaderCard(final Header destination, final IFitsHeader headerCard, final Class valueType, + final String value) + throws FitsException { + final String headerCardKey = headerCard.key(); + + // Check for blank lines or just plain comments that are not standard FITS comments. + if (!StringUtil.hasText(headerCardKey)) { + destination.addValue(headerCardKey, (String) null, headerCard.comment()); + } else if (Standard.COMMENT.key().equals(headerCardKey)) { + destination.insertComment(headerCard.comment()); + } else if (Standard.HISTORY.key().equals(headerCardKey)) { + destination.insertHistory(headerCard.comment()); + } else { + if (valueType == String.class || valueType == null) { + destination.addValue(headerCardKey, value, headerCard.comment()); + } else if (valueType == Boolean.class) { + destination.addValue(headerCardKey, Boolean.parseBoolean(value), + headerCard.comment()); + } else if (valueType == Integer.class || valueType == BigInteger.class) { + destination.addValue(headerCardKey, new BigInteger(value), + headerCard.comment()); + } else if (valueType == Long.class) { + destination.addValue(headerCardKey, Long.parseLong(value), + headerCard.comment()); + } else if (valueType == Double.class) { + destination.addValue(headerCardKey, Double.parseDouble(value), + headerCard.comment()); + } else if (valueType == BigDecimal.class) { + destination.addValue(headerCardKey, new BigDecimal(value), + headerCard.comment()); + } else if (valueType == Float.class) { + destination.addValue(headerCardKey, Float.parseFloat(value), + headerCard.comment()); + } + } + } + private boolean matchHDU(final BasicHDU hdu, final String extensionName, final Integer extensionVersion) { final String extName = hdu.getTrimmedString(Standard.EXTNAME); @@ -563,7 +629,7 @@ private int mapOverlap(final BasicHDU hdu, final int hduIndex, final Listtr is null, it was a long way away from the WCS and does not // impose a limit/cutout - so we can safely skip it if (tr != null) { LOGGER.debug("Transformed coordinates: " + Arrays.toString(tr.coordinates)); diff --git a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/FitsOperationsTest.java b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/FitsOperationsTest.java index ce617036..abee0a8f 100644 --- a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/FitsOperationsTest.java +++ b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/FitsOperationsTest.java @@ -86,8 +86,7 @@ import nom.tam.fits.Header; import nom.tam.fits.HeaderCard; import nom.tam.util.Cursor; -import nom.tam.util.RandomAccessDataObject; -import nom.tam.util.RandomAccessFileExt; +import nom.tam.util.RandomAccessFileIO; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; @@ -113,8 +112,8 @@ public FitsOperationsTest() { public void testGetPrimaryHeader() { try { // setup - final RandomAccessDataObject randomAccessDataObject = - new RandomAccessFileExt(FileUtil.getFileFromResource("sample-mef.fits", + final RandomAccessFileIO randomAccessDataObject = + new RandomAccessStorageObject(FileUtil.getFileFromResource("sample-mef.fits", FitsOperationsTest.class), "r"); FitsOperations fop = new FitsOperations(randomAccessDataObject); @@ -140,8 +139,8 @@ public void testGetPrimaryHeader() { public void testGetHeaders() { try { // setup - final RandomAccessDataObject randomAccessDataObject = - new RandomAccessFileExt(FileUtil.getFileFromResource("sample-mef.fits", + final RandomAccessFileIO randomAccessDataObject = + new RandomAccessStorageObject(FileUtil.getFileFromResource("sample-mef.fits", FitsOperationsTest.class), "r"); FitsOperations fop = new FitsOperations(randomAccessDataObject); @@ -167,54 +166,63 @@ public void testGetHeaders() { } @Test - public void testHeaders() { - - try { - try (final RandomAccessDataObject randomAccessDataObject = - new RandomAccessFileExt(FileUtil.getFileFromResource("sample-mef.fits", - FitsOperationsTest.class), "r"); - final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { - // setup - final FitsOperations fop = new FitsOperations(randomAccessDataObject); - fop.headersToStream(byteArrayOutputStream); + public void testHeaders() throws Exception { + try (final RandomAccessFileIO randomAccessDataObject = + new RandomAccessStorageObject(FileUtil.getFileFromResource("sample-mef.fits", + FitsOperationsTest.class), "r"); + final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + // setup + final FitsOperations fop = new FitsOperations(randomAccessDataObject); + fop.headersToStream(byteArrayOutputStream); - final byte[] output = byteArrayOutputStream.toByteArray(); + final byte[] output = byteArrayOutputStream.toByteArray(); - final File sampleHeaderFile = FileUtil.getFileFromResource("sample-mef.txt", - FitsOperationsTest.class); - final List expectedHeaderLines = new ArrayList<>(); - try (final FileInputStream fileInputStream = new FileInputStream(sampleHeaderFile); - final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream))) { - String line; - while ((line = bufferedReader.readLine()) != null) { - expectedHeaderLines.add(line); - } + final File sampleHeaderFile = FileUtil.getFileFromResource("sample-mef.txt", + FitsOperationsTest.class); + final List expectedHeaderLines = new ArrayList<>(); + try (final FileInputStream fileInputStream = new FileInputStream(sampleHeaderFile); + final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + expectedHeaderLines.add(line); } + } - final List resultHeaderLines = new ArrayList<>(); - try (final BufferedReader bufferedReader = new BufferedReader( - new InputStreamReader(new ByteArrayInputStream(output)))) { - String line; - while ((line = bufferedReader.readLine()) != null) { - resultHeaderLines.add(line); - } + final List resultHeaderLines = new ArrayList<>(); + try (final BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader(new ByteArrayInputStream(output)))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + resultHeaderLines.add(line); } - - Assert.assertEquals("Wrong headers provided.", expectedHeaderLines, resultHeaderLines); } + for (int i = 0; i < expectedHeaderLines.size(); i++) { + final String nextExpectedHeaderLine = expectedHeaderLines.get(i); + final String nextResultHeaderLine = resultHeaderLines.get(i); + final HeaderCard expectedHeaderCard = HeaderCard.create(nextExpectedHeaderLine); + final HeaderCard resultHeaderCard = HeaderCard.create(nextResultHeaderLine); + + Assert.assertEquals("Wrong header key at '" + nextExpectedHeaderLine + "' == '" + + nextResultHeaderLine + "': " + i, expectedHeaderCard.getKey(), + resultHeaderCard.getKey()); + + Assert.assertEquals("Wrong header value at '" + nextExpectedHeaderLine + "' == '" + + nextResultHeaderLine + "': " + i, expectedHeaderCard.getValue(), + resultHeaderCard.getValue()); + } } catch (Exception unexpected) { log.error("unexpected exception", unexpected); - Assert.fail("unexpected exception: " + unexpected); + throw unexpected; } } @Test public void testSlice() throws Exception { // setup - final RandomAccessDataObject randomAccessDataObject = - new RandomAccessFileExt(FileUtil.getFileFromResource("test-hst-mef.fits", + final RandomAccessFileIO randomAccessDataObject = + new RandomAccessStorageObject(FileUtil.getFileFromResource("test-hst-mef.fits", FitsOperationsTest.class), "r"); final FitsOperations fop = new FitsOperations(randomAccessDataObject); final File outputFile = Files.createTempFile( @@ -233,7 +241,7 @@ public void testSlice() throws Exception { fop.cutoutToStream(cutout, fileOutputStream); } - final Fits resultsFits = new Fits(new RandomAccessFileExt(outputFile, "r")); + final Fits resultsFits = new Fits(new RandomAccessStorageObject(outputFile, "r")); resultsFits.read(); Assert.assertEquals("Wrong HDU count. Extensions 3, 106, and 126 should be available.", 4, @@ -255,8 +263,8 @@ public void testSlice() throws Exception { @Test public void testNoOverlap() throws Exception { - final RandomAccessDataObject randomAccessDataObject = - new RandomAccessFileExt(FileUtil.getFileFromResource("test-hst-mef.fits", + final RandomAccessFileIO randomAccessDataObject = + new RandomAccessStorageObject(FileUtil.getFileFromResource("test-hst-mef.fits", FitsOperationsTest.class), "r"); final FitsOperations fop = new FitsOperations(randomAccessDataObject); final File outputFile = Files.createTempFile( diff --git a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/FitsTest.java b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/FitsTest.java index 604c8d4d..d0728e13 100644 --- a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/FitsTest.java +++ b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/FitsTest.java @@ -128,9 +128,18 @@ public static void assertHeadersEqual(final Header expectedHeader, final Header if (expectedCard == null) { Assert.assertNull("Card " + headerCardKey.key() + " should be null.", resultCard); } else { + final Class valueType = expectedCard.valueType(); Assert.assertNotNull("Header " + headerCardKey.key() + " should not be null.", resultCard); - Assert.assertEquals("Header " + headerCardKey.key() + " has the wrong value.", - expectedCard.getValue(), resultCard.getValue()); + + // Floats have varying decimal place specifications, so compare them separately. + if (valueType == Float.class) { + Assert.assertEquals("Header " + headerCardKey.key() + " has the wrong value.", + Float.parseFloat(expectedCard.getValue()), + Float.parseFloat(resultCard.getValue()), 0.0F); + } else { + Assert.assertEquals("Header " + headerCardKey.key() + " has the wrong value.", + expectedCard.getValue(), resultCard.getValue()); + } } }); diff --git a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/BaseCutoutTest.java b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/BaseCutoutTest.java index 75159894..16c16201 100644 --- a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/BaseCutoutTest.java +++ b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/BaseCutoutTest.java @@ -73,12 +73,10 @@ import org.apache.log4j.Logger; import org.junit.Assert; -import java.io.File; import java.util.Arrays; public abstract class BaseCutoutTest { private static final Logger LOGGER = Logger.getLogger(BaseCutoutTest.class); - final static File DEFAULT_DATA_DIR = new File(System.getProperty("user.home") + "/.config/test-data"); // Concrete tests can set this if desired. long padding = 2; @@ -95,9 +93,10 @@ public abstract class BaseCutoutTest { */ void assertFuzzyPixelArrayEquals(final String message, final long[] expected, final long[] result) { if (result == null && expected != null) { - Assert.fail("Result array is null but expected " + Arrays.toString(expected)); + Assert.fail("Result array is null but expected " + Arrays.toString(expected) + + "\nMessage from test: " + message); } else if (result != null && expected == null) { - Assert.fail("Expected null but got " + Arrays.toString(result)); + Assert.fail("Expected null but got " + Arrays.toString(result) + "\nMessage from test: " + message); } else if (result != null) { LOGGER.debug("\n*****\nChecking array \n" + Arrays.toString(result) + "\nagainst\n" + Arrays.toString(expected) + "\n allowing a difference of " + padding + ".\n****"); diff --git a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/CircleCutoutTest.java b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/CircleCutoutTest.java index 7a7ae633..71bd1e8c 100644 --- a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/CircleCutoutTest.java +++ b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/CircleCutoutTest.java @@ -73,17 +73,19 @@ import ca.nrc.cadc.util.FileUtil; import ca.nrc.cadc.util.Log4jInit; import nom.tam.fits.Header; +import nom.tam.fits.HeaderCard; import nom.tam.util.ArrayDataInput; -import nom.tam.util.BufferedDataInputStream; +import nom.tam.util.FitsInputStream; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -107,8 +109,8 @@ public void testALMA() throws Exception { final String headerFileName = "test-alma-cube-header.txt"; final File testFile = FileUtil.getFileFromResource(headerFileName, CircleCutoutTest.class); - try (final InputStream inputStream = new FileInputStream(testFile); - final ArrayDataInput arrayDataInput = new BufferedDataInputStream(inputStream)) { + try (final InputStream inputStream = Files.newInputStream(testFile.toPath()); + final ArrayDataInput arrayDataInput = new FitsInputStream(inputStream)) { final Header testHeader = Header.readHeader(arrayDataInput); final Circle circle = new Circle(new Point(246.52D, -24.33D), 0.01D); @@ -139,9 +141,15 @@ public void testBLAST() throws Exception { LOGGER.debug("Reading header file " + headerFileName); - try (final InputStream inputStream = new FileInputStream(testFile); - final ArrayDataInput arrayDataInput = new BufferedDataInputStream(inputStream)) { - final Header testHeader = Header.readHeader(arrayDataInput); + try (final InputStream inputStream = Files.newInputStream(testFile.toPath()); + final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) { + + final Header testHeader = new Header(); + final char[] buff = new char[80]; + while (bufferedReader.read(buff) >= 0) { + testHeader.addLine(HeaderCard.create(new String(buff))); + } + final Circle circle = new Circle(new Point(309.8D, 42.7D), 0.3D); final CircleCutout circleCutout = new CircleCutout(testHeader); @@ -154,28 +162,6 @@ public void testBLAST() throws Exception { LOGGER.debug("CircleCutoutTest.testComputeBLAST OK: " + (System.currentTimeMillis() - startMillis) + " ms"); } - @Test - @Ignore("Bad header information? Pixels are off by ~5.") - public void testIRIS() throws Exception { - final long startMillis = System.currentTimeMillis(); - - final String headerFileName = "test-iris-header.txt"; - final File testFile = FileUtil.getFileFromResource(headerFileName, CircleCutoutTest.class); - - try (final InputStream inputStream = new FileInputStream(testFile); - final ArrayDataInput arrayDataInput = new BufferedDataInputStream(inputStream)) { - - final Header testHeader = Header.readHeader(arrayDataInput); - final Circle circle = new Circle(new Point(250.0D, 75.2D), 0.3D); - final CircleCutout circleCutout = new CircleCutout(testHeader); - - final long[] expected = new long[]{431, 463, 79, 110}; - final long[] result = circleCutout.getBounds(circle); - assertFuzzyPixelArrayEquals("Wrong IRIS circle bounds.", expected, result); - } - LOGGER.debug("CircleCutoutTest.testComputeIRIS OK: " + (System.currentTimeMillis() - startMillis) + " ms"); - } - @Test public void testOMM() throws Exception { final long startMillis = System.currentTimeMillis(); @@ -183,8 +169,8 @@ public void testOMM() throws Exception { final String headerFileName = "test-omm-header.txt"; final File testFile = FileUtil.getFileFromResource(headerFileName, CircleCutoutTest.class); - try (final InputStream inputStream = new FileInputStream(testFile); - final ArrayDataInput arrayDataInput = new BufferedDataInputStream(inputStream)) { + try (final InputStream inputStream = Files.newInputStream(testFile.toPath()); + final ArrayDataInput arrayDataInput = new FitsInputStream(inputStream)) { final Header testHeader = Header.readHeader(arrayDataInput); final Circle circle = new Circle(new Point(20.89D, -59.47D), 0.1D); @@ -226,8 +212,8 @@ public void testHSTMEF() throws Exception { final File testFile = FileUtil.getFileFromResource("test-hst-mef/" + headerFileName, CircleCutoutTest.class); - try (final InputStream inputStream = new FileInputStream(testFile); - final ArrayDataInput arrayDataInput = new BufferedDataInputStream(inputStream)) { + try (final InputStream inputStream = Files.newInputStream(testFile.toPath()); + final ArrayDataInput arrayDataInput = new FitsInputStream(inputStream)) { final Header testHeader = Header.readHeader(arrayDataInput); LOGGER.debug("Looking at HDU " + hduIndex); @@ -270,8 +256,8 @@ public void testNoOverlap() throws Exception { LOGGER.debug("Reading header file " + headerFileName); - try (final InputStream inputStream = new FileInputStream(testFile); - final ArrayDataInput arrayDataInput = new BufferedDataInputStream(inputStream)) { + try (final InputStream inputStream = Files.newInputStream(testFile.toPath()); + final ArrayDataInput arrayDataInput = new FitsInputStream(inputStream)) { final Header testHeader = Header.readHeader(arrayDataInput); final CircleCutout circleCutout = new CircleCutout(testHeader); assertFuzzyPixelArrayEquals("Should be empty.", null, circleCutout.getBounds(circle)); diff --git a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/FITSHeaderWCSKeywordsTest.java b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/FITSHeaderWCSKeywordsTest.java index 99dba2a3..4e5d4b91 100644 --- a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/FITSHeaderWCSKeywordsTest.java +++ b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/FITSHeaderWCSKeywordsTest.java @@ -72,12 +72,12 @@ import ca.nrc.cadc.util.Log4jInit; import nom.tam.fits.Fits; import nom.tam.fits.Header; -import nom.tam.util.RandomAccessDataObject; -import nom.tam.util.RandomAccessFileExt; +import nom.tam.util.RandomAccessFileIO; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Test; +import org.opencadc.fits.RandomAccessStorageObject; import java.math.BigDecimal; import java.util.Iterator; @@ -117,9 +117,9 @@ public void testEmptyHeaderConstructor() throws Exception { @Test public void testGet() throws Exception { final long startMillis = System.currentTimeMillis(); - try (final RandomAccessDataObject randomAccessDataObject = - new RandomAccessFileExt(FileUtil.getFileFromResource("sample-mef.fits", - FITSHeaderWCSKeywordsTest.class), "r"); + try (final RandomAccessFileIO randomAccessDataObject = + new RandomAccessStorageObject(FileUtil.getFileFromResource("sample-mef.fits", + FITSHeaderWCSKeywordsTest.class), "r"); final Fits fits = new Fits(randomAccessDataObject)) { // Just to cache it up front, and ensure that it can be read. @@ -137,6 +137,9 @@ public void testGet() throws Exception { if (valueType == Integer.class) { Assert.assertEquals("Wrong integer value.", Integer.parseInt(headerCardValue), testSubject.getIntValue(headerCardKey)); + } else if (valueType == Float.class) { + Assert.assertEquals("Wrong float value.", Float.parseFloat(headerCardValue), + testSubject.getFloatValue(headerCardKey), 0.0F); } else if (valueType == Double.class || valueType == BigDecimal.class) { Assert.assertEquals("Wrong double value.", Double.parseDouble(headerCardValue), testSubject.getDoubleValue(headerCardKey), 0.0D); @@ -157,8 +160,8 @@ public void testGet() throws Exception { @Test public void testIterator() throws Exception { final long startMillis = System.currentTimeMillis(); - try (final RandomAccessDataObject randomAccessDataObject = - new RandomAccessFileExt(FileUtil.getFileFromResource("sample-mef.fits", + try (final RandomAccessFileIO randomAccessDataObject = + new RandomAccessStorageObject(FileUtil.getFileFromResource("sample-mef.fits", FITSHeaderWCSKeywordsTest.class), "r"); final Fits fits = new Fits(randomAccessDataObject)) { diff --git a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/NDimensionalSlicerTest.java b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/NDimensionalSlicerTest.java index 937a1f86..e7bb8a35 100644 --- a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/NDimensionalSlicerTest.java +++ b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/NDimensionalSlicerTest.java @@ -72,7 +72,6 @@ import ca.nrc.cadc.util.Log4jInit; import java.io.DataOutputStream; import java.io.File; -import java.io.FileOutputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; @@ -81,14 +80,15 @@ import nom.tam.fits.BasicHDU; import nom.tam.fits.Fits; -import nom.tam.util.RandomAccessDataObject; -import nom.tam.util.RandomAccessFileExt; +import nom.tam.util.FitsOutputStream; +import nom.tam.util.RandomAccessFileIO; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Test; import org.opencadc.fits.FitsTest; import org.opencadc.fits.NoOverlapException; +import org.opencadc.fits.RandomAccessStorageObject; import org.opencadc.soda.ExtensionSlice; import org.opencadc.soda.ExtensionSliceFormat; import org.opencadc.soda.server.Cutout; @@ -123,7 +123,7 @@ public void testMEFFileSlice() throws Exception { final Path outputPath = Files.createTempFile(new File(testWriteDir).toPath(), "test-hst-mef-cutout", ".fits"); LOGGER.debug("Writing out to " + outputPath); - try (final OutputStream outputStream = new FileOutputStream(outputPath.toFile())) { + try (final OutputStream outputStream = Files.newOutputStream(outputPath.toFile().toPath())) { slicer.slice(file, cutout, outputStream); } @@ -187,8 +187,8 @@ public void testMEFRandomAccessSlice() throws Exception { final Path outputPath = Files.createTempFile(new File(testWriteDir).toPath(), "test-hst-mef-cutout", ".fits"); LOGGER.debug("Writing out to " + outputPath); - try (final RandomAccessDataObject randomAccessDataObject = new RandomAccessFileExt(file, "r"); - final OutputStream outputStream = new FileOutputStream(outputPath.toFile()); + try (final RandomAccessFileIO randomAccessDataObject = new RandomAccessStorageObject(file, "r"); + final OutputStream outputStream = Files.newOutputStream(outputPath.toFile().toPath()); final OutputStream hstFileCutoutStream = new DataOutputStream(outputStream)) { slicer.slice(randomAccessDataObject, cutout, hstFileCutoutStream); hstFileCutoutStream.flush(); @@ -222,8 +222,8 @@ public void testSimpleToMEF() throws Exception { final String testWriteDir = configuredTestWriteDir == null ? "/tmp" : configuredTestWriteDir; final Path outputPath = Files.createTempFile(new File(testWriteDir).toPath(), "test-simple-iris-cutout", ".fits"); - try (final RandomAccessDataObject randomAccessDataObject = new RandomAccessFileExt(file, "r"); - final OutputStream outputStream = new FileOutputStream(outputPath.toFile())) { + try (final RandomAccessFileIO randomAccessDataObject = new RandomAccessStorageObject(file, "r"); + final OutputStream outputStream = Files.newOutputStream(outputPath.toFile().toPath())) { slicer.slice(randomAccessDataObject, cutout, outputStream); outputStream.flush(); } @@ -252,8 +252,8 @@ public void testMEFToSimple() throws Exception { final Path outputPath = Files.createTempFile(new File(testWriteDir).toPath(), "test-simple-hst-cutout", ".fits"); LOGGER.debug("Writing out to " + outputPath); - try (final RandomAccessDataObject randomAccessDataObject = new RandomAccessFileExt(file, "r"); - final OutputStream hstFileCutoutStream = new FileOutputStream(outputPath.toFile())) { + try (final RandomAccessFileIO randomAccessDataObject = new RandomAccessStorageObject(file, "r"); + final OutputStream hstFileCutoutStream = Files.newOutputStream(outputPath.toFile().toPath())) { slicer.slice(randomAccessDataObject, cutout, hstFileCutoutStream); hstFileCutoutStream.flush(); } @@ -280,8 +280,8 @@ public void testNoSuchExtension() throws Exception { final Path outputPath = Files.createTempFile(new File(testWriteDir).toPath(), "test-simple-hst-cutout", ".fits"); LOGGER.debug("Writing out to " + outputPath); - try (final RandomAccessDataObject randomAccessDataObject = new RandomAccessFileExt(file, "r"); - final OutputStream hstFileCutoutStream = new FileOutputStream(outputPath.toFile())) { + try (final RandomAccessFileIO randomAccessDataObject = new RandomAccessStorageObject(file, "r"); + final OutputStream hstFileCutoutStream = Files.newOutputStream(outputPath.toFile().toPath())) { slicer.slice(randomAccessDataObject, cutout, hstFileCutoutStream); hstFileCutoutStream.flush(); } catch (NoOverlapException noOverlapException) { @@ -307,9 +307,8 @@ public void testDataInPrimaryHeader() throws Exception { final NDimensionalSlicer slicer = new NDimensionalSlicer(); final File file = Files.createTempFile("test-data-primary-", ".fits").toFile(); - try (final DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(file)); + try (final FitsOutputStream fitsOutputStream = new FitsOutputStream(Files.newOutputStream(file.toPath())); final Fits fits = new Fits()) { - fits.setStreamWrite(true); for (int i = 0; i < 101; i += 1) { for (int j = 0; j < 101; j += 1) { data0[i][j] = i * j; @@ -329,9 +328,10 @@ public void testDataInPrimaryHeader() throws Exception { data2[i][j] = i * j; } } - fits.addHDU(Fits.makeHDU(data2)); - fits.write(dataOutputStream); + fits.addHDU(Fits.makeHDU(data2)); + fits.write(fitsOutputStream); + fitsOutputStream.flush(); } final String configuredTestWriteDir = System.getenv("TEST_WRITE_DIR"); @@ -344,8 +344,8 @@ public void testDataInPrimaryHeader() throws Exception { LOGGER.debug("Writing out to " + outputPath); - try (final RandomAccessDataObject randomAccessDataObject = new RandomAccessFileExt(file, "r"); - final OutputStream outputStream = new FileOutputStream(outputPath.toFile())) { + try (final RandomAccessFileIO randomAccessDataObject = new RandomAccessStorageObject(file, "r"); + final OutputStream outputStream = Files.newOutputStream(outputPath.toFile().toPath())) { slicer.slice(randomAccessDataObject, cutout, outputStream); outputStream.flush(); } catch (IllegalArgumentException illegalArgumentException) { @@ -354,7 +354,6 @@ public void testDataInPrimaryHeader() throws Exception { } try (final Fits checkFits = new Fits(outputPath.toFile())) { - checkFits.setStreamWrite(true); checkFits.read(); int index = 0; diff --git a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/WCSCutoutUtilTest.java b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/WCSCutoutUtilTest.java index b1c9b296..7176b15c 100644 --- a/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/WCSCutoutUtilTest.java +++ b/cadc-data-ops-fits/src/test/java/org/opencadc/fits/slice/WCSCutoutUtilTest.java @@ -74,8 +74,7 @@ import ca.nrc.cadc.util.FileUtil; import ca.nrc.cadc.util.Log4jInit; import nom.tam.fits.Header; -import nom.tam.util.ArrayDataInput; -import nom.tam.util.BufferedDataInputStream; +import nom.tam.fits.HeaderCard; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; @@ -83,15 +82,18 @@ import org.opencadc.soda.PixelRange; import org.opencadc.soda.server.Cutout; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; public class WCSCutoutUtilTest extends BaseCutoutTest { private static final Logger LOGGER = Logger.getLogger(WCSCutoutUtilTest.class); static { + Log4jInit.setLevel("ca.nrc.cadc.wcs", Level.DEBUG); Log4jInit.setLevel("org.opencadc.fits.slice", Level.DEBUG); } @@ -105,9 +107,14 @@ public void testMultipleWCS() throws Exception { cutout.pos = new Circle(new Point(128.638D, 17.33D), 0.01D); cutout.band = new Interval<>(1.3606E-3D, 1.3616E-3D); - try (final InputStream inputStream = new FileInputStream(testFile); - final ArrayDataInput arrayDataInput = new BufferedDataInputStream(inputStream)) { - final Header testHeader = Header.readHeader(arrayDataInput); + try (final InputStream inputStream = Files.newInputStream(testFile.toPath()); + final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) { + final Header testHeader = new Header(); + final char[] buff = new char[80]; + while (bufferedReader.read(buff) >= 0) { + testHeader.addLine(HeaderCard.create(new String(buff))); + } + final PixelRange[] resultRanges = WCSCutoutUtil.getBounds(testHeader, cutout); // Combined Circle cutout (axes 1 & 2), as well as Band cutout on axis 3.