Skip to content

Commit

Permalink
ttools: rationalise and refactor RampKeySet
Browse files Browse the repository at this point in the history
Make RampKeySet more flexible, and use it for the density shading
in ShapeMode as well as for Aux and Spectro shading.
This eliminates some special case/duplicated code in density shading,
and makes it easier to add extra shader functionality in a consistent
way for different functions.

RampKeySet.Ramp interface now just aggregates a Shader and a Scaling,
which is all it was really doing before.
  • Loading branch information
mbtaylor committed Jan 28, 2015
1 parent 0c0783c commit 97ad679
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 257 deletions.
Expand Up @@ -14,6 +14,7 @@
import uk.ac.starlink.ttools.plot2.AuxScale;
import uk.ac.starlink.ttools.plot2.Captioner;
import uk.ac.starlink.ttools.plot2.PlotLayer;
import uk.ac.starlink.ttools.plot2.PlotUtil;
import uk.ac.starlink.ttools.plot2.ShadeAxis;
import uk.ac.starlink.ttools.plot2.ShadeAxisFactory;
import uk.ac.starlink.ttools.plot2.Subrange;
Expand Down Expand Up @@ -82,7 +83,10 @@ public void actionPerformed( ActionEvent evt ) {
} );
rangeSpecifier_.addActionListener( forwarder );

addSpecifierTab( "Map", new ConfigSpecifier( RAMP_KEYS.getKeys() ) );
ConfigKey[] shaderKeys =
PlotUtil.arrayConcat( RAMP_KEYS.getKeys(),
new ConfigKey[] { StyleKeys.AUX_NULLCOLOR } );
addSpecifierTab( "Map", new ConfigSpecifier( shaderKeys ) );
addSpecifierTab( "Ramp", axisSpecifier );
addSpecifierTab( "Range", rangeSpecifier_ );
}
Expand Down Expand Up @@ -139,7 +143,8 @@ public boolean isLog() {
Captioner captioner =
StyleKeys.CAPTIONER.createValue( configger_.getConfig() );
RampKeySet.Ramp ramp = RAMP_KEYS.createValue( config );
return ramp.createShadeAxisFactory( captioner, label, crowd );
return RampKeySet
.createShadeAxisFactory( ramp, captioner, label, crowd );
}

