Significant figures bug in C# and .NET in general


Presently, I am working on a scientific application, and have been creating some data tables. A request was made to me to ensure that some data columns be rounded to 3 significant figures e.g.

10.1234 becomes 10.1

10.7335 becomes 10.7

1.1003 becomes 1.10

I thought through this request with nonchalance at first, but was surprised just how difficult and time consuming it turned out to be to fulfil. After trying out many examples on the interwebs, including some lengthy code libraries, the solution was simplicity itself, using the .NET string format modifier G0 where the number after G is the number of significant figures desired,  so

Console.WriteLine((10.12345).ToString(“G3”));

Will give you a result of 10.1

This works fine and as expected, but the bug is when you have 10.0, what is output to screen is 10

After traipsing through numerous articles, the result was that this behaviour was “by design”. After communicating this “by design” feature to my boss (and numerous scientists), their retort was that it was a bug and ought to be corrected. The reason why they were so annoyed was because the missing trailing zero indicates a level of accuracy that is an unacceptable omission in their field, thus I was advised to prefer two decimal places instead.

One of the first rules you are taught as a new programmer, is that numbers in computer programs are zero based i.e. you start counting at zero because zero is a number, so why in this case are the .NET framework designers ignoring the zero? One must say that one concurs with this being a bug, and wish the framework library team could correct this behaviour, to save developers polluting their codebases with conversions to strings and back to numbers, just so one can present data in a way that is meaningful to mathematically based users.

Should I use DevExpress WPF controls for a new project?


Firstly, I must draw attention to the fact that my intention is not to spew bile, or communicate zealot-ism of any shape or form. My intention is to try and provide a fair, concise and balanced view, relative to personal experience that may hopefully assist anyone looking to answer this question.

Presently, I am now nearly six months into a Greenfield project, written exclusively using DevExpress WPF controls. Over the last few months, I have come to know their WPF API’s particularly well, and will continue to use the controls for the lifetime of the project simply because it is too late. A definite consideration is that it is often impossible to change anything major as a third party software suite you are developing on top of midway, for all sorts of reasons, the most notable being expense and time/delay to finish. WPF is such a flexible platform, I would advocate getting the business logic and functionality of an application thrashed out first, then look to a design team or third-party suite right at the end the end or during the process, rather than automatically restricting oneself from the offset with a third party suite. This, however, is seldom practicable, as the product owner/customer will need to be interacting with the software as time progresses, and they want to see something pretty, there is hardly ever any flexibility here, the application has to look stunning very soon into the start of the project, in order to gain their confidence (and settle their nerves) and continue in this vein.

There is nothing like hindsight, a trite but often unavoidable word when reflecting on a projects progression, It is always harder to be objective at a later date, because quite often, a quite different set of circumstances and considerations result due to the fact that time has moved on, and better ways of dealing with technical challenges and vendors present themselves. the steps required to solve particular problems become perspicacious.

One also must accept that projects must commence at some point, and utilise the best that is available at the time, otherwise no-one would ever start anything, because a better suite of components are just around the corner. Invariably, there have been profuse technical challenges along the way, as the application is a scientific one, but that is the essential stimulus for me personally,  yes, not fun some days, and you have good days and bad ones, but the overwhelming sense of achievement in surmounting the obstacles are what makes one do it again and again. Attention to minute detail is of unparalleled importance.  For all intents and purposes, it is about minutiae!

I think it important to take note that this is not a typical forms over data application but of a scientific bent, and thus far, their controls have proven very hard, if not impossible to customise to meet our technical requirements and specifications with ease and eloquence. Over the last month or so, I have been writing code that I quite frankly feel embarrassed to ever admit that I checked in…why?

The biggest problem is that DevExpress developers completely misunderstood WPF when they developed their WPF controls. I really cannot impress upon you sufficiently well just how much of a displeasure it is using their controls. I feel absolutely terrible (almost guilty) about talking about a vendor with such negativity, but they have made a serious mistake in their WPF suite, it has been a singular source of the most abject frustration for me in about a decade of developing software. WPF was built to allow developers to be flexible, and to build components with ease, using DevExpress controls cuts your flexibility by about 90% (and that is not a guesstimate).

Frequently, it is possible to get off to a bad start in any project, even with experienced developers. It is the fresh ideas and perspicacious vision that allow younger developers for the most part to escape the nebulous approach experienced developers tend to exhibit. In my experience developing WPF applications over the last three years or so, one of the most poisonous components to introduce to a new  WPF application, is a dyed-in- the-wool Windows Forms developer. One feels however that one must communicate extensive and comprehensive experience as a Windows Forms developer, but  somehow I managed to shake off any misdirection in solving WPF problems after witnessing just how bad approaching WPF from a C++ and Windows Forms mentality is. On some projects, I have witnessed resplendent software engineers and architects commit the gravest mistakes in implementing WPF projects, simply because they could not and would not start looking at things from a different direction. It is this scourge that has been eminent in the procurement for DevExpress WPF controls, that much is irrefutable.

