Startsidan  ▸  Texter  ▸  Teknikblogg

Anders Hesselbom

Programmerare, skeptiker, sekulärhumanist, antirasist.
Författare till bok om C64 och senbliven lantis.
Röstar pirat.

Some visual aid

To conclude, click on an organism to zoom in on it. When an organism is zoomed in, some details about it is shown together with the DNA string of the parent organisms (if the parents are still alive).

Download: Drifting.exe

Happy new year!

If you are interested in looking at the source code, a VS2010 Visual Basic solution can be downloaded here. The solution targets .NET Framework 2.0.

Pythonscript för gratis musik

Som bekant kan man ladda hem hur mycket upphovsrättsskyddad musik som helst, helt gratis och (om så önskas) helt anonymt från Google. Om du är förtjust i scriptingspråket Python, har Nick Jensen filat till ett script som du kan använda för att hämta hem din favoritmusik i MP3-format. Nick Jensen’s script finns att ladda hem här.

Using regions

Regions are used to define a path or an area for later use. The Region instruction takes any number of coordinates (3 or more), and stores them in memory. The region can then be used for drawing. The following example is done in Notepad. I have created a text-file, changed the file ending from .txt to .mob. In the file, I have added these three lines of text:

Clear #ffffff 70x70
Region (10,10) (60,10) (60,60) (10,60)
Line Region #ff00ff

When loaded in the Monkeybone viewer, this is the result:

When regions are created using the MonkeyboneWriter class, they are much easier to manipulate. This example defines a shape, writes it, manipulates it, and writes it again.

Module Module1

    Sub Main()

        'Create a Monkeybone stream.
        Using W As New Monkeybone.MonkeyboneWriter("C:\regions.mob", 130, 130,
            System.Drawing.Color.Black)

            'Define a region.
            Dim R As New Monkeybone.Instructions.Region()
            R.AddPoint(10, 110)
            R.AddPoint(60, 10)
            R.AddPoint(110, 110)

            'Write the region to the stream.
            W.WriteLine(R)

            'Write an instruction to draw the region outline in green.
            Dim L As New Monkeybone.Instructions.Line()
            L.Color = Drawing.Color.Lime
            L.UseRegion = True
            W.WriteLine(L)

            'Modify the region (move it 10 pixels to the
               left and 10 pixels down) and write it again.
            R.Move(10, 10)
            W.WriteLine(R)

            'Write an instruction to draw the region outline in yellow.
            L.Color = Drawing.Color.Yellow
            W.Write(L)

            'Flush and close the stream.
            W.Flush()
            W.Close()
        End Using

    End Sub

End Module

The code produces the following mob file:

Clear #000000 130x130
Region (10,110) (60,10) (110,110)
Line Region #00FF00
Region (20,120) (70,20) (120,120)
Line Region #FFFF00

This is the result when it is loaded into the Monkeybone viewer:

Some changes made to the viewer

Some changes are made to the Monkeybone viewer, that is not related to the Monkeybone format (*.mob files). These changes are made just to make the viewer more decent.

Not only Monkeybone images can be opened. Now, you can open PNG and JPG files as well. Features such as viewing the error log, viewing the source or saving, is only available when a Monkeybone image is loaded.

When an image is loaded, no matter if it is a Monekybone image or not, the viewer checks the directory for other images. You can use the file menu to load the next or previous image in the folder, or just press F11 for the previous image and F12 for the next.

Again, these changes are made just to make viewing easier. The Monkeybone viewer is designed to display Monkeybone images. If you are in to serious image viewing, I recommend IrfanView instead. But if you are looking for a viewer of the powerful and editable Monkeybone fomat, the Monkeybone viewer is it.

Counting the DNA differences

The following adjustment is done to the drifting game. In the first version, DNA differences were counted sequentially, meaning that within each group each organism was compared to its neighbor. By changing this so that every organism is compared to every other organism, and then divided to the number of comparisons done within each group, the number of DNA differences within each group is much more accurate. This makes the increasing differences, the drifting, much more obvious.

The screenshot displays the number of differences just a few years after separation of the groups.

Download the drifting game here.

This is the drifting game!