public boolean isLog() {
Expand Down
231 changes: 96 additions & 135 deletions ttools/src/main/uk/ac/starlink/ttools/plot2/config/RampKeySet.java
@@ -1,6 +1,5 @@
package uk.ac.starlink.ttools.plot2.config;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand All @@ -25,139 +24,160 @@
public class RampKeySet implements KeySet<RampKeySet.Ramp> {

private final ConfigKey<Shader> shaderKey_;
private final ConfigKey<Subrange> subrangeKey_;
private final ConfigKey<Subrange> shadeclipKey_;
private final ConfigKey<Boolean> flipKey_;
private final OptionConfigKey<Scaling> scalingKey_;
private final ConfigKey<Color> nullcolorKey_;
private final ConfigKey<Subrange> dataclipKey_;
private final ConfigKey[] keys_;

/**
* Constructor.
*
* @param axname short form of axis name
* @param axName long form of axis name
* @param axname short form of axis name, used in text parameter names
* @param axName long form of axis name, used in descriptions
* @param shaders array of preset shader options
* @param dfltScaling default scaling function
* @param hasDataclip true iff a data subrange key is to be included
*/
public RampKeySet( String axname, String axName ) {
public RampKeySet( String axname, String axName, Shader[] shaders,
Scaling dfltScaling, boolean hasDataclip ) {
List<ConfigKey> keyList = new ArrayList<ConfigKey>();

List<Shader> shaderList = new ArrayList<Shader>();
shaderList.addAll( Arrays.asList( shaders ) );
shaderList.addAll( Arrays.asList( Shaders.getCustomShaders() ) );
shaderKey_ = new ShaderConfigKey(
new ConfigMeta( axname + "map", axName + " Shader" )
.setShortDescription( "Color map for " + axName + " shading" )
.setXmlDescription( new String[] {
"<p>Color map used for " + axName + " axis shading.",
"<p>Color map used for",
axName,
"axis shading.",
"</p>",
} )
, createAuxShaders(), Shaders.LUT_RAINBOW
, shaderList.toArray( new Shader[ 0 ] ), shaderList.get( 0 )
).appendShaderDescription()
.setOptionUsage();
keyList.add( shaderKey_ );

subrangeKey_ =
shadeclipKey_ =
new SubrangeConfigKey( SubrangeConfigKey
.createShaderClipMeta( axname, axName ) );
keyList.add( shadeclipKey_ );

ConfigMeta flipMeta = new ConfigMeta( axname + "flip", "Shader Flip" );
flipMeta.setShortDescription( "Flip " + axName + " colour ramp?" );
flipMeta.setXmlDescription( new String[] {
"<p>If true, the colour map on the " + axName + " axis",
"will be reversed.",
"<p>If true, the colour map on the",
axName,
"axis will be reversed.",
"</p>",
} );
flipKey_ = new BooleanConfigKey( flipMeta );
keyList.add( flipKey_ );

ConfigMeta scalingMeta = new ConfigMeta( axname + "func", "Scaling" );
scalingMeta.setShortDescription( axName + " scaling function" );
scalingMeta.setXmlDescription( new String[] {
"<p>Defines the way that values in the (possibly clipped)",
axname + " range are mapped to the selected colour ramp.",
"<p>Defines the way that values in the",
axName,
"range are mapped to the selected colour ramp.",
"</p>",
} );
scalingKey_ =
new OptionConfigKey<Scaling>( scalingMeta, Scaling.class,
Scaling.getStretchOptions(),
Scaling.LINEAR );
dfltScaling );
scalingKey_.setOptionUsage();
scalingKey_.addOptionsXml();
keyList.add( scalingKey_ );

nullcolorKey_ = new ColorConfigKey(
ColorConfigKey.createColorMeta( axname + "nullcolor", "Null Color",
"points with a null value of the "
+ axName + " coordinate" )
.appendXmlDescription( new String[] {
"<p>If the value is null, then points with a null",
axName,
"value will not be plotted at all.",
"</p>",
} )
, Color.GRAY, true );
dataclipKey_ =
new SubrangeConfigKey( SubrangeConfigKey
.createAxisSubMeta( axname, axName ) );
if ( hasDataclip ) {
keyList.add( dataclipKey_ );
}

keys_ = keyList.toArray( new ConfigKey[ 0 ] );
}

public ConfigKey[] getKeys() {
return new ConfigKey[] {
shaderKey_,
subrangeKey_,
flipKey_,
scalingKey_,
nullcolorKey_,
};
return keys_;
}

public Ramp createValue( ConfigMap config ) {
final Shader shader = StyleKeys.createShader( config, shaderKey_,
subrangeKey_, flipKey_ );
final Scaling scaling = config.get( scalingKey_ );
final Color nullcolor = config.get( nullcolorKey_ );
final boolean isLog = scaling.isLogLike();

/* Determine configured shader instance. */
Shader shader = config.get( shaderKey_ );
Subrange shadeclip = config.get( shadeclipKey_ );
boolean isFlip = config.get( flipKey_ );
if ( ! Subrange.isIdentity( shadeclip ) ) {
shader = Shaders.stretch( shader, (float) shadeclip.getLow(),
(float) shadeclip.getHigh() );
}
if ( isFlip ) {
shader = Shaders.invert( shader );
}

/* Determine configured scaling instance. */
Scaling scaling = config.get( scalingKey_ );
Subrange dataclip = config.get( dataclipKey_ );
if ( ! Subrange.isIdentity( dataclip ) ) {
scaling = Scaling.subrangeScaling( scaling, dataclip );
}

/* Construct and return a Ramp instance. */
final Shader shader0 = shader;
final Scaling scaling0 = scaling;
return new Ramp() {
public Shader getShader() {
return shader;
return shader0;
}
public Scaling getScaling() {
return scaling;
return scaling0;
}
public Color getNullColor() {
return nullcolor;
};
}

/**
* Creates a ShadeAxisFactory for a given ramp.
*
* @param ramp ramp
* @param captioner shader ramp captioner
* @param label shader ramp label
* @param crowding tick crowding factor (1 is normal)
* @return new factory
*/
public static ShadeAxisFactory
createShadeAxisFactory( Ramp ramp, final Captioner captioner,
final String label,
final double crowding ) {
final Shader shader = ramp.getShader();
final Scaling scaling = ramp.getScaling();
final boolean isLog = scaling.isLogLike();
return new ShadeAxisFactory() {
public boolean isLog() {
return isLog;
}
public ShadeAxisFactory
createShadeAxisFactory( final Captioner captioner,
final String label,
final double crowding ) {
return new ShadeAxisFactory() {
public boolean isLog() {
return isLog;
}
public ShadeAxis createShadeAxis( Range range ) {
if ( range == null ) {
range = new Range();
}
double[] bounds = range.getFiniteBounds( isLog );
double lo = bounds[ 0 ];
double hi = bounds[ 1 ];
return new ShadeAxis( shader, scaling, lo, hi,
label, captioner, crowding );
}
};
public ShadeAxis createShadeAxis( Range range ) {
if ( range == null ) {
range = new Range();
}
double[] bounds = range.getFiniteBounds( isLog );
double lo = bounds[ 0 ];
double hi = bounds[ 1 ];
return new ShadeAxis( shader, scaling, lo, hi,
label, captioner, crowding );
}
};
}

/**
* Defines ramp characteristics.
*
* <p>Possibly the code could be simplified by combining the functions
* of this class and ShadeAxisFactory.
* Defines ramp characteristics by aggregating a Shader and a Scaling.
*/
public interface Ramp {

/**
* Creates a ShadeAxisFactory for this ramp.
*
* @param captioner shader ramp captioner
* @param label shader ramp label
* @param crowding tick crowding factor (1 is normal)
* @return new factory
*/
ShadeAxisFactory createShadeAxisFactory( Captioner captioner,
String label,
double crowding );

/**
* Returns this ramp's shader.
*
Expand All @@ -172,64 +192,5 @@ ShadeAxisFactory createShadeAxisFactory( Captioner captioner,
* @return scaling
*/
Scaling getScaling();

/**
* Returns the colour in which items with no ramp data value
* should be painted.
*
* @return null colour; if null, blank values are not painted
*/
Color getNullColor();
}

/**
* Returns a list of shaders suitable for aux axis shading.
*
* @return shaders
*/
private static Shader[] createAuxShaders() {
List<Shader> shaderList = new ArrayList<Shader>();
shaderList.addAll( Arrays.asList( new Shader[] {
Shaders.LUT_RAINBOW,
Shaders.LUT_GLNEMO2,
Shaders.LUT_PASTEL,
Shaders.LUT_ACCENT,
Shaders.LUT_GNUPLOT,
Shaders.LUT_GNUPLOT2,
Shaders.LUT_CUBEHELIX,
Shaders.LUT_SPECXB2Y,
Shaders.LUT_SET1,
Shaders.LUT_PAIRED,
Shaders.CYAN_MAGENTA,
Shaders.RED_BLUE,
Shaders.LUT_BRG,
Shaders.LUT_HEAT,
Shaders.LUT_COLD,
Shaders.LUT_LIGHT,
Shaders.LUT_COLOR,
Shaders.WHITE_BLACK,
Shaders.LUT_STANDARD,
Shaders.LUT_RAINBOW3,
Shaders.createMaskShader( "Mask", 0f, 1f, true ),
Shaders.FIX_HUE,
Shaders.TRANSPARENCY,
Shaders.FIX_INTENSITY,
Shaders.FIX_RED,
Shaders.FIX_GREEN,
Shaders.FIX_BLUE,
Shaders.HSV_H,
Shaders.HSV_S,
Shaders.HSV_V,
Shaders.FIX_Y,
Shaders.FIX_U,
Shaders.FIX_V,
Shaders.BREWER_BUGN,
Shaders.BREWER_BUPU,
Shaders.BREWER_ORRD,
Shaders.BREWER_PUBU,
Shaders.BREWER_PURD,
} ) );
shaderList.addAll( Arrays.asList( Shaders.getCustomShaders() ) );
return shaderList.toArray( new Shader[ 0 ] );
}
}

0 comments on commit 97ad679

Please sign in to comment.