Skip to main content
RSS feed Subscribe to feed

 

Skip Navigation LinksHome  Extending the Spotfire Platform  Creating Extensions to the Spotfire Platform  Creating a Transformation  Transformation: Using Properties From a Previous Transform

©Spotfire 2011

Transformation: Using Properties From a Previous Transform

This custom transformation uses properties to perform the Box-Cox transformation on all real columns using the value of the property.

This is a custom transformation which uses the properties added in the Lambda transformation example – Transformation: Setting Metadata. It performs the Box-Cox transformation on all real columns that have the Custom.Lambda property set using that value as lambda. Columns which do not have Custom.Lambda set are just sent through the transform. It also uses the Custom.Propagate property to decide if the original column also should be returned for transformed columns. The code sample only shows the reader:

private class BoxCoxTransformationReader : CustomDataRowReader
{
    private DataRowReader inputReader;
    private List<DataRowReaderColumn> columns;

    private List<MutableValueCursor<double>> transformedCursors;
    private List<DataValueCursor<double>> transformInputCursors;
    private List<double> lambdas;

    public BoxCoxTransformationReader(DataRowReader inputReader)
    {
        this.inputReader = inputReader;
        this.transformedCursors = new List<MutableValueCursor<double>>();
        this.transformInputCursors = new List<DataValueCursor<double>>();
        this.lambdas = new List<double>();

        this.columns = new List<DataRowReaderColumn>();
        foreach (DataRowReaderColumn col in inputReader.Columns)
        {
            bool propagate = true;
            bool isLambda = false;
            DataColumnProperties properties = col.Properties;
            if (col.DataType == DataType.Real && 
			    col.Properties.HasPropertyValue("Custom.Lambda"))
            {
                isLambda = true;

                double lambda = 
						(double)col.Properties.GetProperty("Custom.Lambda");

                propagate = 
						(bool)col.Properties.GetProperty("Custom.Propagate");

                this.lambdas.Add(lambda);

                MutableValueCursor<double> cursor = (MutableValueCursor <double>)DataValueCursor.CreateMutableCursor(DataType.Real);
                this.transformedCursors.Add(cursor);
                
				this.transformInputCursors.Add(
						(DataValueCursor<double>)col.Cursor);

                this.columns.Add(
                    new DataRowReaderColumn(
                        col.Name,
                        col.DataType,
                        properties,
                        cursor));
            }
            
            if(propagate)
            {
                // does not have a lambda property.
                string columnName = col.Name;
                if(isLambda)
                {
                    // add original to propagated transformed columns.
                    columnName = 
						string.Format("Original {0}", columnName);
                }
                this.columns.Add(
                    new DataRowReaderColumn(
                    columnName,
                    col.DataType,
                    properties,
                    col.Cursor));
            }
        }
    }

    protected override IEnumerable<DataRowReaderColumn> GetColumnsCore()
    {
        return this.columns;
    }

    protected override ResultProperties GetResultPropertiesCore()
    {
        return this.inputReader.ResultProperties;
    }

    protected override void ResetCore()
    {
        this.inputReader.Reset();
    }

    protected override bool MoveNextCore()
    {
        if (!this.inputReader.MoveNext())
        {
            return false;                    
        }
        for (int i = 0; i < this.transformedCursors.Count; ++i)
        {
            DataValueCursor<double> input = this.transformInputCursors[i];
            MutableValueCursor<double> output = this.transformedCursors[i];

            if (input.IsCurrentValueValid)
            {
                output.MutableDataValue.IsValid = true;
                double val = input.CurrentValue;
                double lambda = this.lambdas[i];
                if (lambda == 0)
                {
                    val = Math.Log(val);
                }
                else if(lambda != 1)
                {
                    val = (Math.Pow(val, lambda) - 1) / lambda;
                }
                output.MutableDataValue.Value = val;
            }
            else
            {
                output.MutableDataValue.IsValid = false;
			    output.MutableDataValue.ErrorValue = 
						input.CurrentDataValue.ErrorValue;
            }
        }
        return true;
    }
}