The drifting game does not illustrate evolution or the power of natural selection, but change over time and our ability to tell that about relationship to other spices, such as chimpanzees. The board consists of 285 placeholders (19 x 15). Each placeholder can hold one organism. This is an organism.

The blue number indicates the age in years of the organism. The red number shows the number of offspring the organism has produced. An organism cannot produce offspring on its own; it must mate with another organism of the opposite gender. Light blue rectangle represent male organisms, pink represent female. What else? 😉 The lines are drawn between parents with the child in between.

In the middle, the DNA of the organism is displayed. The red amino acid pairs with red or yellow amino acid. The green amino acid pairs with green or blue amino acid. A DNA string consists of 24 pairs. The effect of this demonstration will be better if the number of pairs is greater, but it makes the visual overview poorer.

When organisms breed, the offspring will have a mixture of the parents DNA. Sometimes, mutations occur. Mutations cannot be traced from either parent. A mutation can sometimes be easy to spot, because in a mutation, any amino acid can pair with any amino acid. So a red could pair with a red, but it could also pair with a green. A pair of red and yellow could be a mutation, a pair of red and green is a mutation.

An organism that isn’t too young or too old might breed and an organism of high age might die and leave room for younger individuals.

To control: Press Space to pause and press F12 to separate the group in to two groups (can be done once). The expected effect after the split is that the number of DNA differences between individuals in the group will remain the same as the previous total, but the DNA differences between the groups will increase over time, even though no selection is done. The DNA differences are counted for sequentially and divided by the number individuals in a group. So, not every individual is compared with every individual. Correction here.

Before the population is splitted into two groups (press F12 to do that), the total number of DNA differences is shown. After the population is splitted into two groups, the total number of DNA differences is shown together with the number of DNA differences within each group. Now you can compare the differences within each group (expected to be smaller) with the total number of differences (expected to be larger since the groups are drifting in different directions).

Download the drifting game here.

PhotoName improvements, December 2009

The following changes are made to PhotoName.

The Options dialog (click Behaviour and Other settings) lets you control what will happen if you double click an image in the list.

A new drop down menu (Edit) is added to the menu bar. From there you can change what images are selected in the list. You can choose to select all images, no images or toggle the selection.

Also, you can view all images as thumbnails, and click on the images you want to select or deselect. To do this, click Edit and Select from thumbnails.

This is very effective if you want to export images as a gallery, because you have a good overview of what pictures you have in the selected directory and which of them will be included in the gallery.

You can download PhotoName from here.

The Monkeybone writer

The Monkeybone Viewer takes a mob file and displays its content on screen. The file stores instructions, such as Bar and Line, as Unicode text. These files can be created by hand using any text editor, such as Notepad (shown here, here, here and here).

To automate the generation of the Monkeybone file, you can write a program that creates a file with instructions (with mob as file ending), and writes the instructions to that file. If you do this using the .NET Framework, you might create a StreamWriter and write lines of text to that writer.

To ensure that the output file is formatted the correct way, and to make this process easier, you can download and use the Monkeybone library that contains the MonkeyboneWriter class. The MonkeyboneWriter class inherits from the StreamWriter class, and it provides overloads of the WriteLine function that takes objects that represent Monkeybone instructions. To make a Bar instruction appear in the file, create a Monkeybone.MonkeyboneWriter object, create a Monkeybone.Bar object and set the properties of the object. Pass the Monkeybone.Bar object to the WriteLine function of the Monkeybone.MonkeyboneWriter object. To make another Bar instruction appear in the file, you can create a new Bar object or modify the Bar object you already have, and pass it to the WriteLine function again, like so:

