Skip to content

Commit

Permalink
ttools: plot2 Coord now uses value domains.
Browse files Browse the repository at this point in the history
The Coord objects that specify where plots get their data from are
now capable of specifying their required data domain,
and using mappers supplied in response to convert values from
some potentially non-obvious input form to a usable common value domain.
  • Loading branch information
mbtaylor committed Aug 15, 2013
1 parent c60bc17 commit ec26f58
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 21 deletions.
@@ -1,5 +1,7 @@
package uk.ac.starlink.ttools.plot2.data;

import uk.ac.starlink.table.DomainMapper;

/**
* Coord implementation for single boolean values.
*
Expand All @@ -17,10 +19,10 @@ public class BooleanCoord extends SingleCoord {
*/
public BooleanCoord( String name, String description, boolean isRequired ) {
super( name, description, isRequired,
Boolean.class, StorageType.BOOLEAN );
Boolean.class, StorageType.BOOLEAN, null );
}

public Object userToStorage( Object[] userCoords ) {
public Object userToStorage( Object[] userCoords, DomainMapper[] mappers ) {
Object c = userCoords[ 0 ];
return c instanceof Boolean ? (Boolean) c : Boolean.FALSE;
}
Expand Down
Expand Up @@ -8,6 +8,7 @@
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import uk.ac.starlink.table.DomainMapper;
import uk.ac.starlink.table.RowSequence;
import uk.ac.starlink.table.StarTable;
import uk.ac.starlink.ttools.plot2.Equality;
Expand Down Expand Up @@ -503,6 +504,7 @@ private static class CoordSpec {
final int icoord_;
final Coord coord_;
final Object coordId_;
final DomainMapper[] mappers_;

/**
* Constructor.
Expand All @@ -516,6 +518,8 @@ private static class CoordSpec {
table_ = dataSpec.getSourceTable();
coordId_ = dataSpec.getCoordId( icoord );
coord_ = dataSpec.getCoord( icoord );
mappers_ = SimpleDataStoreFactory
.getUserCoordMappers( dataSpec, icoord );
}

/**
Expand All @@ -537,7 +541,7 @@ StorageType getStorageType() {
Object readValue( RowSequence rseq, long irow ) throws IOException {
Object[] userCoords =
dataReader_.getUserCoordValues( rseq, irow, icoord_ );
Object value = coord_.userToStorage( userCoords );
Object value = coord_.userToStorage( userCoords, mappers_ );
assert value != null;
return value;
}
Expand Down
30 changes: 29 additions & 1 deletion ttools/src/main/uk/ac/starlink/ttools/plot2/data/Coord.java
@@ -1,6 +1,8 @@
package uk.ac.starlink.ttools.plot2.data;

import java.util.List;
import uk.ac.starlink.table.ValueInfo;
import uk.ac.starlink.table.DomainMapper;

/**
* Defines a coordinate quantity in terms of both the user's view of it
Expand Down Expand Up @@ -35,6 +37,21 @@ public interface Coord {
*/
ValueInfo[] getUserInfos();

/**
* Indicates the target common value domain(s) in which the relevant
* value(s) will be used.
* The return value is a list (one for each user value) of DomainMapper
* abstract sub-types. Each of these sub-types effectively defines
* a target value domain. Null entries for this list are the norm,
* indicating that the user values will just be interpreted as numeric
* values, but non-null domains values can be used if a particular
* interpretation (for instance time) is going to be imposed.
*
* @return list (same length as <code>getUserInfos</code>) of
* domain mapper subtypes; elements may be null
*/
List<Class<? extends DomainMapper>> getUserDomains();

/**
* Indicates whether this item must have a non-blank value in order
* for a plot to be possible.
Expand All @@ -55,10 +72,21 @@ public interface Coord {
* Turns a quantity in the user view to a plotting view object.
* The return value is never null.
*
* <p>The <code>userMappers</code> contains entries as specified
* by the result of the {@link #getUserDomains} method.
* The array must be the same length as the user domains array,
* and each non-null element must be an instance of the class
* in the corresponding element of the user domains array.
* In many cases however, coordinates are not sensitive to domains,
* and for those cases implementations will ignore
* <code>userMappers</code>.
*
* @param userValues array of objects corresponding to the result of
* {@link #getUserInfos}
* @param userMappers domains mappers associated with submitted values
* if available and appropriate;
* @return object of the type corresponding to the result of
* {@link #getStorageType}; not null
*/
Object userToStorage( Object[] userValues );
Object userToStorage( Object[] userValues, DomainMapper[] userMappers );
}
@@ -1,5 +1,6 @@
package uk.ac.starlink.ttools.plot2.data;

import uk.ac.starlink.table.DomainMapper;
import uk.ac.starlink.ttools.plot2.PlotUtil;

/**
Expand All @@ -26,7 +27,8 @@ public abstract class FloatingArrayCoord extends SingleCoord {
private FloatingArrayCoord( String name, String description,
boolean isRequired, boolean isDouble ) {
super( name, description, isRequired, Object.class,
isDouble ? StorageType.DOUBLE_ARRAY : StorageType.FLOAT_ARRAY );
isDouble ? StorageType.DOUBLE_ARRAY : StorageType.FLOAT_ARRAY,
null );
}

/**
Expand Down Expand Up @@ -80,7 +82,8 @@ public static FloatingArrayCoord createCoord( String name, String descrip,
/* Double precision implementation. */
return new FloatingArrayCoord( name, descrip, isRequired, true ) {

public Object userToStorage( Object[] userCoords ) {
public Object userToStorage( Object[] userCoords,
DomainMapper[] mappers ) {
Object a = userCoords[ 0 ];
final double[] da;
if ( a instanceof double[] ) {
Expand Down Expand Up @@ -146,7 +149,8 @@ public double[] readArrayCoord( TupleSequence tseq, int icol ) {

/* Single precision implementation. */
return new FloatingArrayCoord( name, descrip, isRequired, true ) {
public Object userToStorage( Object[] userCoords ) {
public Object userToStorage( Object[] userCoords,
DomainMapper[] mappers ) {
Object a = userCoords[ 0 ];
final float[] fa;
if ( a instanceof float[] ) {
Expand Down
@@ -1,5 +1,6 @@
package uk.ac.starlink.ttools.plot2.data;

import uk.ac.starlink.table.DomainMapper;
import uk.ac.starlink.ttools.plot2.PlotUtil;

/**
Expand Down Expand Up @@ -28,15 +29,18 @@ public class FloatingCoord extends SingleCoord {
* @param description user-directed coordinate description
* @param isRequired true if this coordinate is required for plotting
* @param isDouble true for double precision, false for single
* @param infoClass class of user coordinate quantity
* @param domain DomainMapper subtype for this coord, or null
*/
private FloatingCoord( String name, String description, boolean isRequired,
boolean isDouble ) {
super( name, description, isRequired, Number.class,
isDouble ? StorageType.DOUBLE : StorageType.FLOAT );
boolean isDouble, Class infoClass,
Class<? extends DomainMapper> domain ) {
super( name, description, isRequired, infoClass,
isDouble ? StorageType.DOUBLE : StorageType.FLOAT, domain );
nan_ = isDouble ? new Double( Double.NaN ) : new Float( Float.NaN );
}

public Object userToStorage( Object[] userCoords ) {
public Object userToStorage( Object[] userCoords, DomainMapper[] mappers ) {
Object c = userCoords[ 0 ];
return c instanceof Number ? ((Number) c) : nan_;
}
Expand Down Expand Up @@ -66,6 +70,7 @@ public double readDoubleCoord( TupleSequence tseq, int icol ) {
public static FloatingCoord createCoord( String name, String description,
boolean isRequired ) {
return new FloatingCoord( name, description, isRequired,
PlotUtil.storeFullPrecision() );
PlotUtil.storeFullPrecision(),
Number.class, null );
}
}
@@ -1,9 +1,13 @@
package uk.ac.starlink.ttools.plot2.data;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import uk.ac.starlink.table.DomainMapper;
import uk.ac.starlink.table.RowSequence;
import uk.ac.starlink.table.ValueInfo;
import uk.ac.starlink.ttools.plot2.PlotUtil;

/**
Expand Down Expand Up @@ -43,6 +47,41 @@ public TupleSequence getTupleSequence( DataSpec spec ) {
}
}

/**
* Utility method to work out the domain mappers for a given
* coordinate of a DataSpec.
* For the requested coord, it returns a mapper array with elements
* filled, in with any mapper known for the given user coordinates
* that has the sub-type appropriate for that coordinate.
*
* @param dataSpec data specification object
* @param icoord index of coordinate in <code>dataSpec</code>
* @return mapper array for decoding values of one coordinate
* of a data spec
*/
public static DomainMapper[] getUserCoordMappers( DataSpec dataSpec,
int icoord ) {
List<Class<? extends DomainMapper>> userDomains =
dataSpec.getCoord( icoord ).getUserDomains();
ValueInfo[] userInfos = dataSpec.getUserCoordInfos( icoord );
int nu = userDomains.size();
DomainMapper[] mappers = new DomainMapper[ nu ];
for ( int iu = 0; iu < nu; iu++ ) {
Class reqClazz = userDomains.get( iu );
if ( reqClazz != null ) {
DomainMapper[] infoMappers = userInfos[ iu ].getDomainMappers();
for ( int im = 0;
im < infoMappers.length && mappers[ iu ] == null;
im++ ) {
if ( reqClazz.isInstance( infoMappers[ im ] ) ) {
mappers[ iu ] = infoMappers[ im ];
}
}
}
}
return mappers;
}

/**
* TupleSequence implementation for use with SimpleDataStoreFactory.
* It simply reads the user data every time and converts it to
Expand All @@ -52,6 +91,7 @@ private static class SimpleTupleSequence implements TupleSequence {
private final DataSpec spec_;
private final UserDataReader reader_;
private final RowSequence baseSeq_;
private final DomainMapper[][] mappers_;
private long irow_ = -1;
private boolean failed_;

Expand All @@ -65,6 +105,11 @@ private static class SimpleTupleSequence implements TupleSequence {
spec_ = spec;
reader_ = spec.createUserDataReader();
baseSeq_ = rseq;
int nc = spec.getCoordCount();
mappers_ = new DomainMapper[ nc ][];
for ( int ic = 0; ic < nc; ic++ ) {
mappers_[ ic ] = getUserCoordMappers( spec, ic );
}
}

public boolean next() {
Expand Down Expand Up @@ -96,7 +141,8 @@ public Object getObjectValue( int icol ) {
Object[] userCoords =
reader_.getUserCoordValues( baseSeq_, irow_, icol );
Object value =
spec_.getCoord( icol ).userToStorage( userCoords );
spec_.getCoord( icol )
.userToStorage( userCoords, mappers_[ icol ] );
assert value != null;
return value;
}
Expand Down
@@ -1,6 +1,10 @@
package uk.ac.starlink.ttools.plot2.data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import uk.ac.starlink.table.DefaultValueInfo;
import uk.ac.starlink.table.DomainMapper;
import uk.ac.starlink.table.ValueInfo;

/**
Expand All @@ -15,6 +19,7 @@ public abstract class SingleCoord implements Coord {
private DefaultValueInfo coordInfo_;
private final boolean isRequired_;
private final StorageType storageType_;
private final List<Class<? extends DomainMapper>> domains_;

/**
* Constructor.
Expand All @@ -24,18 +29,28 @@ public abstract class SingleCoord implements Coord {
* @param isRequired true if this coordinate is required for plotting
* @param infoClass class of user coordinate quantity
* @param storageType storage type object
* @param domain DomainMapper subtype for this coord, or null
*/
protected SingleCoord( String name, String description, boolean isRequired,
Class infoClass, StorageType storageType ) {
Class infoClass, StorageType storageType,
Class<? extends DomainMapper> domain ) {
isRequired_ = isRequired;
storageType_ = storageType;
List<Class<? extends DomainMapper>> domainList =
new ArrayList<Class<? extends DomainMapper>>();
domainList.add( domain );
domains_ = Collections.unmodifiableList( domainList );
setCoordInfo( new DefaultValueInfo( name, infoClass, description ) );
}

public ValueInfo[] getUserInfos() {
return new ValueInfo[] { getUserInfo() };
}

public List<Class<? extends DomainMapper>> getUserDomains() {
return domains_;
}

/**
* Returns the single coordinate metadata object.
* This may be modified as part of configuration.
Expand Down
20 changes: 17 additions & 3 deletions ttools/src/main/uk/ac/starlink/ttools/plot2/data/SkyCoord.java
@@ -1,6 +1,9 @@
package uk.ac.starlink.ttools.plot2.data;

import java.util.ArrayList;
import java.util.List;
import uk.ac.starlink.table.DefaultValueInfo;
import uk.ac.starlink.table.DomainMapper;
import uk.ac.starlink.table.ValueInfo;
import uk.ac.starlink.ttools.plot2.PlotUtil;

Expand Down Expand Up @@ -43,6 +46,14 @@ public ValueInfo[] getUserInfos() {
return skyVariant_.getUserInfos();
}

public List<Class<? extends DomainMapper>> getUserDomains() {
List<Class<? extends DomainMapper>> list =
new ArrayList<Class<? extends DomainMapper>>( 2 );
list.add( null );
list.add( null );
return list;
}

public StorageType getStorageType() {
return storageType_;
}
Expand Down Expand Up @@ -128,7 +139,8 @@ private static class DoubleSkyCoord extends SkyCoord {
variant_ = variant;
}

public Object userToStorage( Object[] userCoords ) {
public Object userToStorage( Object[] userCoords,
DomainMapper[] mappers ) {
return variant_.userToDouble3( userCoords );
}

Expand Down Expand Up @@ -165,7 +177,8 @@ private static class FloatSkyCoord extends SkyCoord {
variant_ = variant;
}

public Object userToStorage( Object[] userCoords ) {
public Object userToStorage( Object[] userCoords,
DomainMapper[] mappers ) {
double[] d3 = variant_.userToDouble3( userCoords );
return new float[] {
(float) d3[ 0 ],
Expand Down Expand Up @@ -211,7 +224,8 @@ private static class IntegerSkyCoord extends SkyCoord {
variant_ = variant;
}

public Object userToStorage( Object[] userCoords ) {
public Object userToStorage( Object[] userCoords,
DomainMapper[] mappers ) {
double[] v3 = variant_.userToDouble3( userCoords );
if ( v3 == NO_SKY ) {
return ZERO3;
Expand Down
@@ -1,5 +1,7 @@
package uk.ac.starlink.ttools.plot2.data;

import uk.ac.starlink.table.DomainMapper;

/**
* Coord implementation for String values.
*
Expand All @@ -17,10 +19,10 @@ public class StringCoord extends SingleCoord {
*/
public StringCoord( String name, String description, boolean isRequired ) {
super( name, description, isRequired,
Object.class, StorageType.STRING );
Object.class, StorageType.STRING, null );
}

public Object userToStorage( Object[] userCoords ) {
public Object userToStorage( Object[] userCoords, DomainMapper[] mappers ) {
Object c = userCoords[ 0 ];
return c == null ? "" : c.toString();
}
Expand Down

0 comments on commit ec26f58

Please sign in to comment.