Recently, after speaking with a colleague, we arrived at the conclusion that their WPF API’s have been written top down by Windows Forms developers. It is that, and their overwhelming success as Third Party Windows Forms Vendors where things have gone horribly wrong. Using their controls in most instances, places asphyxia on whatever problem you are trying to resolve, because most of their API’s are just so hard to get to do what you want them to do, because they failed to grasp what WPF developers expect in their components. Frequently, I consult my rather extensive library of code to solve problems that I find cropping up again and again, but it is almost impossible to use any of my  existing WPF code with their controls, because of the way they have implemented their API’s. That is a sad indictment of the API’s. A simple application that you write in WPF and bind to in an items control or List Box in WPF, is impossible to migrate to their Grid controls for example because of their horrendous implementation.

One of the key components in every WPF project that I have worked on is Model View View-Model (MVVM) proficiency. This has been an essential and sought after skill when dealing with customers. As I write today, you will find plethoric requests for MVVM support for their WPF controls, and hitherto there is none. There are no code samples or examples on their numerous websites, so typically you will confront a problem, and find that their controls are specifically written to handle events in the code-behind and not commands. You will also find that they adore the decade old version of ADO.NET that is datasets. I have not worked on a single WPF application that has not used MVVM or POCO’s, finding anything in their documentation or code samples using POCO’s is as likely as finding a hen with teeth, speaks French, and tells jokes.

Their WPF Ribbon is a prime example of being a complete dog to work with. It is incomplete, non-MVVM compliant, and when customers say their want an Office 2010 Application Menu for example, your sat left wondering, why you paid the money for the controls. Using it in your applications is a factory for writing tightly coupled hard to modify code, and if you do create workarounds you find that you have a polluted codebase, trying to get a MVVM application that is easily testable. Whilst we are on the subject of testing, try to find a single example of a WPF component of theirs in a test situation, I will save you the time, and regrettably advise you that there are no code samples, nor do their components help one build testable code. DevExpress almost obstinately choose to ensure that you develop the hardest to maintain and poorly separated code, by creating components that cultivate bad practices. If you are a design oriented software team or company, you will find that DevExpress only supply asphyxiation to your ability to progress, you can take out the ”express” and replace it with “Dev-Stress” or “Dev-Stressed”

What I cannot however fault, is their support, this is certainly a redeeming feature, because their have an absolutely brilliant support system, and their staff are a joy to work with. They almost always find a solution for a query, though sometimes one is left wondering why  you needed to consult someone to perform what are mostly basic functions.If you are thinking of using their controls then you must be prepared to accept that you are for the most part, a paying guinea pig, because most of the issues you will have have either been reported by other customers, or your problem will be used to resolve other peoples problems in the future, as their websites and forums are pretty useless, they seem to take little care in preparing helpful documentation and code samples that reflect real world usage for their customers, pretty much every example is an example on how not to write quality software.

Another big issue I have found is with their release cycle. They generally have two big releases every year, and lots of incremental ones. If you find a bug, it is always tempting to update to their bug fix versions, but I have found this to be an endless source of hair-loss. Pretty much every time I have upgraded to solve an issue, it has been partially fixed, or ended up creating bugs or their have renamed and changed things that break things. The Visual Studio way of releasing software seems the best for developing complex projects, where over the period of a year or so, you can concentrate of solving the domain problems, rather than bug-riddled releases. It may sound as If I am being harsh or truculent, but this is the reality of using their software.

If you are thinking of using DevExpress WPF controls, you really have to try and assess whether you fall into their 90% use case, or their 10% oddities, but even if you do fall into their 90%, their API’s will assist you in writing a lot of hard to test, inelegant and expensive to maintain code, as they have been written to work best using the paradigm of the technology they are meant to be replacing (Windows Forms). If you have worked with WPF for any amount of time, it is almost unbelievable just how restrictive their controls are to use. Presently, even as one writes, befuddlement  continues to present itself, as to how or why their controls work the way they do? The Microsoft WPF control library is such a flexible system, why asphyxiate you and your organisations software development efforts by people that still write software components as if it was a decade ago?

Saturation/Desaturation with HLSL/Pixel Shaders and WPF


Setup and Configuration

I have been working a lot with image processing applications recently, and encountered a problem a little while ago where there was a algorithm slowing a portion of an application down, due to it performing pixel by pixel transformations in C# code. I was advised to seek correction of the problem, and fervidly look into HLSL as a possible solution, and was fortunate enough enough to stumble upon the Shader Effects & Build Tasks project on codeplex. The reason that HLSL was suggested was because HLSL code executes on the graphics card, is supremely efficient, lightning fast and can even execute in parallel.

Downloading and installing Shader Effects BuildTask and Templates.zip (you can also download the source instead if you want) greatly simplifies ones ability to work with Pixel Shaders, as it allows for Visual Studio integration. Make sure you install the ShaderBuildTaskSetup.msi and most importantly read the readme, as this will direct you on the location for unzipping the required templates that you will need to do if requisite templates are to be available for you in visual studio (very easy, just copy a few zipped files to a location on your machine)

Projects