Module Module1

    Sub Main()

        'Create a Monkeybone stream.
        Using W As New Monkeybone.MonkeyboneWriter("C:\mypicture.mob", _
            200, 170, System.Drawing.Color.Black)

            'Create a vertical Monkeybone bar.
            Dim B As New Monkeybone.Instructions.Bar(10, 10, 20, 100)
            B.Orientation = Monkeybone.Instructions.Bar.BarOrientation.Vertical
            B.Color = Drawing.Color.Red

            'Write the bar to the stream.
            W.WriteLine(B)

            'Modify it, and write it again.
            B.X += 10
            B.Y += 20
            B.Color = Drawing.Color.Yellow
            W.WriteLine(B)

            'Modify it, and write it again.
            B.X += 10
            B.Y += 20
            B.Color = Drawing.Color.Green
            W.WriteLine(B)

            'A nice sine effect on top of everything!
            Dim SineBar As New Monkeybone.Instructions.Bar(0, 5, 1, 160, Drawing.Color.White)
            SineBar.Orientation = Monkeybone.Instructions.Bar.BarOrientation.Vertical
            For I As Integer = 0 To 31
                SineBar.X += 6
                SineBar.BarFillPercent = 60 + CType((Math.Sin(I / 5) * 40), Integer)
                W.WriteLine(SineBar)
            Next

            'Flush and close the stream.
            W.Flush()
            W.Close()
        End Using

    End Sub

End Module

(The code requires a reference to the Monkeybone library.)

Monkeybone pictures can created using Notepad, from any program that creates a Unicode text file with the mob file ending, or from a .NET application using the MonkeyboneWriter class of the Monkeybone library.

This is the output from the example program (the contents of the mypicture.mob file):

Clear #000000 200x170
Bar #FF0000 X:10 Y:10 W:20 H:100
Bar #FFFF00 X:20 Y:30 W:20 H:100
Bar #008000 X:30 Y:50 W:20 H:100
Bar #FFFFFF X:46 Y:5 W:5 H:160 VFill:60%
Bar #FFFFFF X:52 Y:5 W:5 H:160 VFill:68%
Bar #FFFFFF X:58 Y:5 W:5 H:160 VFill:76%
Bar #FFFFFF X:64 Y:5 W:5 H:160 VFill:83%
Bar #FFFFFF X:70 Y:5 W:5 H:160 VFill:89%
Bar #FFFFFF X:76 Y:5 W:5 H:160 VFill:94%
Bar #FFFFFF X:82 Y:5 W:5 H:160 VFill:97%
Bar #FFFFFF X:88 Y:5 W:5 H:160 VFill:99%
Bar #FFFFFF X:94 Y:5 W:5 H:160
Bar #FFFFFF X:100 Y:5 W:5 H:160 VFill:99%
Bar #FFFFFF X:106 Y:5 W:5 H:160 VFill:96%
Bar #FFFFFF X:112 Y:5 W:5 H:160 VFill:92%
Bar #FFFFFF X:118 Y:5 W:5 H:160 VFill:87%
Bar #FFFFFF X:124 Y:5 W:5 H:160 VFill:81%
Bar #FFFFFF X:130 Y:5 W:5 H:160 VFill:73%
Bar #FFFFFF X:136 Y:5 W:5 H:160 VFill:66%
Bar #FFFFFF X:142 Y:5 W:5 H:160 VFill:58%
Bar #FFFFFF X:148 Y:5 W:5 H:160 VFill:50%
Bar #FFFFFF X:154 Y:5 W:5 H:160 VFill:42%
Bar #FFFFFF X:160 Y:5 W:5 H:160 VFill:36%
Bar #FFFFFF X:166 Y:5 W:5 H:160 VFill:30%
Bar #FFFFFF X:172 Y:5 W:5 H:160 VFill:25%
Bar #FFFFFF X:178 Y:5 W:5 H:160 VFill:22%
Bar #FFFFFF X:184 Y:5 W:5 H:160 VFill:20%
Bar #FFFFFF X:190 Y:5 W:5 H:160 VFill:20%
Bar #FFFFFF X:196 Y:5 W:5 H:160 VFill:22%
Bar #FFFFFF X:202 Y:5 W:5 H:160 VFill:25%
Bar #FFFFFF X:208 Y:5 W:5 H:160 VFill:29%
Bar #FFFFFF X:214 Y:5 W:5 H:160 VFill:35%
Bar #FFFFFF X:220 Y:5 W:5 H:160 VFill:41%
Bar #FFFFFF X:226 Y:5 W:5 H:160 VFill:49%

If you load the mypicture.mob file in the Monkeybone viewer, this would be the result:

Making fun things from the knowledge of evolution

