MapInfo Pro

Expand all | Collapse all

MapInfo Monday: Creating a Dynamic GIFF using Python

  • 1.  MapInfo Monday: Creating a Dynamic GIFF using Python

    Posted 11-23-2020 10:50
    Happy #MapInfo​Monday

    I almost forgot about my post for today but I certainly didn't want to let you down.

    This time I had a look at the data that recently had been made freely available by the Danish Meteorological Institute. I downloaded the lightning data from DMI's lightning detector network. It holds lightning data from back in 2002 up til now.

    A quick query of the data showed me a single day back in 2002 where more than 100,000 bolts of lightning occurred across Denmark.

    So I queried the data from June 18 in 2002 and extracted the observation time from the combined observation data time string. In the map below, you can see all the observations throughout the day.

    But in order to get a better understanding of when the observations happened, I created a small Python script that would extract the observation for every 15 minutes, show them on the map, and export this as a single image.

    All these individual images, the Python script will combine into a dynamic GIFF which shows how the lightning storm moves across Denmark.

    At the top left corner, I inserted a point and labeled it with a time stamp. This time is updated for every hour and the time can so be seen on the image and in the final GIFF.

    Here's my Python script
    import time
    import os
    from System import Enum
    from MapInfo.Types import *
    from MapInfo.Types.Data import *
    import imageio
    
    #Get the map window
    map = pro.Maps[0]
    #Get the table to use
    table = pro.Catalog.Tables['Lightnings_20020618']
    path = os.path.dirname(table.FullPath)
    path = os.path.join(path, '20020618.gif')
    #print('gif path: ' + path)
    
    #loop through the day
    with imageio.get_writer(path, mode='I') as writer:
        #loop through the hours
        for nHour in range(24):  #should be 24
            #Loop the 15 minute intervals of each hour
            for nMinute in [0,15,30,45]:
                tFrom = (2002, 6, 18, nHour, nMinute, 0, 0, 0, 0)
                sFrom = time.asctime(tFrom)[11:16]
                if nMinute == 45:
                    if nHour == 23:
                        nHour = 0
                    else:
                        nHour = nHour + 1
                    nMinute = 00
                else:
                    nHour = nHour
                    nMinute = nMinute + 15
                    
                tTo = (2002, 6, 18, nHour, nMinute, 0, 0, 0, 0)
                sTo = time.asctime(tTo)[11:16]
                print("{}: {}-{}".format(pro.EvalMapBasicCommand('Time(24)'), sFrom, sTo))
                
                #Build SQL string
                sSQL = 'Select * From {} As "t" Where t.OBSERVED_TIME >= "{}"'.format(table.Alias, sFrom)
                if sTo != "00:00":
                    sSQL = sSQL + 'And t.OBSERVED_TIME < "{}"'.format(sTo) 
                    
                sSQL = sSQL + ' Into _temp noselect'
                #print(sSQL)
                pro.RunMapBasicCommandEx(sSQL)
                map.Layers.AddLayer('_temp', 1)
                
                #Update the timestamp
                if sFrom[3:5] == "00":
                    sUpdate = 'Update Time_Title Set TimeStamp = "{}"'.format(sFrom)
                    pro.RunMapBasicCommandEx(sUpdate)
                    pro.RunMapBasicCommandEx("Commit Table Time_Title")
                
                #Export the map window to an image file
                fileName = pro.EvalMapBasicCommandEx('TempFileName$("")')
                sCmd = 'Save Window {} As "{}" Type "PNG" Width 19.0235 Units "cm" Height 14.7637 Units "cm" Resolution 120'.format(map.WindowInfo.WindowId, fileName)
                pro.RunMapBasicCommandEx(sCmd)
    
                #Add the map image to the dynamic GIFF
                image = imageio.imread(fileName)
                writer.append_data(image)
                pro.RunMapBasicCommandEx('Kill "{}"'.format(fileName))

    In MapInfo Pro v2019.3, I used the Python console to write and execute my script.

    From the Python Console, I can use Ctrl + Enter to execute the script.

    As the script starts selecting the observations from the morning hours, the bolts of lightning start appearing on the west side of Denmark.

    The script deletes the individual map images as they get added to the GIFF which means that the final result is a single GIFF combined from the 24 * 4 time intervals across the day.

    Here's the final GIFF.

    The above method can be used to visualize any data that has time information to it.

    I hope you found this interesting. Stay tuned for more #MapInfoMonday tips next week


    ------------------------------
    Peter Horsbøll Møller
    Principal Presales Consultant | Distinguished Engineer
    Precisely | Trust in Data
    ------------------------------


  • 2.  RE: MapInfo Monday: Creating a Dynamic GIFF using Python

    Posted 11-27-2020 09:10
    Edited by Peter Horsbøll Møller 12-01-2020 10:13
      |   view attached
    I have been asked to share a bit more details on how to create this in MapInfo Pro.

    First, let me state that the script I have shared does require MapInfo Pro v2019.3.

    So I have attached a zip file to this response holding the data and the Python script that I used.

    Now even though MapInfo comes with Python preinstalled these days including a number of often-used Python libraries, it's still necessary to install a couple of other modules used in my script for creating the GIFF.

    Here's how you do that:
    1. Open the Command window by typing "CMD" in the Search field next to the Start button in Windows and hit Enter.

    2. This will open the Command window

    3. Now type: CD C:\Program Files\MapInfo\Professional\Python37, where C:\Program Files\MapInfo\Professional is the MapInfo Pro installation folder. In my case, that folder is C:\MapInfo\Pro x64\19.0. Then hit Enter.

    This moves you into the Python folder for MapInfo Pro which is necessary to be able to install the needed Python libraries.

    4. Now it's time to install the libraries. This is done by entering two statements, one at a time. Each statement will download and install a Python library. These are the statements:
    • python -m pip install imageio
    • python -m pip install Pillow

    If you don't already have these modules installed, you can see how they get downloaded and installed. In my case, you can see that the libraries already are installed (requirements are already satisfied.).

    5. Close the Command window either through the X in the order or by running the Exit command.

    Now the Python requirements are in place.

    Unzip the attached file.

    Start MapInfo Pro, and open the table Lightnings_20020618 from the attached zip file into a map window. You can also add a background map if you want to. Note that the extent and size of the map are used for the images in your GIFF. Now turn off the visibility of the Lightning table as the script will add a part of the bolts of lightning to the map as it runs through the day.

    Open the Python console from the Tool Windows dropdown.

    Open the file Visulize Lightnings.py in a text editor, copy the content, and paste it into the Python Console.

    As the script prints some messages to the Message window I'd recommend opening that window before running the script. Otherwise, it might open and change the size of your map window. You can open the Message window from the Tool Windows dropdown.

    You also need to open the table Time_Title from the attached zip file. It shows a point that you should label with the column TimeStamp. You can also change the label properties to make it stand out on your background. The point can be moved to any location you want. Save changes to the table when done.

    Now click inside the Python Console to give this window focus, and then Hit Ctrl + Enter on your keyboard to start the script.

    As it loops through the day, you will see the bolts of lightning appear and move across the map. In the Message window, you can see how far it is in the process.

    When the script has finished, you can find the final GIFF, called 20020618.gif, in the same folder as you put the table Lightnings_20020618.

    ------------------------------
    Peter Horsbøll Møller
    Principal Presales Consultant | Distinguished Engineer
    Precisely | Trust in Data
    ------------------------------

    Attachment(s)

    zip
    Visualize Lightnings.zip   10.41 MB 1 version


  • 3.  RE: MapInfo Monday: Creating a Dynamic GIFF using Python

    Posted 12-09-2020 12:44
    One other tip: You can run the python script directly without using the python console.

    From the Home tab choose the File Open dropdown and click on "Program" or press Ctrl+U
    Navigate to Visulize Lightnings.py and it will run.

    This is the same way you can run a mapbasic .mbx program.

    ------------------------------
    Bob Fortin
    Software Architect and Distinguished Engineer
    MapInfo Pro Development Team
    ------------------------------