diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6481e0c..b32c49d 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -27,8 +27,24 @@ jobs:
distribution: corretto
cache: maven
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.12'
+
+ - name: Install reference file generator requirements
+ run: |
+ pip install -r test-requirements.txt
+
+ - name: Locate Python
+ id: locate-python
+ run:
+ echo "python-path=`which python`" >> "$GITHUB_OUTPUT"
+
- name: Execute tests
run: mvn clean verify
+ env:
+ GWCS_JAVA_TESTS_PYTHON_PATH: ${{ steps.locate-python.outputs.python-path }}
- name: Add code coverage PR comment
uses: madrapps/jacoco-report@v1.7.2
diff --git a/pom.xml b/pom.xml
index 4bd672c..4005e7c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,7 +35,7 @@
11
dev
1.18.36
- 0.1-alpha-8
+ 0.1-beta-1
0.44.0
3.4.0
1.7.0
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/AsdfNodeUtils.java b/src/main/java/edu/stsci/gwcs/asdf/converter/AsdfNodeUtils.java
index 027dc12..01c4126 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/AsdfNodeUtils.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/AsdfNodeUtils.java
@@ -1,5 +1,6 @@
package edu.stsci.gwcs.asdf.converter;
+import org.asdfformat.asdf.ndarray.DoubleNdArray;
import org.asdfformat.asdf.node.AsdfNode;
import java.util.List;
@@ -14,7 +15,17 @@ public static String[] readStringArray(final AsdfNode node, final String key) {
}
public static int[] readIntArray(final AsdfNode node, final String key) {
- final List list = node.getList(key, Integer.class);
+ final AsdfNode child = node.get(key);
+ if (child.isNdArray()) {
+ final DoubleNdArray ndArray = child.asNdArray().asDoubleNdArray();
+ final int length = ndArray.getShape().get(0);
+ final int[] result = new int[length];
+ for (int i = 0; i < length; i++) {
+ result[i] = (int) ndArray.get(i);
+ }
+ return result;
+ }
+ final List list = child.asList(Integer.class);
final int[] result = new int[list.size()];
for (int i = 0; i < result.length; i++) {
result[i] = list.get(i);
@@ -23,7 +34,17 @@ public static int[] readIntArray(final AsdfNode node, final String key) {
}
public static double[] readDoubleArray(final AsdfNode node, final String key) {
- final List list = node.getList(key, Double.class);
+ final AsdfNode child = node.get(key);
+ if (child.isNdArray()) {
+ final DoubleNdArray ndArray = child.asNdArray().asDoubleNdArray();
+ final int length = ndArray.getShape().get(0);
+ final double[] result = new double[length];
+ for (int i = 0; i < length; i++) {
+ result[i] = ndArray.get(i);
+ }
+ return result;
+ }
+ final List list = child.asList(Double.class);
final double[] result = new double[list.size()];
for (int i = 0; i < result.length; i++) {
result[i] = list.get(i);
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/StepConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/StepConverter.java
index dc4dd93..6bc2cb9 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/StepConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/StepConverter.java
@@ -12,6 +12,7 @@
public class StepConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:gwcs/step-1.1.0",
+ "tag:stsci.edu:gwcs/step-1.2.0",
"tag:stsci.edu:gwcs/step-1.3.0"
);
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/WcsConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/WcsConverter.java
index f7c01ec..2557333 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/WcsConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/WcsConverter.java
@@ -10,6 +10,7 @@
public class WcsConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:gwcs/wcs-1.2.0",
+ "tag:stsci.edu:gwcs/wcs-1.3.0",
"tag:stsci.edu:gwcs/wcs-1.4.0"
);
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/frame/CelestialFrameConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/frame/CelestialFrameConverter.java
index 244c5d9..5728d6c 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/frame/CelestialFrameConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/frame/CelestialFrameConverter.java
@@ -11,6 +11,7 @@
public class CelestialFrameConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:gwcs/celestial_frame-1.0.0",
+ "tag:stsci.edu:gwcs/celestial_frame-1.1.0",
"tag:stsci.edu:gwcs/celestial_frame-1.2.0"
);
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/frame/Frame2DConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/frame/Frame2DConverter.java
index 263befc..704ce4c 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/frame/Frame2DConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/frame/Frame2DConverter.java
@@ -11,6 +11,7 @@
public class Frame2DConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:gwcs/frame2d-1.0.0",
+ "tag:stsci.edu:gwcs/frame2d-1.1.0",
"tag:stsci.edu:gwcs/frame2d-1.2.0"
);
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/ConstantConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/ConstantConverter.java
index cb6a274..c30da26 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/ConstantConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/ConstantConverter.java
@@ -11,7 +11,8 @@
public class ConstantConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/constant-1.4.0",
- "tag:stsci.edu:asdf/transform/constant-1.5.0"
+ "tag:stsci.edu:asdf/transform/constant-1.5.0",
+ "tag:stsci.edu:asdf/transform/constant-1.6.0"
);
public ConstantConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/IdentityConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/IdentityConverter.java
index 5deeb00..d331671 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/IdentityConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/IdentityConverter.java
@@ -11,7 +11,8 @@
public class IdentityConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/identity-1.2.0",
- "tag:stsci.edu:asdf/transform/identity-1.3.0"
+ "tag:stsci.edu:asdf/transform/identity-1.3.0",
+ "tag:stsci.edu:asdf/transform/identity-1.4.0"
);
public IdentityConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/RemapAxesConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/RemapAxesConverter.java
index e90a994..70c4568 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/RemapAxesConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/RemapAxesConverter.java
@@ -12,7 +12,8 @@
public class RemapAxesConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/remap_axes-1.3.0",
- "tag:stsci.edu:asdf/transform/remap_axes-1.4.0"
+ "tag:stsci.edu:asdf/transform/remap_axes-1.4.0",
+ "tag:stsci.edu:asdf/transform/remap_axes-1.5.0"
);
public RemapAxesConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/AddConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/AddConverter.java
index 8cf4b72..5106118 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/AddConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/AddConverter.java
@@ -9,7 +9,8 @@
public class AddConverter extends BinaryCompoundConverter {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/add-1.2.0",
- "tag:stsci.edu:asdf/transform/add-1.3.0"
+ "tag:stsci.edu:asdf/transform/add-1.3.0",
+ "tag:stsci.edu:asdf/transform/add-1.4.0"
);
public AddConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/ComposeConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/ComposeConverter.java
index fc6b223..1578e16 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/ComposeConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/ComposeConverter.java
@@ -9,7 +9,8 @@
public class ComposeConverter extends BinaryCompoundConverter {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/compose-1.2.0",
- "tag:stsci.edu:asdf/transform/compose-1.3.0"
+ "tag:stsci.edu:asdf/transform/compose-1.3.0",
+ "tag:stsci.edu:asdf/transform/compose-1.4.0"
);
public ComposeConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/ConcatenateConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/ConcatenateConverter.java
index 5b2acef..b181bc0 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/ConcatenateConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/ConcatenateConverter.java
@@ -9,7 +9,8 @@
public class ConcatenateConverter extends BinaryCompoundConverter {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/concatenate-1.2.0",
- "tag:stsci.edu:asdf/transform/concatenate-1.3.0"
+ "tag:stsci.edu:asdf/transform/concatenate-1.3.0",
+ "tag:stsci.edu:asdf/transform/concatenate-1.4.0"
);
public ConcatenateConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/DivideConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/DivideConverter.java
index c8e94de..286959c 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/DivideConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/DivideConverter.java
@@ -9,7 +9,8 @@
public class DivideConverter extends BinaryCompoundConverter {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/divide-1.2.0",
- "tag:stsci.edu:asdf/transform/divide-1.3.0"
+ "tag:stsci.edu:asdf/transform/divide-1.3.0",
+ "tag:stsci.edu:asdf/transform/divide-1.4.0"
);
public DivideConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/FixInputsConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/FixInputsConverter.java
index 0bfac2f..17c13b9 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/FixInputsConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/FixInputsConverter.java
@@ -1,20 +1,21 @@
package edu.stsci.gwcs.asdf.converter.transform.compound;
import edu.stsci.gwcs.asdf.GwcsAsdfSupport;
+import edu.stsci.gwcs.asdf.converter.AsdfNodeUtils;
import edu.stsci.gwcs.asdf.converter.ConverterBase;
import edu.stsci.gwcs.transform.Transform;
import edu.stsci.gwcs.transform.compound.FixInputs;
import org.asdfformat.asdf.node.AsdfNode;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import java.util.Set;
public class FixInputsConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/fix_inputs-1.2.0",
- "tag:stsci.edu:asdf/transform/fix_inputs-1.3.0"
+ "tag:stsci.edu:asdf/transform/fix_inputs-1.3.0",
+ "tag:stsci.edu:asdf/transform/fix_inputs-1.4.0"
);
public FixInputsConverter(final GwcsAsdfSupport support) {
@@ -27,18 +28,18 @@ public Transform fromAsdfNode(final AsdfNode node) {
final Transform delegate = support().deserializeTransform(forwardNode.get(0L));
final AsdfNode mappingNode = forwardNode.get(1L);
- final List keys = mappingNode.getList("keys", Integer.class);
- final List values = mappingNode.getList("values", Double.class);
+ final int[] keys = AsdfNodeUtils.readIntArray(mappingNode, "keys");
+ final double[] values = AsdfNodeUtils.readDoubleArray(mappingNode, "values");
- if (keys.size() != values.size()) {
+ if (keys.length != values.length) {
throw new IllegalArgumentException(
"fix_inputs keys and values must have the same length, got "
- + keys.size() + " keys and " + values.size() + " values");
+ + keys.length + " keys and " + values.length + " values");
}
final Map fixedInputs = new LinkedHashMap<>();
- for (int i = 0; i < keys.size(); i++) {
- fixedInputs.put(keys.get(i), values.get(i));
+ for (int i = 0; i < keys.length; i++) {
+ fixedInputs.put(keys[i], values[i]);
}
return new FixInputs(delegate, fixedInputs);
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/MultiplyConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/MultiplyConverter.java
index 1092780..670a223 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/MultiplyConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/MultiplyConverter.java
@@ -9,7 +9,8 @@
public class MultiplyConverter extends BinaryCompoundConverter {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/multiply-1.2.0",
- "tag:stsci.edu:asdf/transform/multiply-1.3.0"
+ "tag:stsci.edu:asdf/transform/multiply-1.3.0",
+ "tag:stsci.edu:asdf/transform/multiply-1.4.0"
);
public MultiplyConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/PowerConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/PowerConverter.java
index 7d7072d..4c6b731 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/PowerConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/PowerConverter.java
@@ -9,7 +9,8 @@
public class PowerConverter extends BinaryCompoundConverter {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/power-1.2.0",
- "tag:stsci.edu:asdf/transform/power-1.3.0"
+ "tag:stsci.edu:asdf/transform/power-1.3.0",
+ "tag:stsci.edu:asdf/transform/power-1.4.0"
);
public PowerConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/SubtractConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/SubtractConverter.java
index d07c770..73c6fea 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/SubtractConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/compound/SubtractConverter.java
@@ -9,7 +9,8 @@
public class SubtractConverter extends BinaryCompoundConverter {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/subtract-1.2.0",
- "tag:stsci.edu:asdf/transform/subtract-1.3.0"
+ "tag:stsci.edu:asdf/transform/subtract-1.3.0",
+ "tag:stsci.edu:asdf/transform/subtract-1.4.0"
);
public SubtractConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/AffineConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/AffineConverter.java
index aa2b1b4..8e68028 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/AffineConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/AffineConverter.java
@@ -12,7 +12,8 @@
public class AffineConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/affine-1.3.0",
- "tag:stsci.edu:asdf/transform/affine-1.4.0"
+ "tag:stsci.edu:asdf/transform/affine-1.4.0",
+ "tag:stsci.edu:asdf/transform/affine-1.5.0"
);
public AffineConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/ScaleConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/ScaleConverter.java
index 40a9a74..2f97433 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/ScaleConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/ScaleConverter.java
@@ -11,7 +11,8 @@
public class ScaleConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/scale-1.2.0",
- "tag:stsci.edu:asdf/transform/scale-1.3.0"
+ "tag:stsci.edu:asdf/transform/scale-1.3.0",
+ "tag:stsci.edu:asdf/transform/scale-1.4.0"
);
public ScaleConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/ShiftConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/ShiftConverter.java
index 9818962..b99e75c 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/ShiftConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/functional/ShiftConverter.java
@@ -11,7 +11,8 @@
public class ShiftConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/shift-1.2.0",
- "tag:stsci.edu:asdf/transform/shift-1.3.0"
+ "tag:stsci.edu:asdf/transform/shift-1.3.0",
+ "tag:stsci.edu:asdf/transform/shift-1.4.0"
);
public ShiftConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/geometry/DirectionCosinesConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/geometry/DirectionCosinesConverter.java
index 06812df..7a304f0 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/geometry/DirectionCosinesConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/geometry/DirectionCosinesConverter.java
@@ -12,6 +12,8 @@
public class DirectionCosinesConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:gwcs/direction_cosines-1.0.0",
+ "tag:stsci.edu:gwcs/direction_cosines-1.1.0",
+ "tag:stsci.edu:gwcs/direction_cosines-1.2.0",
"tag:stsci.edu:gwcs/direction_cosines-1.3.0"
);
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/geometry/SphericalCartesianConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/geometry/SphericalCartesianConverter.java
index 85a0b03..5233d1b 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/geometry/SphericalCartesianConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/geometry/SphericalCartesianConverter.java
@@ -12,6 +12,8 @@
public class SphericalCartesianConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:gwcs/spherical_cartesian-1.0.0",
+ "tag:stsci.edu:gwcs/spherical_cartesian-1.1.0",
+ "tag:stsci.edu:gwcs/spherical_cartesian-1.2.0",
"tag:stsci.edu:gwcs/spherical_cartesian-1.3.0"
);
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/polynomial/PolynomialConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/polynomial/PolynomialConverter.java
index ce981c2..2f11380 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/polynomial/PolynomialConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/polynomial/PolynomialConverter.java
@@ -13,7 +13,8 @@
public class PolynomialConverter extends ConverterBase {
private static final Set TAGS = Set.of(
- "tag:stsci.edu:asdf/transform/polynomial-1.2.0"
+ "tag:stsci.edu:asdf/transform/polynomial-1.2.0",
+ "tag:stsci.edu:asdf/transform/polynomial-1.3.0"
);
public PolynomialConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/projection/ProjectionConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/projection/ProjectionConverter.java
index 8197fa9..9902497 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/projection/ProjectionConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/projection/ProjectionConverter.java
@@ -42,58 +42,93 @@ public class ProjectionConverter extends ConverterBase {
private static final Set TAGS = Set.of(
TAG_PREFIX + "gnomonic-1.2.0",
TAG_PREFIX + "gnomonic-1.3.0",
+ TAG_PREFIX + "gnomonic-1.4.0",
TAG_PREFIX + "stereographic-1.2.0",
TAG_PREFIX + "stereographic-1.3.0",
+ TAG_PREFIX + "stereographic-1.4.0",
TAG_PREFIX + "zenithal_equal_area-1.2.0",
TAG_PREFIX + "zenithal_equal_area-1.3.0",
+ TAG_PREFIX + "zenithal_equal_area-1.4.0",
TAG_PREFIX + "zenithal_equidistant-1.2.0",
TAG_PREFIX + "zenithal_equidistant-1.3.0",
+ TAG_PREFIX + "zenithal_equidistant-1.4.0",
TAG_PREFIX + "zenithal_perspective-1.2.0",
TAG_PREFIX + "zenithal_perspective-1.3.0",
+ TAG_PREFIX + "zenithal_perspective-1.4.0",
+ TAG_PREFIX + "zenithal_perspective-1.5.0",
TAG_PREFIX + "slant_zenithal_perspective-1.2.0",
TAG_PREFIX + "slant_zenithal_perspective-1.3.0",
+ TAG_PREFIX + "slant_zenithal_perspective-1.4.0",
TAG_PREFIX + "slant_orthographic-1.2.0",
TAG_PREFIX + "slant_orthographic-1.3.0",
+ TAG_PREFIX + "slant_orthographic-1.4.0",
TAG_PREFIX + "airy-1.2.0",
TAG_PREFIX + "airy-1.3.0",
+ TAG_PREFIX + "airy-1.4.0",
TAG_PREFIX + "conic_perspective-1.2.0",
TAG_PREFIX + "conic_perspective-1.3.0",
+ TAG_PREFIX + "conic_perspective-1.4.0",
+ TAG_PREFIX + "conic_perspective-1.5.0",
TAG_PREFIX + "conic_equal_area-1.2.0",
TAG_PREFIX + "conic_equal_area-1.3.0",
+ TAG_PREFIX + "conic_equal_area-1.4.0",
+ TAG_PREFIX + "conic_equal_area-1.5.0",
TAG_PREFIX + "conic_equidistant-1.2.0",
TAG_PREFIX + "conic_equidistant-1.3.0",
+ TAG_PREFIX + "conic_equidistant-1.4.0",
+ TAG_PREFIX + "conic_equidistant-1.5.0",
TAG_PREFIX + "conic_orthomorphic-1.2.0",
TAG_PREFIX + "conic_orthomorphic-1.3.0",
+ TAG_PREFIX + "conic_orthomorphic-1.4.0",
+ TAG_PREFIX + "conic_orthomorphic-1.5.0",
TAG_PREFIX + "cylindrical_perspective-1.2.0",
TAG_PREFIX + "cylindrical_perspective-1.3.0",
+ TAG_PREFIX + "cylindrical_perspective-1.4.0",
+ TAG_PREFIX + "cylindrical_perspective-1.5.0",
TAG_PREFIX + "cylindrical_equal_area-1.2.0",
TAG_PREFIX + "cylindrical_equal_area-1.3.0",
+ TAG_PREFIX + "cylindrical_equal_area-1.4.0",
+ TAG_PREFIX + "cylindrical_equal_area-1.5.0",
TAG_PREFIX + "mercator-1.2.0",
TAG_PREFIX + "mercator-1.3.0",
+ TAG_PREFIX + "mercator-1.4.0",
TAG_PREFIX + "plate_carree-1.2.0",
TAG_PREFIX + "plate_carree-1.3.0",
+ TAG_PREFIX + "plate_carree-1.4.0",
TAG_PREFIX + "bonne_equal_area-1.2.0",
TAG_PREFIX + "bonne_equal_area-1.3.0",
+ TAG_PREFIX + "bonne_equal_area-1.4.0",
+ TAG_PREFIX + "bonne_equal_area-1.5.0",
TAG_PREFIX + "polyconic-1.2.0",
TAG_PREFIX + "polyconic-1.3.0",
+ TAG_PREFIX + "polyconic-1.4.0",
TAG_PREFIX + "hammer_aitoff-1.2.0",
TAG_PREFIX + "hammer_aitoff-1.3.0",
- TAG_PREFIX + "mollweide-1.2.0",
- TAG_PREFIX + "mollweide-1.3.0",
+ TAG_PREFIX + "hammer_aitoff-1.4.0",
+ TAG_PREFIX + "molleweide-1.2.0",
+ TAG_PREFIX + "molleweide-1.3.0",
+ TAG_PREFIX + "molleweide-1.4.0",
TAG_PREFIX + "parabolic-1.2.0",
TAG_PREFIX + "parabolic-1.3.0",
+ TAG_PREFIX + "parabolic-1.4.0",
TAG_PREFIX + "sanson_flamsteed-1.2.0",
TAG_PREFIX + "sanson_flamsteed-1.3.0",
+ TAG_PREFIX + "sanson_flamsteed-1.4.0",
TAG_PREFIX + "healpix-1.2.0",
TAG_PREFIX + "healpix-1.3.0",
+ TAG_PREFIX + "healpix-1.4.0",
TAG_PREFIX + "healpix_polar-1.2.0",
TAG_PREFIX + "healpix_polar-1.3.0",
+ TAG_PREFIX + "healpix_polar-1.4.0",
TAG_PREFIX + "quad_spherical_cube-1.2.0",
TAG_PREFIX + "quad_spherical_cube-1.3.0",
+ TAG_PREFIX + "quad_spherical_cube-1.4.0",
TAG_PREFIX + "cobe_quad_spherical_cube-1.2.0",
TAG_PREFIX + "cobe_quad_spherical_cube-1.3.0",
+ TAG_PREFIX + "cobe_quad_spherical_cube-1.4.0",
TAG_PREFIX + "tangential_spherical_cube-1.2.0",
- TAG_PREFIX + "tangential_spherical_cube-1.3.0"
+ TAG_PREFIX + "tangential_spherical_cube-1.3.0",
+ TAG_PREFIX + "tangential_spherical_cube-1.4.0"
);
public ProjectionConverter(final GwcsAsdfSupport support) {
@@ -181,7 +216,7 @@ private static Projection createProjection(final String name, final AsdfNode nod
return new Polyconic(direction);
case "hammer_aitoff":
return new HammerAitoff(direction);
- case "mollweide":
+ case "molleweide":
return new Mollweide(direction);
case "parabolic":
return new Parabolic(direction);
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/Rotate3DConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/Rotate3DConverter.java
index 7b56e0f..062cc2c 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/Rotate3DConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/Rotate3DConverter.java
@@ -13,7 +13,8 @@
public class Rotate3DConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/rotate3d-1.3.0",
- "tag:stsci.edu:asdf/transform/rotate3d-1.4.0"
+ "tag:stsci.edu:asdf/transform/rotate3d-1.4.0",
+ "tag:stsci.edu:asdf/transform/rotate3d-1.5.0"
);
public Rotate3DConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/RotateSequence3DConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/RotateSequence3DConverter.java
index f2ebc9c..db1127e 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/RotateSequence3DConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/RotateSequence3DConverter.java
@@ -1,17 +1,18 @@
package edu.stsci.gwcs.asdf.converter.transform.rotation;
import edu.stsci.gwcs.asdf.GwcsAsdfSupport;
+import edu.stsci.gwcs.asdf.converter.AsdfNodeUtils;
import edu.stsci.gwcs.asdf.converter.ConverterBase;
import edu.stsci.gwcs.transform.Transform;
import edu.stsci.gwcs.transform.rotation.RotateSequence3D;
import org.asdfformat.asdf.node.AsdfNode;
-import java.util.List;
import java.util.Set;
public class RotateSequence3DConverter extends ConverterBase {
private static final Set TAGS = Set.of(
- "tag:stsci.edu:asdf/transform/rotate_sequence_3d-1.1.0"
+ "tag:stsci.edu:asdf/transform/rotate_sequence_3d-1.1.0",
+ "tag:stsci.edu:asdf/transform/rotate_sequence_3d-1.2.0"
);
public RotateSequence3DConverter(final GwcsAsdfSupport support) {
@@ -25,11 +26,7 @@ public Transform fromAsdfNode(final AsdfNode node) {
throw new IllegalArgumentException("Unsupported rotation_type: " + rotationType);
}
- final List anglesList = node.getList("angles", Double.class);
- final double[] angles = new double[anglesList.size()];
- for (int i = 0; i < angles.length; i++) {
- angles[i] = anglesList.get(i);
- }
+ final double[] angles = AsdfNodeUtils.readDoubleArray(node, "angles");
final String axesOrder = node.getString("axes_order");
return new RotateSequence3D(angles, axesOrder);
}
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/Rotation2DConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/Rotation2DConverter.java
index ea5f860..81afe9a 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/Rotation2DConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/rotation/Rotation2DConverter.java
@@ -11,7 +11,8 @@
public class Rotation2DConverter extends ConverterBase {
private static final Set TAGS = Set.of(
"tag:stsci.edu:asdf/transform/rotate2d-1.3.0",
- "tag:stsci.edu:asdf/transform/rotate2d-1.4.0"
+ "tag:stsci.edu:asdf/transform/rotate2d-1.4.0",
+ "tag:stsci.edu:asdf/transform/rotate2d-1.5.0"
);
public Rotation2DConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/selector/LabelMapperDictConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/selector/LabelMapperDictConverter.java
index 0df962f..b95862a 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/selector/LabelMapperDictConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/selector/LabelMapperDictConverter.java
@@ -13,7 +13,10 @@
public class LabelMapperDictConverter extends ConverterBase {
private static final Set TAGS = Set.of(
- "tag:stsci.edu:gwcs/label_mapper-1.0.0"
+ "tag:stsci.edu:gwcs/label_mapper-1.0.0",
+ "tag:stsci.edu:gwcs/label_mapper-1.1.0",
+ "tag:stsci.edu:gwcs/label_mapper-1.2.0",
+ "tag:stsci.edu:gwcs/label_mapper-1.3.0"
);
public LabelMapperDictConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/selector/RegionsSelectorConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/selector/RegionsSelectorConverter.java
index c1e92f9..42f047a 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/selector/RegionsSelectorConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/selector/RegionsSelectorConverter.java
@@ -13,7 +13,10 @@
public class RegionsSelectorConverter extends ConverterBase {
private static final Set TAGS = Set.of(
- "tag:stsci.edu:gwcs/regions_selector-1.0.0"
+ "tag:stsci.edu:gwcs/regions_selector-1.0.0",
+ "tag:stsci.edu:gwcs/regions_selector-1.1.0",
+ "tag:stsci.edu:gwcs/regions_selector-1.2.0",
+ "tag:stsci.edu:gwcs/regions_selector-1.3.0"
);
public RegionsSelectorConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/GratingEquationConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/GratingEquationConverter.java
index a70aa9e..056d9eb 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/GratingEquationConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/GratingEquationConverter.java
@@ -11,7 +11,10 @@
public class GratingEquationConverter extends ConverterBase {
private static final Set TAGS = Set.of(
- "tag:stsci.edu:gwcs/grating_equation-1.0.0"
+ "tag:stsci.edu:gwcs/grating_equation-1.0.0",
+ "tag:stsci.edu:gwcs/grating_equation-1.1.0",
+ "tag:stsci.edu:gwcs/grating_equation-1.2.0",
+ "tag:stsci.edu:gwcs/grating_equation-1.3.0"
);
public GratingEquationConverter(final GwcsAsdfSupport support) {
@@ -21,7 +24,7 @@ public GratingEquationConverter(final GwcsAsdfSupport support) {
@Override
public Transform fromAsdfNode(final AsdfNode node) {
final double grooveDensity = node.getDouble("groove_density");
- final int order = node.getInt("order");
+ final int order = (int) node.getDouble("order");
final String output = node.getString("output");
final Transform transform;
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierGlassConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierGlassConverter.java
index e5bd632..914e023 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierGlassConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierGlassConverter.java
@@ -11,7 +11,10 @@
public class SellmeierGlassConverter extends ConverterBase {
private static final Set TAGS = Set.of(
- "tag:stsci.edu:gwcs/sellmeier_glass-1.0.0"
+ "tag:stsci.edu:gwcs/sellmeier_glass-1.0.0",
+ "tag:stsci.edu:gwcs/sellmeier_glass-1.1.0",
+ "tag:stsci.edu:gwcs/sellmeier_glass-1.2.0",
+ "tag:stsci.edu:gwcs/sellmeier_glass-1.3.0"
);
public SellmeierGlassConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierZemaxConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierZemaxConverter.java
index f0ccacb..a0d6cbc 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierZemaxConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierZemaxConverter.java
@@ -11,7 +11,10 @@
public class SellmeierZemaxConverter extends ConverterBase {
private static final Set TAGS = Set.of(
- "tag:stsci.edu:gwcs/sellmeier_zemax-1.0.0"
+ "tag:stsci.edu:gwcs/sellmeier_zemax-1.0.0",
+ "tag:stsci.edu:gwcs/sellmeier_zemax-1.1.0",
+ "tag:stsci.edu:gwcs/sellmeier_zemax-1.2.0",
+ "tag:stsci.edu:gwcs/sellmeier_zemax-1.3.0"
);
public SellmeierZemaxConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/Snell3DConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/Snell3DConverter.java
index f756c79..dc495e7 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/Snell3DConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/Snell3DConverter.java
@@ -10,7 +10,10 @@
public class Snell3DConverter extends ConverterBase {
private static final Set TAGS = Set.of(
- "tag:stsci.edu:gwcs/snell3d-1.0.0"
+ "tag:stsci.edu:gwcs/snell3d-1.0.0",
+ "tag:stsci.edu:gwcs/snell3d-1.1.0",
+ "tag:stsci.edu:gwcs/snell3d-1.2.0",
+ "tag:stsci.edu:gwcs/snell3d-1.3.0"
);
public Snell3DConverter(final GwcsAsdfSupport support) {
diff --git a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/tabular/Tabular1DConverter.java b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/tabular/Tabular1DConverter.java
index 0a2e3a2..3ae953e 100644
--- a/src/main/java/edu/stsci/gwcs/asdf/converter/transform/tabular/Tabular1DConverter.java
+++ b/src/main/java/edu/stsci/gwcs/asdf/converter/transform/tabular/Tabular1DConverter.java
@@ -14,7 +14,9 @@
public class Tabular1DConverter extends ConverterBase {
private static final Set TAGS = Set.of(
- "tag:stsci.edu:asdf/transform/tabular-1.2.0"
+ "tag:stsci.edu:asdf/transform/tabular-1.2.0",
+ "tag:stsci.edu:asdf/transform/tabular-1.3.0",
+ "tag:stsci.edu:asdf/transform/tabular-1.4.0"
);
public Tabular1DConverter(final GwcsAsdfSupport support) {
diff --git a/src/test/java/edu/stsci/gwcs/asdf/GwcsAsdfSupportTest.java b/src/test/java/edu/stsci/gwcs/asdf/GwcsAsdfSupportTest.java
index c139274..8d48ba8 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/GwcsAsdfSupportTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/GwcsAsdfSupportTest.java
@@ -212,8 +212,11 @@ void deserializeWcsWithPixelShape() {
when(wcsNode.getTag()).thenReturn("tag:stsci.edu:gwcs/wcs-1.4.0");
when(wcsNode.getString("name")).thenReturn("test_wcs");
when(wcsNode.get("steps")).thenReturn(stepsNode);
- when(wcsNode.getOptional("pixel_shape")).thenReturn(Optional.of(mock(AsdfNode.class)));
- when(wcsNode.getList("pixel_shape", Integer.class)).thenReturn(List.of(4088, 4088));
+ final AsdfNode pixelShapeNode = mock(AsdfNode.class);
+ when(pixelShapeNode.isNdArray()).thenReturn(false);
+ when(pixelShapeNode.asList(Integer.class)).thenReturn(List.of(4088, 4088));
+ when(wcsNode.getOptional("pixel_shape")).thenReturn(Optional.of(pixelShapeNode));
+ when(wcsNode.get("pixel_shape")).thenReturn(pixelShapeNode);
final Wcs wcs = support.deserializeWcs(wcsNode);
@@ -270,7 +273,10 @@ private AsdfNode mockFrame2DNode(final String name, final String[] axisNames) {
when(node.getTag()).thenReturn("tag:stsci.edu:gwcs/frame2d-1.0.0");
when(node.getString("name")).thenReturn(name);
when(node.getList("axes_names", String.class)).thenReturn(List.of(axisNames));
- when(node.getList("axes_order", Integer.class)).thenReturn(List.of(0, 1));
+ final AsdfNode axisOrderNode = mock(AsdfNode.class);
+ when(axisOrderNode.isNdArray()).thenReturn(false);
+ when(axisOrderNode.asList(Integer.class)).thenReturn(List.of(0, 1));
+ when(node.get("axes_order")).thenReturn(axisOrderNode);
when(node.getList("axis_physical_types", String.class)).thenReturn(List.of("custom:x", "custom:y"));
when(node.getList("unit", String.class)).thenReturn(List.of("pixel", "pixel"));
return node;
diff --git a/src/test/java/edu/stsci/gwcs/asdf/converter/AsdfNodeUtilsTest.java b/src/test/java/edu/stsci/gwcs/asdf/converter/AsdfNodeUtilsTest.java
index b933b7b..855b4e9 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/converter/AsdfNodeUtilsTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/converter/AsdfNodeUtilsTest.java
@@ -31,7 +31,10 @@ void readStringArrayPreservesOrder() {
@Test
void readIntArrayReturnsEmptyArrayForEmptyList() {
final AsdfNode node = mock(AsdfNode.class);
- when(node.getList("order", Integer.class)).thenReturn(Collections.emptyList());
+ final AsdfNode child = mock(AsdfNode.class);
+ when(node.get("order")).thenReturn(child);
+ when(child.isNdArray()).thenReturn(false);
+ when(child.asList(Integer.class)).thenReturn(Collections.emptyList());
final int[] result = AsdfNodeUtils.readIntArray(node, "order");
assertEquals(0, result.length);
@@ -40,7 +43,10 @@ void readIntArrayReturnsEmptyArrayForEmptyList() {
@Test
void readIntArrayPreservesOrder() {
final AsdfNode node = mock(AsdfNode.class);
- when(node.getList("order", Integer.class)).thenReturn(List.of(2, 0, 1));
+ final AsdfNode child = mock(AsdfNode.class);
+ when(node.get("order")).thenReturn(child);
+ when(child.isNdArray()).thenReturn(false);
+ when(child.asList(Integer.class)).thenReturn(List.of(2, 0, 1));
final int[] result = AsdfNodeUtils.readIntArray(node, "order");
assertArrayEquals(new int[]{2, 0, 1}, result);
diff --git a/src/test/java/edu/stsci/gwcs/asdf/converter/frame/Frame2DConverterTest.java b/src/test/java/edu/stsci/gwcs/asdf/converter/frame/Frame2DConverterTest.java
index a710d98..d30de2e 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/converter/frame/Frame2DConverterTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/converter/frame/Frame2DConverterTest.java
@@ -62,7 +62,10 @@ public static AsdfNode mockFrame2DNode(final String tag,
when(node.getTag()).thenReturn(tag);
when(node.getString("name")).thenReturn(name);
when(node.getList("axes_names", String.class)).thenReturn(axisNames);
- when(node.getList("axes_order", Integer.class)).thenReturn(axisOrder);
+ final AsdfNode axisOrderNode = mock(AsdfNode.class);
+ when(axisOrderNode.isNdArray()).thenReturn(false);
+ when(axisOrderNode.asList(Integer.class)).thenReturn(axisOrder);
+ when(node.get("axes_order")).thenReturn(axisOrderNode);
when(node.getList("axis_physical_types", String.class)).thenReturn(axisPhysicalTypes);
when(node.getList("unit", String.class)).thenReturn(units);
return node;
diff --git a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/RemapAxesConverterTest.java b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/RemapAxesConverterTest.java
index 82265a3..52a6f36 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/RemapAxesConverterTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/RemapAxesConverterTest.java
@@ -13,11 +13,21 @@
import static org.mockito.Mockito.*;
class RemapAxesConverterTest {
+
+ private static AsdfNode mockIntListNode(final List values) {
+ final AsdfNode child = mock(AsdfNode.class);
+ when(child.isNdArray()).thenReturn(false);
+ when(child.asList(Integer.class)).thenReturn(values);
+ return child;
+ }
+
@Test
void deserializeRemapAxesWithNInputs() {
+ final AsdfNode mappingNode = mockIntListNode(List.of(1, 0, 1));
+
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:asdf/transform/remap_axes-1.3.0");
- when(node.getList("mapping", Integer.class)).thenReturn(List.of(1, 0, 1));
+ when(node.get("mapping")).thenReturn(mappingNode);
final AsdfNode nInputsNode = mock(AsdfNode.class);
when(nInputsNode.asInt()).thenReturn(3);
@@ -37,9 +47,11 @@ void deserializeRemapAxesWithNInputs() {
@Test
void deserializeRemapAxesWithoutNInputs() {
+ final AsdfNode mappingNode = mockIntListNode(List.of(1, 0));
+
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:asdf/transform/remap_axes-1.4.0");
- when(node.getList("mapping", Integer.class)).thenReturn(List.of(1, 0));
+ when(node.get("mapping")).thenReturn(mappingNode);
when(node.getOptional("n_inputs")).thenReturn(Optional.empty());
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
diff --git a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/compound/CompoundConverterTest.java b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/compound/CompoundConverterTest.java
index 7dfffa4..8c0e909 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/compound/CompoundConverterTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/compound/CompoundConverterTest.java
@@ -194,8 +194,14 @@ void deserializeFixInputs() {
when(identityNode.getOptional("bounding_box")).thenReturn(Optional.empty());
final AsdfNode mappingNode = mock(AsdfNode.class);
- when(mappingNode.getList("keys", Integer.class)).thenReturn(List.of(1));
- when(mappingNode.getList("values", Double.class)).thenReturn(List.of(99.0));
+ final AsdfNode keysNode = mock(AsdfNode.class);
+ when(keysNode.isNdArray()).thenReturn(false);
+ when(keysNode.asList(Integer.class)).thenReturn(List.of(1));
+ when(mappingNode.get("keys")).thenReturn(keysNode);
+ final AsdfNode valuesNode = mock(AsdfNode.class);
+ when(valuesNode.isNdArray()).thenReturn(false);
+ when(valuesNode.asList(Double.class)).thenReturn(List.of(99.0));
+ when(mappingNode.get("values")).thenReturn(valuesNode);
final AsdfNode forwardNode = mock(AsdfNode.class);
when(forwardNode.get(0L)).thenReturn(identityNode);
@@ -232,8 +238,14 @@ void deserializeFixInputsMultipleFixedInputs() {
when(identityNode.getOptional("bounding_box")).thenReturn(Optional.empty());
final AsdfNode mappingNode = mock(AsdfNode.class);
- when(mappingNode.getList("keys", Integer.class)).thenReturn(List.of(0, 2));
- when(mappingNode.getList("values", Double.class)).thenReturn(List.of(5.0, 15.0));
+ final AsdfNode keysNode = mock(AsdfNode.class);
+ when(keysNode.isNdArray()).thenReturn(false);
+ when(keysNode.asList(Integer.class)).thenReturn(List.of(0, 2));
+ when(mappingNode.get("keys")).thenReturn(keysNode);
+ final AsdfNode valuesNode = mock(AsdfNode.class);
+ when(valuesNode.isNdArray()).thenReturn(false);
+ when(valuesNode.asList(Double.class)).thenReturn(List.of(5.0, 15.0));
+ when(mappingNode.get("values")).thenReturn(valuesNode);
final AsdfNode forwardNode = mock(AsdfNode.class);
when(forwardNode.get(0L)).thenReturn(identityNode);
@@ -528,8 +540,14 @@ void deserializeFixInputsKeyValueSizeMismatchThrows() {
when(identityNode.getOptional("bounding_box")).thenReturn(Optional.empty());
final AsdfNode mappingNode = mock(AsdfNode.class);
- when(mappingNode.getList("keys", Integer.class)).thenReturn(List.of(0, 1));
- when(mappingNode.getList("values", Double.class)).thenReturn(List.of(99.0));
+ final AsdfNode keysNode = mock(AsdfNode.class);
+ when(keysNode.isNdArray()).thenReturn(false);
+ when(keysNode.asList(Integer.class)).thenReturn(List.of(0, 1));
+ when(mappingNode.get("keys")).thenReturn(keysNode);
+ final AsdfNode valuesNode = mock(AsdfNode.class);
+ when(valuesNode.isNdArray()).thenReturn(false);
+ when(valuesNode.asList(Double.class)).thenReturn(List.of(99.0));
+ when(mappingNode.get("values")).thenReturn(valuesNode);
final AsdfNode forwardNode = mock(AsdfNode.class);
when(forwardNode.get(0L)).thenReturn(identityNode);
diff --git a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/projection/ProjectionConverterTest.java b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/projection/ProjectionConverterTest.java
index 5917719..b20d57f 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/projection/ProjectionConverterTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/projection/ProjectionConverterTest.java
@@ -342,7 +342,7 @@ void deserializeHammerAitoff() {
@Test
void deserializeMollweide() {
- final AsdfNode node = projectionNode("mollweide-1.3.0", "pix2sky");
+ final AsdfNode node = projectionNode("molleweide-1.3.0", "pix2sky");
assertInstanceOf(Mollweide.class, support.deserializeTransform(node));
}
diff --git a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/rotation/RotateSequence3DConverterTest.java b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/rotation/RotateSequence3DConverterTest.java
index d13a6ae..30db738 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/rotation/RotateSequence3DConverterTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/rotation/RotateSequence3DConverterTest.java
@@ -15,10 +15,14 @@
class RotateSequence3DConverterTest {
@Test
void deserializeRotateSequence3D() {
+ final AsdfNode anglesNode = mock(AsdfNode.class);
+ when(anglesNode.isNdArray()).thenReturn(false);
+ when(anglesNode.asList(Double.class)).thenReturn(List.of(90.0, 0.0, 0.0));
+
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:asdf/transform/rotate_sequence_3d-1.1.0");
when(node.getString("rotation_type")).thenReturn("cartesian");
- when(node.getList("angles", Double.class)).thenReturn(List.of(90.0, 0.0, 0.0));
+ when(node.get("angles")).thenReturn(anglesNode);
when(node.getString("axes_order")).thenReturn("zyx");
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
@@ -41,10 +45,14 @@ void deserializeRotateSequence3D() {
@Test
void deserializeIdentityRotation() {
+ final AsdfNode anglesNode = mock(AsdfNode.class);
+ when(anglesNode.isNdArray()).thenReturn(false);
+ when(anglesNode.asList(Double.class)).thenReturn(List.of(0.0, 0.0, 0.0));
+
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:asdf/transform/rotate_sequence_3d-1.1.0");
when(node.getString("rotation_type")).thenReturn("cartesian");
- when(node.getList("angles", Double.class)).thenReturn(List.of(0.0, 0.0, 0.0));
+ when(node.get("angles")).thenReturn(anglesNode);
when(node.getString("axes_order")).thenReturn("xyz");
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
diff --git a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/GratingEquationConverterTest.java b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/GratingEquationConverterTest.java
index aba76e6..0299909 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/GratingEquationConverterTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/GratingEquationConverterTest.java
@@ -18,7 +18,7 @@ void deserializeAnglesFromGratingEquation3D() {
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:gwcs/grating_equation-1.0.0");
when(node.getDouble("groove_density")).thenReturn(100.0);
- when(node.getInt("order")).thenReturn(1);
+ when(node.getDouble("order")).thenReturn(1.0);
when(node.getString("output")).thenReturn("angle");
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
@@ -37,7 +37,7 @@ void deserializeWavelengthFromGratingEquation() {
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:gwcs/grating_equation-1.0.0");
when(node.getDouble("groove_density")).thenReturn(100.0);
- when(node.getInt("order")).thenReturn(1);
+ when(node.getDouble("order")).thenReturn(1.0);
when(node.getString("output")).thenReturn("wavelength");
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
@@ -56,7 +56,7 @@ void anglesFromGratingEquationEvaluatesCorrectly() {
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:gwcs/grating_equation-1.0.0");
when(node.getDouble("groove_density")).thenReturn(100.0);
- when(node.getInt("order")).thenReturn(1);
+ when(node.getDouble("order")).thenReturn(1.0);
when(node.getString("output")).thenReturn("angle");
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
@@ -77,7 +77,7 @@ void unknownOutputThrows() {
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:gwcs/grating_equation-1.0.0");
when(node.getDouble("groove_density")).thenReturn(100.0);
- when(node.getInt("order")).thenReturn(1);
+ when(node.getDouble("order")).thenReturn(1.0);
when(node.getString("output")).thenReturn("invalid");
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
diff --git a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierGlassConverterTest.java b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierGlassConverterTest.java
index 6053c35..840b08f 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierGlassConverterTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierGlassConverterTest.java
@@ -13,12 +13,23 @@
import static org.mockito.Mockito.*;
class SellmeierGlassConverterTest {
+
+ private static AsdfNode mockDoubleListNode(final List values) {
+ final AsdfNode child = mock(AsdfNode.class);
+ when(child.isNdArray()).thenReturn(false);
+ when(child.asList(Double.class)).thenReturn(values);
+ return child;
+ }
+
@Test
void deserializeSellmeierGlass() {
+ final AsdfNode bCoefNode = mockDoubleListNode(List.of(0.6961663, 0.4079426, 0.8974794));
+ final AsdfNode cCoefNode = mockDoubleListNode(List.of(0.0046914826, 0.013512063, 97.934003));
+
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:gwcs/sellmeier_glass-1.0.0");
- when(node.getList("B_coef", Double.class)).thenReturn(List.of(0.6961663, 0.4079426, 0.8974794));
- when(node.getList("C_coef", Double.class)).thenReturn(List.of(0.0046914826, 0.013512063, 97.934003));
+ when(node.get("B_coef")).thenReturn(bCoefNode);
+ when(node.get("C_coef")).thenReturn(cCoefNode);
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
when(node.getOptional("outputs")).thenReturn(Optional.empty());
@@ -33,10 +44,13 @@ void deserializeSellmeierGlass() {
@Test
void sellmeierGlassEvaluatesCorrectly() {
+ final AsdfNode bCoefNode = mockDoubleListNode(List.of(0.6961663, 0.4079426, 0.8974794));
+ final AsdfNode cCoefNode = mockDoubleListNode(List.of(0.0046914826, 0.013512063, 97.934003));
+
final AsdfNode node = mock(AsdfNode.class);
when(node.getTag()).thenReturn("tag:stsci.edu:gwcs/sellmeier_glass-1.0.0");
- when(node.getList("B_coef", Double.class)).thenReturn(List.of(0.6961663, 0.4079426, 0.8974794));
- when(node.getList("C_coef", Double.class)).thenReturn(List.of(0.0046914826, 0.013512063, 97.934003));
+ when(node.get("B_coef")).thenReturn(bCoefNode);
+ when(node.get("C_coef")).thenReturn(cCoefNode);
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
when(node.getOptional("outputs")).thenReturn(Optional.empty());
diff --git a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierZemaxConverterTest.java b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierZemaxConverterTest.java
index a98bc8f..498cd34 100644
--- a/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierZemaxConverterTest.java
+++ b/src/test/java/edu/stsci/gwcs/asdf/converter/transform/spectroscopy/SellmeierZemaxConverterTest.java
@@ -13,21 +13,39 @@
import static org.mockito.Mockito.*;
class SellmeierZemaxConverterTest {
- @Test
- void deserializeSellmeierZemax() {
+
+ private static AsdfNode mockDoubleListNode(final List values) {
+ final AsdfNode child = mock(AsdfNode.class);
+ when(child.isNdArray()).thenReturn(false);
+ when(child.asList(Double.class)).thenReturn(values);
+ return child;
+ }
+
+ private AsdfNode mockSellmeierZemaxNode(final String tag, final double temperature) {
+ final AsdfNode bCoefNode = mockDoubleListNode(List.of(0.6961663, 0.4079426, 0.8974794));
+ final AsdfNode cCoefNode = mockDoubleListNode(List.of(0.0046914826, 0.013512063, 97.934003));
+ final AsdfNode dCoefNode = mockDoubleListNode(List.of(1.0e-5, 2.0e-5, 3.0e-5));
+ final AsdfNode eCoefNode = mockDoubleListNode(List.of(4.0e-5, 5.0e-5, 0.15));
+
final AsdfNode node = mock(AsdfNode.class);
- when(node.getTag()).thenReturn("tag:stsci.edu:gwcs/sellmeier_zemax-1.0.0");
- when(node.getDouble("temperature")).thenReturn(296.15);
+ when(node.getTag()).thenReturn(tag);
+ when(node.getDouble("temperature")).thenReturn(temperature);
when(node.getDouble("ref_temperature")).thenReturn(293.15);
when(node.getDouble("ref_pressure")).thenReturn(1.0);
when(node.getDouble("pressure")).thenReturn(1.0);
- when(node.getList("B_coef", Double.class)).thenReturn(List.of(0.6961663, 0.4079426, 0.8974794));
- when(node.getList("C_coef", Double.class)).thenReturn(List.of(0.0046914826, 0.013512063, 97.934003));
- when(node.getList("D_coef", Double.class)).thenReturn(List.of(1.0e-5, 2.0e-5, 3.0e-5));
- when(node.getList("E_coef", Double.class)).thenReturn(List.of(4.0e-5, 5.0e-5, 0.15));
+ when(node.get("B_coef")).thenReturn(bCoefNode);
+ when(node.get("C_coef")).thenReturn(cCoefNode);
+ when(node.get("D_coef")).thenReturn(dCoefNode);
+ when(node.get("E_coef")).thenReturn(eCoefNode);
when(node.getOptional("name")).thenReturn(Optional.empty());
when(node.getOptional("inputs")).thenReturn(Optional.empty());
when(node.getOptional("outputs")).thenReturn(Optional.empty());
+ return node;
+ }
+
+ @Test
+ void deserializeSellmeierZemax() {
+ final AsdfNode node = mockSellmeierZemaxNode("tag:stsci.edu:gwcs/sellmeier_zemax-1.0.0", 296.15);
final GwcsAsdfSupport support = new GwcsAsdfSupport();
final Transform transform = support.deserializeTransform(node);
@@ -39,20 +57,7 @@ void deserializeSellmeierZemax() {
final double[] result = transform.evaluate(0.5893);
assertTrue(result[0] > 1.0, "Refractive index should be > 1");
- final AsdfNode refNode = mock(AsdfNode.class);
- when(refNode.getTag()).thenReturn("tag:stsci.edu:gwcs/sellmeier_zemax-1.0.0");
- when(refNode.getDouble("temperature")).thenReturn(293.15);
- when(refNode.getDouble("ref_temperature")).thenReturn(293.15);
- when(refNode.getDouble("ref_pressure")).thenReturn(1.0);
- when(refNode.getDouble("pressure")).thenReturn(1.0);
- when(refNode.getList("B_coef", Double.class)).thenReturn(List.of(0.6961663, 0.4079426, 0.8974794));
- when(refNode.getList("C_coef", Double.class)).thenReturn(List.of(0.0046914826, 0.013512063, 97.934003));
- when(refNode.getList("D_coef", Double.class)).thenReturn(List.of(1.0e-5, 2.0e-5, 3.0e-5));
- when(refNode.getList("E_coef", Double.class)).thenReturn(List.of(4.0e-5, 5.0e-5, 0.15));
- when(refNode.getOptional("name")).thenReturn(Optional.empty());
- when(refNode.getOptional("inputs")).thenReturn(Optional.empty());
- when(refNode.getOptional("outputs")).thenReturn(Optional.empty());
-
+ final AsdfNode refNode = mockSellmeierZemaxNode("tag:stsci.edu:gwcs/sellmeier_zemax-1.0.0", 293.15);
final Transform refTransform = support.deserializeTransform(refNode);
final double[] refResult = refTransform.evaluate(0.5893);
diff --git a/src/test/java/edu/stsci/gwcs/testing/GwcsReferenceFileType.java b/src/test/java/edu/stsci/gwcs/testing/GwcsReferenceFileType.java
new file mode 100644
index 0000000..384d8c3
--- /dev/null
+++ b/src/test/java/edu/stsci/gwcs/testing/GwcsReferenceFileType.java
@@ -0,0 +1,32 @@
+package edu.stsci.gwcs.testing;
+
+import java.io.InputStream;
+
+public enum GwcsReferenceFileType implements ReferenceFile {
+ FUNCTIONAL,
+ POLYNOMIAL,
+ TABULAR,
+ COMPOUND,
+ ROTATION,
+ GEOMETRY,
+ PROJECTION,
+ SPECTROSCOPY,
+ FITS_WCS,
+ WCS_IMAGING,
+ WCS_CAL,
+ WCS_SPECTROSCOPY,
+ ROMAN_WCS,
+ ;
+
+ @Override
+ public String getName() {
+ return name();
+ }
+
+ @Override
+ public InputStream openScript() {
+ return GwcsReferenceFileType.class.getResourceAsStream(
+ String.format("/reference-file-scripts/%s.py", name().toLowerCase())
+ );
+ }
+}
diff --git a/src/test/java/edu/stsci/gwcs/testing/ReferenceFile.java b/src/test/java/edu/stsci/gwcs/testing/ReferenceFile.java
new file mode 100644
index 0000000..5bc9d4a
--- /dev/null
+++ b/src/test/java/edu/stsci/gwcs/testing/ReferenceFile.java
@@ -0,0 +1,9 @@
+package edu.stsci.gwcs.testing;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public interface ReferenceFile {
+ String getName();
+ InputStream openScript() throws IOException;
+}
diff --git a/src/test/java/edu/stsci/gwcs/testing/ReferenceFileUtils.java b/src/test/java/edu/stsci/gwcs/testing/ReferenceFileUtils.java
new file mode 100644
index 0000000..900f7b9
--- /dev/null
+++ b/src/test/java/edu/stsci/gwcs/testing/ReferenceFileUtils.java
@@ -0,0 +1,95 @@
+package edu.stsci.gwcs.testing;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+public class ReferenceFileUtils {
+ private static final String PYTHON_PATH = System.getenv("GWCS_JAVA_TESTS_PYTHON_PATH");
+ private static final Path GENERATOR_SCRIPT_PATH = extractGeneratorScript();
+
+ private static final Map CACHE = new HashMap<>();
+
+ private static Path extractGeneratorScript() {
+ try {
+ final Path path = Files.createTempFile("reference_file_generator_", ".py");
+ path.toFile().deleteOnExit();
+
+ try (
+ final InputStream input = Optional.ofNullable(
+ ReferenceFileUtils.class.getResourceAsStream("/testing/reference_file_generator.py"))
+ .orElseThrow(() -> new RuntimeException("Missing testing/reference_file_generator.py"));
+ final OutputStream output = Files.newOutputStream(path, StandardOpenOption.CREATE)
+ ) {
+ input.transferTo(output);
+ }
+
+ return path;
+ } catch (final IOException e) {
+ throw new RuntimeException("Failed to extract generator script", e);
+ }
+ }
+
+ public static Path getPath(final ReferenceFile referenceFile) {
+ final String key = referenceFile.getName();
+
+ if (!CACHE.containsKey(key)) {
+ CACHE.put(key, generateTestFile(referenceFile));
+ }
+
+ return CACHE.get(key);
+ }
+
+ private static Path generateTestFile(final ReferenceFile referenceFile) {
+ assumeTrue(
+ Optional.ofNullable(PYTHON_PATH)
+ .filter(p -> !p.isEmpty())
+ .map(p -> Files.exists(Paths.get(p)))
+ .orElse(false),
+ "GWCS_JAVA_TESTS_PYTHON_PATH missing or unset"
+ );
+
+ try {
+ final InputStream scriptInput = referenceFile.openScript();
+ assumeTrue(scriptInput != null,
+ "Reference script not found for " + referenceFile.getName());
+
+ final Path outputPath = Files.createTempFile(referenceFile.getName() + "-", ".asdf");
+ outputPath.toFile().deleteOnExit();
+
+ final Process process = new ProcessBuilder(PYTHON_PATH, GENERATOR_SCRIPT_PATH.toString()).start();
+
+ try (scriptInput; final OutputStream processInput = process.getOutputStream()) {
+ scriptInput.transferTo(processInput);
+ }
+
+ try (
+ final InputStream processOutput = process.getInputStream();
+ final OutputStream fileOutput = Files.newOutputStream(outputPath, StandardOpenOption.CREATE)
+ ) {
+ processOutput.transferTo(fileOutput);
+ }
+
+ final int exitCode = process.waitFor();
+ if (exitCode != 0) {
+ final String stderr = new String(process.getErrorStream().readAllBytes());
+ throw new RuntimeException(
+ "Python generator failed for " + referenceFile.getName()
+ + " (exit code " + exitCode + "): " + stderr);
+ }
+
+ return outputPath;
+ } catch (final IOException | InterruptedException e) {
+ throw new RuntimeException("Failed to generate reference file for " + referenceFile.getName(), e);
+ }
+ }
+}
diff --git a/src/test/java/edu/stsci/gwcs/testing/TransformReferenceTest.java b/src/test/java/edu/stsci/gwcs/testing/TransformReferenceTest.java
new file mode 100644
index 0000000..2691903
--- /dev/null
+++ b/src/test/java/edu/stsci/gwcs/testing/TransformReferenceTest.java
@@ -0,0 +1,168 @@
+package edu.stsci.gwcs.testing;
+
+import edu.stsci.gwcs.Wcs;
+import edu.stsci.gwcs.asdf.GwcsAsdfSupport;
+import edu.stsci.gwcs.transform.Transform;
+import org.asdfformat.asdf.Asdf;
+import org.asdfformat.asdf.AsdfFile;
+import org.asdfformat.asdf.node.AsdfNode;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+@Tag("reference-tests")
+public class TransformReferenceTest {
+
+ @ParameterizedTest(name = "{0}")
+ @EnumSource(GwcsReferenceFileType.class)
+ void referenceTest(final GwcsReferenceFileType referenceFileType) throws IOException {
+ final Path path = ReferenceFileUtils.getPath(referenceFileType);
+
+ try (final AsdfFile asdfFile = Asdf.open(path)) {
+ final AsdfNode testCases = asdfFile.getTree().get("test_cases");
+
+ for (int i = 0; i < testCases.size(); i++) {
+ final AsdfNode testCase = testCases.get((long) i);
+ final String testCaseName = testCase.getString("name");
+ final String label = referenceFileType.getName() + "/" + testCaseName;
+
+ final double tolerance = testCase.getOptional("tolerance")
+ .map(AsdfNode::asDouble)
+ .orElse(TestingUtils.DOUBLE_TOLERANCE);
+
+ if (testCase.getOptional("fixture_path").isPresent()) {
+ verifyFixtureWcs(testCase, label, tolerance);
+ } else if (testCase.getOptional("wcs").isPresent()) {
+ verifyWcs(testCase, label, tolerance);
+ } else {
+ verifyTransform(testCase, label, tolerance);
+ }
+ }
+ }
+ }
+
+ private void verifyTransform(final AsdfNode testCase, final String label,
+ final double tolerance) {
+ final Transform transform = GwcsAsdfSupport.instance().deserializeTransform(
+ testCase.get("transform"));
+
+ verifyForward(transform, testCase, label, tolerance);
+
+ if (testCase.getOptional("has_inverse").map(AsdfNode::asBoolean).orElse(false)) {
+ final Transform inverse = transform.getInverse();
+ verifyInverse(inverse, testCase, label, tolerance);
+ }
+ }
+
+ private void verifyWcs(final AsdfNode testCase, final String label,
+ final double tolerance) {
+ final Wcs wcs = GwcsAsdfSupport.instance().deserializeWcs(testCase.get("wcs"));
+
+ verifyForwardWcs(wcs, testCase, label, tolerance);
+
+ if (testCase.getOptional("has_inverse").map(AsdfNode::asBoolean).orElse(false)) {
+ verifyInverseWcs(wcs, testCase, label, tolerance);
+ }
+ }
+
+ private void verifyFixtureWcs(final AsdfNode testCase, final String label,
+ final double tolerance) throws IOException {
+ final String fixturePath = testCase.getString("fixture_path");
+ final Path fixtureFile = Path.of("src/test/resources/" + fixturePath);
+
+ final Wcs wcs;
+ try (final AsdfFile fixtureAsdf = Asdf.open(fixtureFile)) {
+ final AsdfNode wcsNode = fixtureAsdf.getTree().get("roman").get("meta").get("wcs");
+ wcs = GwcsAsdfSupport.instance().deserializeWcs(wcsNode);
+ }
+
+ verifyForwardWcs(wcs, testCase, label, tolerance);
+
+ if (testCase.getOptional("has_inverse").map(AsdfNode::asBoolean).orElse(false)) {
+ verifyInverseWcs(wcs, testCase, label, tolerance);
+ }
+ }
+
+ private void verifyForward(final Transform transform, final AsdfNode testCase,
+ final String label, final double tolerance) {
+ final double[][] inputs = readNdArray2D(testCase.get("forward_inputs"));
+ final double[][] expectedOutputs = readNdArray2D(testCase.get("forward_outputs"));
+
+ for (int i = 0; i < inputs.length; i++) {
+ final double[] actual = transform.evaluate(inputs[i]);
+ assertArrayEquals(
+ expectedOutputs[i], actual, tolerance,
+ String.format("%s forward[%d]: input=%s", label, i, formatArray(inputs[i]))
+ );
+ }
+ }
+
+ private void verifyInverse(final Transform inverse, final AsdfNode testCase,
+ final String label, final double tolerance) {
+ final double[][] inputs = readNdArray2D(testCase.get("inverse_inputs"));
+ final double[][] expectedOutputs = readNdArray2D(testCase.get("inverse_outputs"));
+
+ for (int i = 0; i < inputs.length; i++) {
+ final double[] actual = inverse.evaluate(inputs[i]);
+ assertArrayEquals(
+ expectedOutputs[i], actual, tolerance,
+ String.format("%s inverse[%d]: input=%s", label, i, formatArray(inputs[i]))
+ );
+ }
+ }
+
+ private void verifyForwardWcs(final Wcs wcs, final AsdfNode testCase,
+ final String label, final double tolerance) {
+ final double[][] inputs = readNdArray2D(testCase.get("forward_inputs"));
+ final double[][] expectedOutputs = readNdArray2D(testCase.get("forward_outputs"));
+
+ for (int i = 0; i < inputs.length; i++) {
+ final double[] actual = wcs.evaluate(inputs[i]);
+ assertArrayEquals(
+ expectedOutputs[i], actual, tolerance,
+ String.format("%s forward[%d]: input=%s", label, i, formatArray(inputs[i]))
+ );
+ }
+ }
+
+ private void verifyInverseWcs(final Wcs wcs, final AsdfNode testCase,
+ final String label, final double tolerance) {
+ final double[][] inputs = readNdArray2D(testCase.get("inverse_inputs"));
+ final double[][] expectedOutputs = readNdArray2D(testCase.get("inverse_outputs"));
+
+ for (int i = 0; i < inputs.length; i++) {
+ final double[] actual = wcs.evaluateInverse(inputs[i]);
+ assertArrayEquals(
+ expectedOutputs[i], actual, tolerance,
+ String.format("%s inverse[%d]: input=%s", label, i, formatArray(inputs[i]))
+ );
+ }
+ }
+
+ private static double[][] readNdArray2D(final AsdfNode node) {
+ final var ndArray = node.asNdArray().asDoubleNdArray();
+ final int rows = ndArray.getShape().get(0);
+ final int cols = ndArray.getShape().get(1);
+ final double[][] result = new double[rows][cols];
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < cols; c++) {
+ result[r][c] = ndArray.get(r, c);
+ }
+ }
+ return result;
+ }
+
+ private static String formatArray(final double[] values) {
+ final StringBuilder sb = new StringBuilder("[");
+ for (int i = 0; i < values.length; i++) {
+ if (i > 0) sb.append(", ");
+ sb.append(values[i]);
+ }
+ return sb.append("]").toString();
+ }
+}
diff --git a/src/test/resources/reference-file-scripts/compound.py b/src/test/resources/reference-file-scripts/compound.py
new file mode 100644
index 0000000..a2b9b54
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/compound.py
@@ -0,0 +1,99 @@
+compose = models.Shift(2.0) | models.Scale(3.0)
+concat = models.Shift(1.0) & models.Shift(2.0)
+add = models.Shift(1.0) + models.Scale(2.0)
+subtract = models.Shift(1.0) - models.Scale(2.0)
+multiply = models.Shift(1.0) * models.Scale(2.0)
+divide = models.Shift(1.0) / models.Scale(2.0)
+power = models.Shift(1.0) ** models.Scale(2.0)
+fix = models.fix_inputs(
+ models.AffineTransformation2D(
+ matrix=np.array([[2.0, 0.0], [0.0, 3.0]]),
+ translation=np.array([1.0, 2.0]),
+ ),
+ {0: 5.0},
+)
+
+inputs_1d = np.array([[1.0], [2.5], [-3.0], [0.5]])
+inputs_2d = np.array([[1.0, 2.0], [3.0, 4.0], [-1.0, -2.0], [0.0, 0.0]])
+
+compose_outputs = np.array([[compose(x[0])] for x in inputs_1d])
+concat_outputs = np.array([list(concat(x[0], x[1])) for x in inputs_2d])
+add_outputs = np.array([[add(x[0])] for x in inputs_1d])
+subtract_outputs = np.array([[subtract(x[0])] for x in inputs_1d])
+multiply_outputs = np.array([[multiply(x[0])] for x in inputs_1d])
+divide_outputs = np.array([[divide(x[0])] for x in inputs_1d])
+power_outputs = np.array([[power(x[0])] for x in inputs_1d])
+fix_outputs = np.array([list(fix(x[0])) for x in inputs_1d])
+
+compose_inv = compose.inverse
+compose_inv_inputs = compose_outputs.copy()
+compose_inv_outputs = np.array([[compose_inv(x[0])] for x in compose_inv_inputs])
+
+concat_inv = concat.inverse
+concat_inv_inputs = concat_outputs.copy()
+concat_inv_outputs = np.array(
+ [list(concat_inv(x[0], x[1])) for x in concat_inv_inputs]
+)
+
+af["test_cases"] = [
+ {
+ "name": "compose",
+ "transform": compose,
+ "forward_inputs": inputs_1d,
+ "forward_outputs": compose_outputs,
+ "has_inverse": True,
+ "inverse_inputs": compose_inv_inputs,
+ "inverse_outputs": compose_inv_outputs,
+ },
+ {
+ "name": "concatenate",
+ "transform": concat,
+ "forward_inputs": inputs_2d,
+ "forward_outputs": concat_outputs,
+ "has_inverse": True,
+ "inverse_inputs": concat_inv_inputs,
+ "inverse_outputs": concat_inv_outputs,
+ },
+ {
+ "name": "add",
+ "transform": add,
+ "forward_inputs": inputs_1d,
+ "forward_outputs": add_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "subtract",
+ "transform": subtract,
+ "forward_inputs": inputs_1d,
+ "forward_outputs": subtract_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "multiply",
+ "transform": multiply,
+ "forward_inputs": inputs_1d,
+ "forward_outputs": multiply_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "divide",
+ "transform": divide,
+ "forward_inputs": inputs_1d,
+ "forward_outputs": divide_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "power",
+ "transform": power,
+ "forward_inputs": inputs_1d,
+ "forward_outputs": power_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "fix_inputs",
+ "transform": fix,
+ "forward_inputs": inputs_1d,
+ "forward_outputs": fix_outputs,
+ "has_inverse": False,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/fits_wcs.py b/src/test/resources/reference-file-scripts/fits_wcs.py
new file mode 100644
index 0000000..93a53a4
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/fits_wcs.py
@@ -0,0 +1,42 @@
+crpix = np.array([512.0, 512.0])
+crval = np.array([180.0, 45.0])
+cdelt = np.array([-1e-4, 1e-4])
+pc = np.array([[1.0, 0.0], [0.0, 1.0]])
+cd = np.outer(cdelt, np.array([1.0, 1.0])) * pc
+
+shift_x = models.Shift(-crpix[0])
+shift_y = models.Shift(-crpix[1])
+affine = models.AffineTransformation2D(matrix=cd)
+tan = models.Pix2Sky_TAN()
+rot = models.RotateNative2Celestial(crval[0], crval[1], 180.0)
+
+transform = (shift_x & shift_y) | affine | tan | rot
+
+forward_inputs = np.array([
+ [512.0, 512.0],
+ [0.0, 0.0],
+ [1023.0, 1023.0],
+ [256.0, 768.0],
+])
+forward_outputs = np.array(
+ [list(transform(row[0], row[1])) for row in forward_inputs]
+)
+
+inv = transform.inverse
+inverse_inputs = forward_outputs.copy()
+inverse_outputs = np.array(
+ [list(inv(row[0], row[1])) for row in inverse_inputs]
+)
+
+af["test_cases"] = [
+ {
+ "name": "fits_wcs_imaging",
+ "transform": transform,
+ "forward_inputs": forward_inputs,
+ "forward_outputs": forward_outputs,
+ "has_inverse": True,
+ "inverse_inputs": inverse_inputs,
+ "inverse_outputs": inverse_outputs,
+ "tolerance": 1e-5,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/functional.py b/src/test/resources/reference-file-scripts/functional.py
new file mode 100644
index 0000000..a4b44bd
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/functional.py
@@ -0,0 +1,55 @@
+shift = models.Shift(3.0)
+scale = models.Scale(2.5)
+affine = models.AffineTransformation2D(
+ matrix=np.array([[0.9, -0.1], [0.2, 1.1]]),
+ translation=np.array([5.0, -3.0]),
+)
+
+shift_inputs = np.array([[1.0], [2.5], [-3.0], [0.0]])
+shift_outputs = np.array([[x[0] + 3.0] for x in shift_inputs])
+
+scale_inputs = np.array([[1.0], [2.5], [-3.0], [0.0]])
+scale_outputs = np.array([[x[0] * 2.5] for x in scale_inputs])
+
+affine_inputs = np.array([[1.0, 2.0], [0.0, 0.0], [-1.5, 3.5], [10.0, -5.0]])
+affine_outputs = np.array([affine(x[0], x[1]) for x in affine_inputs])
+
+shift_inv_inputs = shift_outputs.copy()
+shift_inv_outputs = shift_inputs.copy()
+
+scale_inv_inputs = scale_outputs.copy()
+scale_inv_outputs = scale_inputs.copy()
+
+affine_inv = affine.inverse
+affine_inv_inputs = affine_outputs.copy()
+affine_inv_outputs = np.array([affine_inv(x[0], x[1]) for x in affine_inv_inputs])
+
+af["test_cases"] = [
+ {
+ "name": "shift",
+ "transform": shift,
+ "forward_inputs": shift_inputs,
+ "forward_outputs": shift_outputs,
+ "has_inverse": True,
+ "inverse_inputs": shift_inv_inputs,
+ "inverse_outputs": shift_inv_outputs,
+ },
+ {
+ "name": "scale",
+ "transform": scale,
+ "forward_inputs": scale_inputs,
+ "forward_outputs": scale_outputs,
+ "has_inverse": True,
+ "inverse_inputs": scale_inv_inputs,
+ "inverse_outputs": scale_inv_outputs,
+ },
+ {
+ "name": "affine",
+ "transform": affine,
+ "forward_inputs": affine_inputs,
+ "forward_outputs": affine_outputs,
+ "has_inverse": True,
+ "inverse_inputs": affine_inv_inputs,
+ "inverse_outputs": affine_inv_outputs,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/geometry.py b/src/test/resources/reference-file-scripts/geometry.py
new file mode 100644
index 0000000..d3d0173
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/geometry.py
@@ -0,0 +1,99 @@
+from gwcs.geometry import (
+ CartesianToSpherical,
+ FromDirectionCosines,
+ SphericalToCartesian,
+ ToDirectionCosines,
+)
+
+s2c = SphericalToCartesian(wrap_lon_at=180)
+c2s = CartesianToSpherical(wrap_lon_at=180)
+to_dc = ToDirectionCosines()
+from_dc = FromDirectionCosines()
+
+s2c_inputs = np.array([[45.0, 30.0], [-60.0, 15.0], [120.0, -45.0], [0.0, 0.0]])
+s2c_outputs = np.array(
+ [list(s2c(row[0], row[1])) for row in s2c_inputs]
+)
+
+c2s_inputs = np.array([
+ [0.6123724, 0.6123724, 0.5],
+ [-0.3535534, 0.6123724, 0.7071068],
+ [0.0, -0.7071068, 0.7071068],
+ [1.0, 0.0, 0.0],
+])
+c2s_outputs = np.array(
+ [list(c2s(row[0], row[1], row[2])) for row in c2s_inputs]
+)
+
+to_dc_inputs = np.array([[0.5, 0.3, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [-0.5, 0.5, 0.0]])
+to_dc_outputs = np.array(
+ [list(to_dc(row[0], row[1], row[2])) for row in to_dc_inputs]
+)
+
+from_dc_inputs = to_dc_outputs.copy()
+from_dc_outputs = np.array(
+ [list(from_dc(row[0], row[1], row[2], row[3])) for row in from_dc_inputs]
+)
+
+s2c_inv = s2c.inverse
+s2c_inv_inputs = s2c_outputs.copy()
+s2c_inv_outputs = np.array(
+ [list(s2c_inv(row[0], row[1], row[2])) for row in s2c_inv_inputs]
+)
+
+c2s_inv = c2s.inverse
+c2s_inv_inputs = c2s_outputs.copy()
+c2s_inv_outputs = np.array(
+ [list(c2s_inv(row[0], row[1])) for row in c2s_inv_inputs]
+)
+
+to_dc_inv = to_dc.inverse
+to_dc_inv_inputs = to_dc_outputs.copy()
+to_dc_inv_outputs = np.array(
+ [list(to_dc_inv(row[0], row[1], row[2], row[3])) for row in to_dc_inv_inputs]
+)
+
+from_dc_inv = from_dc.inverse
+from_dc_inv_inputs = from_dc_outputs.copy()
+from_dc_inv_outputs = np.array(
+ [list(from_dc_inv(row[0], row[1], row[2])) for row in from_dc_inv_inputs]
+)
+
+af["test_cases"] = [
+ {
+ "name": "spherical_to_cartesian",
+ "transform": s2c,
+ "forward_inputs": s2c_inputs,
+ "forward_outputs": s2c_outputs,
+ "has_inverse": True,
+ "inverse_inputs": s2c_inv_inputs,
+ "inverse_outputs": s2c_inv_outputs,
+ },
+ {
+ "name": "cartesian_to_spherical",
+ "transform": c2s,
+ "forward_inputs": c2s_inputs,
+ "forward_outputs": c2s_outputs,
+ "has_inverse": True,
+ "inverse_inputs": c2s_inv_inputs,
+ "inverse_outputs": c2s_inv_outputs,
+ },
+ {
+ "name": "to_direction_cosines",
+ "transform": to_dc,
+ "forward_inputs": to_dc_inputs,
+ "forward_outputs": to_dc_outputs,
+ "has_inverse": True,
+ "inverse_inputs": to_dc_inv_inputs,
+ "inverse_outputs": to_dc_inv_outputs,
+ },
+ {
+ "name": "from_direction_cosines",
+ "transform": from_dc,
+ "forward_inputs": from_dc_inputs,
+ "forward_outputs": from_dc_outputs,
+ "has_inverse": True,
+ "inverse_inputs": from_dc_inv_inputs,
+ "inverse_outputs": from_dc_inv_outputs,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/polynomial.py b/src/test/resources/reference-file-scripts/polynomial.py
new file mode 100644
index 0000000..27c6e35
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/polynomial.py
@@ -0,0 +1,29 @@
+poly1d = models.Polynomial1D(
+ degree=3, c0=1.0, c1=-2.0, c2=0.5, c3=0.1, domain=[-5, 5], window=[-1, 1]
+)
+poly2d = models.Polynomial2D(
+ degree=2, c0_0=1.0, c1_0=2.0, c0_1=-1.0, c2_0=0.3, c1_1=0.5, c0_2=-0.2
+)
+
+poly1d_inputs = np.array([[0.0], [2.5], [-3.0], [4.5]])
+poly1d_outputs = np.array([[poly1d(row[0])] for row in poly1d_inputs])
+
+poly2d_inputs = np.array([[1.0, 2.0], [0.0, 0.0], [-1.5, 3.5], [2.0, -1.0]])
+poly2d_outputs = np.array([[poly2d(row[0], row[1])] for row in poly2d_inputs])
+
+af["test_cases"] = [
+ {
+ "name": "polynomial1d",
+ "transform": poly1d,
+ "forward_inputs": poly1d_inputs,
+ "forward_outputs": poly1d_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "polynomial2d",
+ "transform": poly2d,
+ "forward_inputs": poly2d_inputs,
+ "forward_outputs": poly2d_outputs,
+ "has_inverse": False,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/projection.py b/src/test/resources/reference-file-scripts/projection.py
new file mode 100644
index 0000000..fade5f1
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/projection.py
@@ -0,0 +1,85 @@
+gnomonic = models.Pix2Sky_TAN()
+stereographic = models.Pix2Sky_STG()
+mollweide = models.Pix2Sky_MOL()
+healpix = models.Pix2Sky_HPX()
+
+gnomonic_inputs = np.array([[0.0, 0.0], [5.0, 5.0], [-3.0, 7.0], [10.0, -5.0]])
+gnomonic_outputs = np.array([list(gnomonic(row[0], row[1])) for row in gnomonic_inputs])
+
+stereographic_inputs = np.array([[0.0, 0.0], [10.0, 10.0], [-5.0, 15.0], [20.0, -10.0]])
+stereographic_outputs = np.array(
+ [list(stereographic(row[0], row[1])) for row in stereographic_inputs]
+)
+
+mollweide_inputs = np.array([[0.0, 0.0], [10.0, 5.0], [-15.0, -8.0], [5.0, 12.0]])
+mollweide_outputs = np.array(
+ [list(mollweide(row[0], row[1])) for row in mollweide_inputs]
+)
+
+healpix_inputs = np.array([[0.0, 0.0], [10.0, 10.0], [-10.0, 20.0], [5.0, -15.0]])
+healpix_outputs = np.array(
+ [list(healpix(row[0], row[1])) for row in healpix_inputs]
+)
+
+gnomonic_inv = gnomonic.inverse
+gnomonic_inv_inputs = gnomonic_outputs.copy()
+gnomonic_inv_outputs = np.array(
+ [list(gnomonic_inv(row[0], row[1])) for row in gnomonic_inv_inputs]
+)
+
+stereographic_inv = stereographic.inverse
+stereographic_inv_inputs = stereographic_outputs.copy()
+stereographic_inv_outputs = np.array(
+ [list(stereographic_inv(row[0], row[1])) for row in stereographic_inv_inputs]
+)
+
+mollweide_inv = mollweide.inverse
+mollweide_inv_inputs = mollweide_outputs.copy()
+mollweide_inv_outputs = np.array(
+ [list(mollweide_inv(row[0], row[1])) for row in mollweide_inv_inputs]
+)
+
+healpix_inv = healpix.inverse
+healpix_inv_inputs = healpix_outputs.copy()
+healpix_inv_outputs = np.array(
+ [list(healpix_inv(row[0], row[1])) for row in healpix_inv_inputs]
+)
+
+af["test_cases"] = [
+ {
+ "name": "gnomonic",
+ "transform": gnomonic,
+ "forward_inputs": gnomonic_inputs,
+ "forward_outputs": gnomonic_outputs,
+ "has_inverse": True,
+ "inverse_inputs": gnomonic_inv_inputs,
+ "inverse_outputs": gnomonic_inv_outputs,
+ },
+ {
+ "name": "stereographic",
+ "transform": stereographic,
+ "forward_inputs": stereographic_inputs,
+ "forward_outputs": stereographic_outputs,
+ "has_inverse": True,
+ "inverse_inputs": stereographic_inv_inputs,
+ "inverse_outputs": stereographic_inv_outputs,
+ },
+ {
+ "name": "mollweide",
+ "transform": mollweide,
+ "forward_inputs": mollweide_inputs,
+ "forward_outputs": mollweide_outputs,
+ "has_inverse": True,
+ "inverse_inputs": mollweide_inv_inputs,
+ "inverse_outputs": mollweide_inv_outputs,
+ },
+ {
+ "name": "healpix",
+ "transform": healpix,
+ "forward_inputs": healpix_inputs,
+ "forward_outputs": healpix_outputs,
+ "has_inverse": True,
+ "inverse_inputs": healpix_inv_inputs,
+ "inverse_outputs": healpix_inv_outputs,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/roman_wcs.py b/src/test/resources/reference-file-scripts/roman_wcs.py
new file mode 100644
index 0000000..da0d8b2
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/roman_wcs.py
@@ -0,0 +1,76 @@
+import os
+import asdf
+
+script_dir = os.path.dirname(os.path.abspath(__file__)) if '__file__' in dir() else '.'
+resource_dir = os.path.join(script_dir, '..', 'roman-reference-files')
+if not os.path.isdir(resource_dir):
+ resource_dir = os.path.join('src', 'test', 'resources', 'roman-reference-files')
+
+test_cases = []
+
+CAL_FILENAME = 'r0034001001001001001_0001_wfi01_f062_cal_wcs_only.asdf'
+COADD_FILENAME = 'r0000101001001001001_p_v01001001001001_045p86x47y51_f158_coadd_wcs_only.asdf'
+
+cal_path = os.path.join(resource_dir, CAL_FILENAME)
+if os.path.exists(cal_path):
+ with asdf.open(cal_path) as cal_asdf:
+ cal_wcs = cal_asdf['roman']['meta']['wcs']
+
+ cal_inputs = np.array([
+ [1024.0, 1024.0],
+ [0.0, 0.0],
+ [2047.0, 2047.0],
+ [512.0, 1536.0],
+ ])
+ cal_outputs = np.array([list(cal_wcs(row[0], row[1])) for row in cal_inputs])
+
+ cal_inv = cal_wcs.backward_transform
+ cal_inv_inputs = cal_outputs.copy()
+ cal_inv_outputs = np.array(
+ [list(cal_inv(row[0], row[1])) for row in cal_inv_inputs]
+ )
+
+ test_cases.append({
+ "name": "roman_cal",
+ "fixture_path": "roman-reference-files/" + CAL_FILENAME,
+ "forward_inputs": cal_inputs,
+ "forward_outputs": cal_outputs,
+ "has_inverse": True,
+ "inverse_inputs": cal_inv_inputs,
+ "inverse_outputs": cal_inv_outputs,
+ "tolerance": 1e-10,
+ })
+
+coadd_path = os.path.join(resource_dir, COADD_FILENAME)
+if os.path.exists(coadd_path):
+ with asdf.open(coadd_path) as coadd_asdf:
+ coadd_wcs = coadd_asdf['roman']['meta']['wcs']
+
+ coadd_inputs = np.array([
+ [512.0, 512.0],
+ [0.0, 0.0],
+ [1023.0, 1023.0],
+ [256.0, 768.0],
+ ])
+ coadd_outputs = np.array(
+ [list(coadd_wcs(row[0], row[1])) for row in coadd_inputs]
+ )
+
+ coadd_inv = coadd_wcs.backward_transform
+ coadd_inv_inputs = coadd_outputs.copy()
+ coadd_inv_outputs = np.array(
+ [list(coadd_inv(row[0], row[1])) for row in coadd_inv_inputs]
+ )
+
+ test_cases.append({
+ "name": "roman_coadd",
+ "fixture_path": "roman-reference-files/" + COADD_FILENAME,
+ "forward_inputs": coadd_inputs,
+ "forward_outputs": coadd_outputs,
+ "has_inverse": True,
+ "inverse_inputs": coadd_inv_inputs,
+ "inverse_outputs": coadd_inv_outputs,
+ "tolerance": 1e-10,
+ })
+
+af["test_cases"] = test_cases
diff --git a/src/test/resources/reference-file-scripts/rotation.py b/src/test/resources/reference-file-scripts/rotation.py
new file mode 100644
index 0000000..508ef72
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/rotation.py
@@ -0,0 +1,114 @@
+rotation2d = models.Rotation2D(angle=35.0)
+
+euler_angle = models.EulerAngleRotation(23.0, 45.0, 67.0, axes_order='xyz')
+
+rotate_seq = models.RotationSequence3D(angles=[10.0, 20.0, 30.0], axes_order='xyz')
+
+native2celestial = models.RotateNative2Celestial(lon=45.0, lat=60.0, lon_pole=180.0)
+
+celestial2native = models.RotateCelestial2Native(lon=45.0, lat=60.0, lon_pole=180.0)
+
+rotation2d_inputs = np.array([[1.0, 0.0], [0.0, 1.0], [3.0, 4.0], [-2.0, 1.5]])
+rotation2d_outputs = np.array(
+ [list(rotation2d(row[0], row[1])) for row in rotation2d_inputs]
+)
+
+euler_inputs = np.array([[10.0, 20.0], [30.0, 40.0], [-15.0, 25.0], [45.0, -10.0]])
+euler_outputs = np.array(
+ [list(euler_angle(row[0], row[1])) for row in euler_inputs]
+)
+
+rotate_seq_inputs = np.array(
+ [[10.0, 20.0, 30.0], [30.0, 40.0, 50.0], [-15.0, 25.0, 10.0], [45.0, -10.0, 20.0]]
+)
+rotate_seq_outputs = np.array(
+ [list(rotate_seq(row[0], row[1], row[2])) for row in rotate_seq_inputs]
+)
+
+n2c_inputs = np.array([[0.0, 0.0], [10.0, 20.0], [-15.0, 30.0], [45.0, -10.0]])
+n2c_outputs = np.array(
+ [list(native2celestial(row[0], row[1])) for row in n2c_inputs]
+)
+
+c2n_inputs = np.array([[0.0, 0.0], [10.0, 20.0], [-15.0, 30.0], [45.0, -10.0]])
+c2n_outputs = np.array(
+ [list(celestial2native(row[0], row[1])) for row in c2n_inputs]
+)
+
+rotation2d_inv = rotation2d.inverse
+rotation2d_inv_inputs = rotation2d_outputs.copy()
+rotation2d_inv_outputs = np.array(
+ [list(rotation2d_inv(row[0], row[1])) for row in rotation2d_inv_inputs]
+)
+
+euler_inv = euler_angle.inverse
+euler_inv_inputs = euler_outputs.copy()
+euler_inv_outputs = np.array(
+ [list(euler_inv(row[0], row[1])) for row in euler_inv_inputs]
+)
+
+rotate_seq_inv = rotate_seq.inverse
+rotate_seq_inv_inputs = rotate_seq_outputs.copy()
+rotate_seq_inv_outputs = np.array(
+ [list(rotate_seq_inv(row[0], row[1], row[2])) for row in rotate_seq_inv_inputs]
+)
+
+n2c_inv = native2celestial.inverse
+n2c_inv_inputs = n2c_outputs.copy()
+n2c_inv_outputs = np.array(
+ [list(n2c_inv(row[0], row[1])) for row in n2c_inv_inputs]
+)
+
+c2n_inv = celestial2native.inverse
+c2n_inv_inputs = c2n_outputs.copy()
+c2n_inv_outputs = np.array(
+ [list(c2n_inv(row[0], row[1])) for row in c2n_inv_inputs]
+)
+
+af["test_cases"] = [
+ {
+ "name": "rotation2d",
+ "transform": rotation2d,
+ "forward_inputs": rotation2d_inputs,
+ "forward_outputs": rotation2d_outputs,
+ "has_inverse": True,
+ "inverse_inputs": rotation2d_inv_inputs,
+ "inverse_outputs": rotation2d_inv_outputs,
+ },
+ {
+ "name": "euler_angle_rotation",
+ "transform": euler_angle,
+ "forward_inputs": euler_inputs,
+ "forward_outputs": euler_outputs,
+ "has_inverse": True,
+ "inverse_inputs": euler_inv_inputs,
+ "inverse_outputs": euler_inv_outputs,
+ },
+ {
+ "name": "rotate_sequence_3d",
+ "transform": rotate_seq,
+ "forward_inputs": rotate_seq_inputs,
+ "forward_outputs": rotate_seq_outputs,
+ "has_inverse": True,
+ "inverse_inputs": rotate_seq_inv_inputs,
+ "inverse_outputs": rotate_seq_inv_outputs,
+ },
+ {
+ "name": "rotate_native2celestial",
+ "transform": native2celestial,
+ "forward_inputs": n2c_inputs,
+ "forward_outputs": n2c_outputs,
+ "has_inverse": True,
+ "inverse_inputs": n2c_inv_inputs,
+ "inverse_outputs": n2c_inv_outputs,
+ },
+ {
+ "name": "rotate_celestial2native",
+ "transform": celestial2native,
+ "forward_inputs": c2n_inputs,
+ "forward_outputs": c2n_outputs,
+ "has_inverse": True,
+ "inverse_inputs": c2n_inv_inputs,
+ "inverse_outputs": c2n_inv_outputs,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/spectroscopy.py b/src/test/resources/reference-file-scripts/spectroscopy.py
new file mode 100644
index 0000000..30dbb45
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/spectroscopy.py
@@ -0,0 +1,103 @@
+from gwcs import spectroscopy as sp
+
+sellmeier_glass = sp.SellmeierGlass(
+ B_coef=[1.03961212, 0.23179234, 1.01046945],
+ C_coef=[6.00069867e-3, 2.00179144e-2, 1.03560653e2],
+)
+
+glass_inputs = np.array([[0.5], [0.6], [0.8], [1.0]])
+glass_outputs = np.array([[sellmeier_glass(row[0])] for row in glass_inputs])
+
+sellmeier_zemax = sp.SellmeierZemax(
+ temperature=22.0,
+ ref_temperature=20.0,
+ ref_pressure=101325.0,
+ pressure=101325.0,
+ B_coef=[1.03961212, 0.23179234, 1.01046945],
+ C_coef=[6.00069867e-3, 2.00179144e-2, 1.03560653e2],
+ D_coef=[1.86e-6, 1.31e-8, -1.37e-11],
+ E_coef=[4.34e-7, 1.15e-9, 0.17],
+)
+
+zemax_inputs = np.array([[0.5], [0.6], [0.8], [1.0]])
+zemax_outputs = np.array(
+ [[sellmeier_zemax(np.array([row[0]]))[0]] for row in zemax_inputs]
+)
+
+snell3d = sp.Snell3D()
+
+snell_inputs = np.array([
+ [1.5, 0.3, 0.4, 0.0],
+ [1.0, 0.3, 0.4, 0.0],
+ [1.2, 0.1, 0.2, 0.0],
+ [2.0, 0.5, 0.3, 0.0],
+])
+snell_outputs = np.array(
+ [list(snell3d(row[0], row[1], row[2], row[3])) for row in snell_inputs]
+)
+
+angles_from_grating = sp.AnglesFromGratingEquation3D(
+ groove_density=2700.0, spectral_order=-1,
+)
+
+angles_inputs = np.array([
+ [2e-6, 0.1, 0.1],
+ [1e-6, 0.05, 0.05],
+ [5e-7, 0.2, 0.1],
+ [3e-6, 0.01, 0.02],
+])
+angles_outputs = np.array(
+ [list(angles_from_grating(row[0], row[1], row[2])) for row in angles_inputs]
+)
+
+wavelength_from_grating = sp.WavelengthFromGratingEquation(
+ groove_density=2700.0, spectral_order=-1,
+)
+
+wl_inputs = np.array([
+ [0.1, 0.2],
+ [0.05, 0.15],
+ [0.3, 0.1],
+ [0.01, 0.02],
+])
+wl_outputs = np.array(
+ [[wavelength_from_grating(row[0], row[1])] for row in wl_inputs]
+)
+
+af["test_cases"] = [
+ {
+ "name": "sellmeier_glass",
+ "transform": sellmeier_glass,
+ "forward_inputs": glass_inputs,
+ "forward_outputs": glass_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "sellmeier_zemax",
+ "transform": sellmeier_zemax,
+ "forward_inputs": zemax_inputs,
+ "forward_outputs": zemax_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "snell3d",
+ "transform": snell3d,
+ "forward_inputs": snell_inputs,
+ "forward_outputs": snell_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "angles_from_grating_equation_3d",
+ "transform": angles_from_grating,
+ "forward_inputs": angles_inputs,
+ "forward_outputs": angles_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "wavelength_from_grating_equation",
+ "transform": wavelength_from_grating,
+ "forward_inputs": wl_inputs,
+ "forward_outputs": wl_outputs,
+ "has_inverse": False,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/tabular.py b/src/test/resources/reference-file-scripts/tabular.py
new file mode 100644
index 0000000..e651221
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/tabular.py
@@ -0,0 +1,27 @@
+tabular1d = models.Tabular1D(
+ points=np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0]),
+ lookup_table=np.array([0.0, 2.1, 3.8, 6.2, 7.9, 10.5]),
+ method="linear",
+ bounds_error=True,
+)
+
+tabular1d_inputs = np.array([[0.5], [1.7], [2.3], [4.2]])
+tabular1d_outputs = np.array([[tabular1d(row[0])] for row in tabular1d_inputs])
+
+tabular1d_inv = tabular1d.inverse
+tabular1d_inv_inputs = tabular1d_outputs.copy()
+tabular1d_inv_outputs = np.array(
+ [[tabular1d_inv(row[0])] for row in tabular1d_inv_inputs]
+)
+
+af["test_cases"] = [
+ {
+ "name": "tabular1d",
+ "transform": tabular1d,
+ "forward_inputs": tabular1d_inputs,
+ "forward_outputs": tabular1d_outputs,
+ "has_inverse": True,
+ "inverse_inputs": tabular1d_inv_inputs,
+ "inverse_outputs": tabular1d_inv_outputs,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/wcs_cal.py b/src/test/resources/reference-file-scripts/wcs_cal.py
new file mode 100644
index 0000000..88972e6
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/wcs_cal.py
@@ -0,0 +1,67 @@
+detector = cf.Frame2D(name="detector", axes_order=(0, 1))
+v2v3 = cf.Frame2D(name="v2v3", axes_order=(0, 1))
+v2v3vacorr = cf.Frame2D(name="v2v3vacorr", axes_order=(0, 1))
+v2v3corr = cf.Frame2D(name="v2v3corr", axes_order=(0, 1))
+sky = cf.CelestialFrame(reference_frame=coord.ICRS(), axes_order=(0, 1))
+
+distortion = (
+ (models.Shift(-1024.0) & models.Shift(-1024.0))
+ | models.AffineTransformation2D(
+ matrix=np.array([[0.11, 0.005], [-0.005, 0.11]]),
+ translation=np.array([0.0, 0.0]),
+ )
+)
+
+velocity_correction = models.AffineTransformation2D(
+ matrix=np.array([[1.001, 0.0], [0.0, 0.999]]),
+ translation=np.array([0.0, 0.0]),
+)
+
+tpc_correction = models.AffineTransformation2D(
+ matrix=np.array([[1.0, 0.002], [-0.002, 1.0]]),
+ translation=np.array([0.1, -0.05]),
+)
+
+tan = models.Pix2Sky_TAN()
+celestial_rotation = models.RotateNative2Celestial(
+ lon=53.16, lat=-27.79, lon_pole=180.0
+)
+to_sky = (
+ (models.Scale(1.0 / 3600.0) & models.Scale(1.0 / 3600.0))
+ | tan
+ | celestial_rotation
+)
+
+pipeline = [
+ (detector, distortion),
+ (v2v3, velocity_correction),
+ (v2v3vacorr, tpc_correction),
+ (v2v3corr, to_sky),
+ (sky, None),
+]
+w = gwcs_wcs.WCS(pipeline)
+
+inputs = np.array([
+ [1024.0, 1024.0],
+ [512.0, 512.0],
+ [100.0, 200.0],
+ [1500.0, 1800.0],
+])
+outputs = np.array([list(w(row[0], row[1])) for row in inputs])
+
+inv = w.backward_transform
+inv_inputs = outputs.copy()
+inv_outputs = np.array([list(inv(row[0], row[1])) for row in inv_inputs])
+
+af["test_cases"] = [
+ {
+ "name": "cal_pipeline",
+ "wcs": w,
+ "forward_inputs": inputs,
+ "forward_outputs": outputs,
+ "has_inverse": True,
+ "inverse_inputs": inv_inputs,
+ "inverse_outputs": inv_outputs,
+ "tolerance": 1e-9,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/wcs_imaging.py b/src/test/resources/reference-file-scripts/wcs_imaging.py
new file mode 100644
index 0000000..e6cfcce
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/wcs_imaging.py
@@ -0,0 +1,28 @@
+detector = cf.Frame2D(name="detector", axes_order=(0, 1))
+sky = cf.CelestialFrame(reference_frame=coord.ICRS(), axes_order=(0, 1))
+
+shift = models.Shift(1.0) & models.Shift(2.0)
+scale = models.Scale(0.1) & models.Scale(0.1)
+transform = shift | scale
+
+pipeline = [(detector, transform), (sky, None)]
+w = gwcs_wcs.WCS(pipeline)
+
+inputs = np.array([[0.0, 0.0], [10.0, 20.0], [50.0, 50.0], [100.0, 100.0]])
+outputs = np.array([list(w(row[0], row[1])) for row in inputs])
+
+inv = w.backward_transform
+inv_inputs = outputs.copy()
+inv_outputs = np.array([list(inv(row[0], row[1])) for row in inv_inputs])
+
+af["test_cases"] = [
+ {
+ "name": "simple_imaging",
+ "wcs": w,
+ "forward_inputs": inputs,
+ "forward_outputs": outputs,
+ "has_inverse": True,
+ "inverse_inputs": inv_inputs,
+ "inverse_outputs": inv_outputs,
+ },
+]
diff --git a/src/test/resources/reference-file-scripts/wcs_spectroscopy.py b/src/test/resources/reference-file-scripts/wcs_spectroscopy.py
new file mode 100644
index 0000000..a33e3a8
--- /dev/null
+++ b/src/test/resources/reference-file-scripts/wcs_spectroscopy.py
@@ -0,0 +1,44 @@
+from gwcs import spectroscopy as sp
+
+grating = sp.WavelengthFromGratingEquation(groove_density=2700.0, spectral_order=-1)
+glass = sp.SellmeierGlass(
+ B_coef=[1.03961212, 0.23179234, 1.01046945],
+ C_coef=[6.00069867e-3, 2.00179144e-2, 1.03560653e2],
+)
+
+grating_inputs = np.array([
+ [0.1, 0.2],
+ [0.05, 0.15],
+ [-0.1, 0.3],
+ [0.15, -0.1],
+])
+grating_outputs = np.array(
+ [[grating(row[0], row[1])] for row in grating_inputs]
+)
+
+glass_inputs = np.array([
+ [0.5],
+ [0.6],
+ [0.7],
+ [0.8],
+])
+glass_outputs = np.array(
+ [[glass(row[0])] for row in glass_inputs]
+)
+
+af["test_cases"] = [
+ {
+ "name": "wavelength_from_grating_equation",
+ "transform": grating,
+ "forward_inputs": grating_inputs,
+ "forward_outputs": grating_outputs,
+ "has_inverse": False,
+ },
+ {
+ "name": "sellmeier_glass",
+ "transform": glass,
+ "forward_inputs": glass_inputs,
+ "forward_outputs": glass_outputs,
+ "has_inverse": False,
+ },
+]
diff --git a/src/test/resources/testing/reference_file_generator.py b/src/test/resources/testing/reference_file_generator.py
new file mode 100644
index 0000000..396d1b5
--- /dev/null
+++ b/src/test/resources/testing/reference_file_generator.py
@@ -0,0 +1,35 @@
+import sys
+from io import BytesIO
+
+import asdf
+import numpy as np
+from astropy import coordinates as coord
+from astropy.modeling import models
+
+import gwcs.coordinate_frames as cf
+import gwcs.wcs as gwcs_wcs
+
+
+def main():
+ af = asdf.AsdfFile()
+
+ script = sys.stdin.read()
+ env = {
+ "af": af,
+ "np": np,
+ "models": models,
+ "cf": cf,
+ "gwcs_wcs": gwcs_wcs,
+ "coord": coord,
+ }
+ exec(script, env)
+
+ buffer = BytesIO()
+ af.write_to(buffer)
+
+ buffer.seek(0)
+ sys.stdout.buffer.write(buffer.read())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/test-requirements.txt b/test-requirements.txt
new file mode 100644
index 0000000..0f2743d
--- /dev/null
+++ b/test-requirements.txt
@@ -0,0 +1,3 @@
+gwcs
+astropy
+numpy