Evolution is a powerful mechanism, and the powerful source that is behind it is decent with modification plus selection. In nature, it has taken us from simple chemical reactions to complex self-aware organism over billions of years. The structure of any living mammal is very complex, and biology is filled with complicated concepts, and nothing would make any sense if we didn’t know about the very simple concept of evolution. In nature, evolution explains why fossils of different ages look different, and it explains the origin of very complex structures like the cell, the immune system and the human brain, and this knowledge casts light over areas that doesn’t have anything to do with biology, like computer science and computer programming.

Designed structures are usually simple and have one or a few purposes, while evolved structures usually are complex and have multiple functions. Designed structures usually are things. Obstacles, roads, walls, jugs. Evolved structures usually work as things. Pipes, connections, obstacles, skeletons. This is because evolved structures come about without a given purpose, but are maintained and further developed if the structure is useful.

Can we use the knowledge of our origin get some fun out of our computer? Yes! I have mentioned John Conway’s game of life earlier.

This is EvoLisa. It is a program that draws polygons and compares them to a picture. Then it changes the polygons slightly, and again compares them to a picture. Changes that make the polygons look more like the picture are kept, other changes are discarded. The result is a computer generated vector based pictures that looks like the original picture. More generations of change and selection, gives a computer generated picture that is more like the original picture. Here, selection is based on comparison to the original picture, in nature, selection is based on what organisms till survive and reproduce.

The simplest query tool ever

A colleague wanted to do a database query from a computer without any database client. He needed a tool that allowed him to type in a SQL query, and receive a sortable grid with the result set. All of these features are built-in in the .NET Framework, and it didn’t take me more than 2 minutes to do an exe file with these features using Visual Studio 2010. I used .NET 2.0 because these basic features are available in that version, and he did not want to install a newer version of the .NET Framework.

This is the user interface: A tab strip with three tabs. One for a connection string, one for the query and one for the result grid. The first two contains a textbox each, and the third contains a DataGridView control. Also, the program has a status bar with a label and a toolstrip with two buttons; one for testing the connectionstring that the user enters in the textbox of the first tab, and one for executing the query and presenting the result in the grid.

The program consist one variable and four event handlers in one form. The variable holds the result set.

Private Ds As DataSet

The first function responds to the Load event of the form. This function restores the last values that from the textboxes. This is just for user convenience.

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
    txtCn.Text = CType(Application.UserAppDataRegistry.GetValue("Cn", ""), String)
    txtQuery.Text = CType(Application.UserAppDataRegistry.GetValue("Query", ""), String)
End Sub

The second function responds to the Close event of the form. This function saves the values from the textboxes so that they can be restored (in the Load event) in the next session. Also, if needed, it disposes the dataset variable.

Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) _
Handles Me.FormClosed
    Application.UserAppDataRegistry.SetValue("Cn", txtCn.Text)
    Application.UserAppDataRegistry.SetValue("Query", txtQuery.Text)
    If Not Ds Is Nothing Then
        Ds.Dispose()
    End If
End Sub

This is the handler for the test button. It simply connects to the given data source, and tells if it succeeds or fails.

Private Sub btnTestConnection_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnTestConnection.Click
    'Jump to the connection tab (the first one).
    TabControl1.SelectedTab = tabConnection

    'Do the test.
    Me.Cursor = Cursors.WaitCursor
    Dim Success As Boolean = False
    Try
        Using Cn As New SqlClient.SqlConnection(txtCn.Text)
            Cn.Open()
            Success = (Cn.State = ConnectionState.Open)
            Cn.Close()
        End Using
    Catch ex As Exception
    End Try
    Me.Cursor = Cursors.Default
    If Success Then
        lblStatus.Text = "Connection test succeeded."
        MessageBox.Show("Connection test succeeded.", Me.Text, _
            MessageBoxButtons.OK, MessageBoxIcon.Information)
    Else
        lblStatus.Text = "Connection test failed."
        MessageBox.Show("Connection test failed.", Me.Text, MessageBoxButtons.OK, _
            MessageBoxIcon.Error)
    End If
End Sub

Finally, this is the handler for the execute button.