Now that the required components are installed, create a new WPF project/solution in Visual Studio (I am using 2010 Ultimate, but this should work with Visual Studio 2008, the Express Editions or Silverlight) and call it SaturateDesaturate.

Add another project to this solution, this time a Shader Effect Library (ensure the templates linked to above are installed) and call it ShaderEffects.

ShaderEffects

This new shader effects library hooks up the plumbing required to easily create pixel shaders. Again, I would advise you read the readme in this new .dll project. Right click the file that ends in .fx , select properties, you should have the following

BuildAction

When you installed the build tasks and templates above, this key component was added to this type of .dll, so whenever you add a new effect file, ensure that the .fx file has it’s build action set to effect or else things will not work.

Code Sample

Delete the automatically added Effect1.cs and Effect1.fx make sure you do not delete EffectLibrary.cs as this will be used by any effects that you add.

Add a new shader effect to the ShaderEffects project and call it DesaturateEffect.. For brevities sake , copy the following code into it;

 

using System.Windows;

using System.Windows.Media;
using System.Windows.Media.Effects;
 
namespace ShaderEffects
{
public class DesaturateEffect : ShaderEffect
{
#region Constructors
 
static DesaturateEffect()
{
_pixelShader.UriSource = Global.MakePackUri("DesaturateEffect.ps");
}
 
public DesaturateEffect()
{
this.PixelShader = _pixelShader;
 
// Update each DependencyProperty that’s registered with a shader register.  This
// is needed to ensure the shader gets sent the proper default value.
UpdateShaderValue(InputProperty);
UpdateShaderValue(SaturationProperty);
}
 
#endregion
 
#region Dependency Properties
 
public Brush Input
{
get { return (Brush)GetValue(InputProperty); }
set { SetValue(InputProperty, value); }
}
 
// Brush-valued properties turn into sampler-property in the shader.
// This helper sets "ImplicitInput" as the default, meaning the default
// sampler is whatever the rendering of the element it’s being applied to is.
public static readonly DependencyProperty InputProperty =
RegisterPixelShaderSamplerProperty("Input", typeof(DesaturateEffect), 0);
 
 
 
public double Saturation
{
get { return (double)GetValue(SaturationProperty); }
set { SetValue(SaturationProperty, value); }
}
 
public static readonly DependencyProperty SaturationProperty =
DependencyProperty.Register("Saturation",
typeof(double),
typeof(DesaturateEffect),
new UIPropertyMetadata(1.0, PixelShaderConstantCallback(0)));
 
 
#endregion
 
#region Member Data
 
private static PixelShader _pixelShader = new PixelShader();
 
#endregion
 
}
}
 
 

This essentially hooks up the WPF piece to the HLSL piece, with the PixelShaderConstantCallback receiving the value from the HLSL.

HLSL

Copy the following code into your .fx file

//————————————————————————————–
//
// WPF ShaderEffect HLSL — DesaturateEffect
//
//————————————————————————————–
 
//—————————————————————————————–
// Shader constant register mappings (scalars – float, double, Point, Color, Point3D, etc.)
//—————————————————————————————–
 
float4 Saturation : register(c0);
 
//————————————————————————————–
// Sampler Inputs (Brushes, including ImplicitInput)
//————————————————————————————–
 
sampler2D implicitInputSampler : register(S0);
 
//————————————————————————————–
// Pixel Shader
//————————————————————————————–
 
float4 main(float2 uv : TEXCOORD) : COLOR
{
float3  LuminanceWeights = float3(0.299,0.587,0.114);
float4    srcPixel = tex2D(implicitInputSampler, uv);
float    luminance = dot(srcPixel,LuminanceWeights);
float4    dstPixel = lerp(luminance,srcPixel,Saturation);
//retain the incoming alpha
dstPixel.a = srcPixel.a;
return dstPixel;
 
}
 
 

This simple HLSL code will be applied to every pixel on the image using the graphics card and saturate/desaturate the image. In the MainWindow.xaml copy the following code;

<Window x:Class="SaturateDesaturate.MainWindow"
xmlns:shaders="clr-namespace:ShaderEffects;assembly=ShaderEffects"
Title="MainWindow" Height="600" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Image Source="/SaturateDesaturate;component/Images/Jellyfish.jpg" Grid.Row="0" >
<Image.Effect>
<shaders:DesaturateEffect Saturation="{Binding ElementName=slider, Path=Value}" />
</Image.Effect>
</Image>
 
<Slider x:Name="slider" Minimum="0" Maximum="6" Value="1" Grid.Row="1" />
</Grid>
</Window>

If you add an image and compare the saturation with a program like Paint.NET you will see that you have saturation added to your WPF images with a very few lines of code, and best of all it is very fast. I would also recommend you search codeplex for a shader effects library that contains many more shader effects and will help you get started and understand how they work.

I would also advise you to ensure that you remember to freeze all pixel shader instances (in your effect .cs files) and remove any static references (especially static constructors and shaders), as they are a prime candidate for memory leaks.

Original Image

 

Original

Paint.NET

 

Paint.NET200

HLSL Example

 

HLSL