Private Sub btnExecute_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnExecute.Click
    'Remove the current data table as data source of the grid.
    DataGridView1.DataSource = Nothing

    If Not Me.Ds Is Nothing Then
        'If there is an old data set in memory, dispose that.
        Me.Ds.Dispose()
        'To remember that no data is present, set the variable to NULL.
        Me.Ds = Nothing
    End If
  
    'Jump to the result tab (the third one).
    TabControl1.SelectedTab = tabResult

    'Do the query and bind the result. Quick and dirty error "handling".
    Me.Cursor = Cursors.WaitCursor
    Try
        Using Cn As New SqlClient.SqlConnection(txtCn.Text)
            Cn.Open()
            Using Cmd As New SqlClient.SqlCommand(txtQuery.Text, Cn)
                Using Da As New SqlClient.SqlDataAdapter(Cmd)
                    Ds = New DataSet()
                    Da.Fill(Ds)
                    If Ds.Tables.Count > 0 Then
                        DataGridView1.DataSource = Ds.Tables(0)
                        If Ds.Tables.Count > 1 Then
                            Me.Cursor = Cursors.Default
                            MessageBox.Show("More than one dataset was returned.", "Query", _
                                MessageBoxButtons.OK, MessageBoxIcon.Information)
                        End If
                    Else
                        Me.Cursor = Cursors.Default
                        MessageBox.Show("No dataset was returned.", "Query", _
                            MessageBoxButtons.OK, MessageBoxIcon.Information)
                    End If
                End Using
            End Using
            Cn.Close()
        End Using
        lblStatus.Text = "Success."
    Catch ex As Exception
        lblStatus.Text = "Failed. " & ex.Message
            Me.Cursor = Cursors.Default
        MessageBox.Show(ex.Message, "Failed", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
    Me.Cursor = Cursors.Default
End Sub

So, making a personal query tool doesn’t have to take more than a couple of minutes in .NET.

ASP.NET 4.0: Diagrams

To get your hands on this new and cool feature, create an ASP.NET 4.0 application or web site from within Visual Studio 2010. Check the Data section of the Toolbox window for a new control called Chart. Dragging out a Chart onto a web page creates the following code:

<asp:Chart ID="Chart1" runat="server">
  <Series>
    <asp:Series Name="Series1">
  </asp:Series>
  </Series>
    <ChartAreas>
      <asp:ChartArea Name="ChartArea1">
    </asp:ChartArea>
  </ChartAreas>
</asp:Chart>

There is a huge amount of properties available for the chart. They control the look of the chart, the chart type among other things. I don’t have any databases installed on this computer, so to get some data to do a chart from; I connect the control to a data source that represents the system database master. I use the following query to get a bunch of large numbers:

SELECT [name],[number] FROM dbo.spt_values WHERE [number]>17000

I use number as Y value member.

This is what I have to do to get the fully functional chart! Fooling around with chart types and visual properties is dangerously amusing.

If you haven’t got a database server at all, you can quickly create an object data source in Visual Basic, and assign that to your chart. Connection this code…

Public Class MyChartData

    Private mValue As Integer

    Public Sub New(ByVal Value As Integer)
        Me.mValue = Value
    End Sub

    Public ReadOnly Property Value() As Integer
        Get
            Return Me.mValue
        End Get
    End Property

    Public Shared Function GetItems() As MyChartData()
        Dim Ret As New List(Of MyChartData)()
        Ret.Add(New MyChartData(10))
        Ret.Add(New MyChartData(20))
        Ret.Add(New MyChartData(15))
        Ret.Add(New MyChartData(25))
        Return Ret.ToArray()
    End Function

End Class

…gives you this beautiful result:

Ah, the simplicity! Aaaaah, the power!

Lite tramsande med GDI+ i Visual Basic

Detta ser inte speciellt vackert ut, men jag är mycket imponerad över vad man kan göra med namnrymden System.Drawing och lite GDI+ i Visual Basic.

Detta är några futtiga kodrader som ritar på två image-objekt. Det ena ritas ny grafik på ovanpå den befintliga (lite sinuskurvor), och den andra bilden rensas innan en gul boll, en svart text och en vit text ritas på. Innan bilden med sinuskurvorna sparas, ritas bilden med texterna och bollen ovanpå den första. Om inte annat kan man fundera på vilka möjligheter System.Drawing egentligen har.

The ups and downs of Visual Studio 2010: Fonts and scaling

The first time I head of the zoom feature of VS2010 was in a talk by Dag König at Microsoft. The level of readability is a very important question for me, and the font rendering of Windows (Clear Type) is superb compared to the blurry font rendering that Macintosh has. The big question, does the zoom feature affect the font rendering of the text editor? To the left, Visual Studio 9 with Consolas 8. To the right, Visual Studio 2010 with Consolas 8.

VS2010 still uses clear type, and the readability is still there. The hue is slightly reduced, if the anti aliasing is too gray, the text will appear blurry as it does on a Macintosh that only uses a gray scale for smoothing edges. The upper side of reducing the hue is that smoothing works better with text in different colors.  In VS2010, the default color for a class keyword in Visual Basic is cyan as opposed to black in VS9.

And the zooming feature: Hold down Ctrl and use your mouse wheel. Not a feature I use every day – I use a font size that I can read without zooming, but really cool to use in presentations.

The .NET Framework lets you control how text is rendered in your programs. The property of the Graphics object you use to control this is called TextRenderingHint. Examine this code:

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) _
    Handles Me.Paint
    Using B As New System.Drawing.Bitmap(300, 300)
        Using G As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(B)
            Using F As New System.Drawing.Font("Consolas", 10)
                G.FillRectangle(Brushes.White, 0, 0, 300, 300)

                'Regular smoothing
                G.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
                G.DrawString("Hello", F, Brushes.Black, 10, 10)

                'Regular smoothing with grid fit
                G.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
                G.DrawString("Hello", F, Brushes.Black, 10, 25)

                'Clear Type smoothing with grid fit
                G.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
                G.DrawString("Hello", F, Brushes.Black, 10, 40)

            End Using
        End Using
        e.Graphics.DrawImage(B, 0, 0)
    End Using
End Sub

The option called AntiAlias renders text in a similar way to the Macintosh. The text appears blurry, but the outcome has true proportions, meaning that what you see on screen is a blurrier version of what you would see on a printed version. This option works best in high resolutions and for print previewing.

The AntiAliasGridFit makes the text less blurry, because letters align to the pixel grid of the screen. The downside is that character spacing is incorrect, but readability is much higher. This option works best with CRT screens.

The ClearTypeGridFit also aligns characters to the pixel grid, but it uses clear type. This option works best with a flat screen.

The output from the above code is shown here:

The ups and downs of Visual Studio 2010: Call Hierarchy

The function that finds all references to a function or a variable has been in Visual Studio for a few versions now. VS2010 has a similar feature called Call Hierarchy. Right click on any function definition or function call, and click View Call Hierarchy. This shows the Call Hierarchy window with a tree structure that displays what other functions are called from the function you clicked on, and who is calling it. This can help discover unused code and understanding the call stack of a program. In C#, not in Visual Basic. The View Call Hierarchy isn’t there if you right click on a Visual Basic function in VS2010 Beta 2. A quick look at Microsoft Connect tells me that the subject has been brought up, but nothing else has happened yet.

One thing that does work, is the automated generation of sequence diagrams. VS2010 not only does this automatically, but the output is also editable. Objects on the diagram can be resized, moved or deleted, and new items can be added. All you have to do is click Generate Sequence Diagram.

Make a HTML gallery from your photos

The latest feature in PhotoName: Make a HTML gallery from a bunch of photos!

Download PhotoName from here. If you have a previous version installed, remember to uninstall that first (from the Windows Control Panel).

Categories: General

Tags: PhotoName



En kopp kaffe!

Bjud mig på en kopp kaffe (20:-) som tack för bra innehåll!

Bjud på en kopp kaffe!

Om...

Kontaktuppgifter, med mera, finns här.

Följ mig

Twitter Instagram
GitHub RSS

Public Service

Folkbildning om public service.

Hem   |   linktr.ee/hesselbom   |   winsoft.se   |   80tal.se   |   Filmtips