OpenTemp.cs

This page contains the main body and utility methods of OpenTemp.cs
Use the links below for the input methods:

ParseStations()
ParseGHCNv2()

Use the links below for the analysis methods:

CalculateMonthlyAverages()
CalculateSeriesOffsets()
_MeshUSALower48()

Use these links for the ouput methods:

WriteStationResults()
WriteCellStationResults()
WriteCellInfo()
WriteSeriesOffsets()
WriteMonthlyResults()
WriteYearlyResults()

// =====
// Copyright 2007 John Van Vliet, all rights reserved
// Here’s my simple license, soon to be replaced by a proper license.
// What you can do:
// - read the code
// - play with the code
// - run the code
// - modify the code
// What you can’t do:
// - re-publish the original code or any modified versions
// =====

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Text;

namespace OpenTemp
{
    /// <summary>
    /// The OpenTemp program processes station, temperature, and region files to generate temperature trends.
    /// </summary>
    /// <remarks>
    /// <para>The program is currently hard-coded for the USA lower-48.</para>
    /// </remarks>
    class OpenTemp
    {
        string _dataFile;
        string _stationsFile;
        static string _outputStationFile;
        static string _outputSeriesOffsetsFile;
        static string _outputCellFile;
        static string _outputCellStationsFile;
        static string _outputMonthlyFile;
        static string _outputYearlyFile;
        static string _logFile;
        static GraphicsPath _regionGraphicsPath;
        static StreamWriter _logSW;

        Dictionary<string, Station> _stations;
        List<Cell> _cells;
        SortedList<DateTime, float> _monthlyAverages;

        float _cellSize = 0.5f;             // mesh size in degrees of latitude and longitude
        float _averagingRadius = 1000.0f;   // number of kilometers for averaging region
        /// <summary>
        /// Program entry point. Process command line parameters and coordinate processing.
        /// </summary>
        static int Main(string[] args)
        {
            string dataFile = “”;           // Name of the GHCN file to read
            string stationsFile = “”;       // Name of the file with a list of stations
            bool writeStations = false;
            bool writeCells = false;
            bool writeCellStations = false;
            bool writeMonthly = false;
            bool writeYearly = false;
            bool useOffsets = false;
            int status;

            // Output file names
            DateTime now = DateTime.Now;
            _outputStationFile       = “station.csv”;
            _outputCellFile          = “cell.csv”;
            _outputCellStationsFile  = “cellstation.csv”;
            _outputSeriesOffsetsFile = “offsets.csv”;
            _outputMonthlyFile       = “monthly.csv”;
            _outputYearlyFile        = “yearly.csv”;
            _logFile                 = “opentemp.log”;

            // Open log file
            using (_logSW = new StreamWriter(_logFile, false))
            {

                // Parse command-line arguments
                foreach (string arg in args)
                {
                    if (arg.StartsWith(@”/ghcn=”))
                    {
                        dataFile = arg.Substring(6);
                    }
                    else if (arg.StartsWith(@”/stn=”))
                    {
                        stationsFile = arg.Substring(5);
                    }
                    else if (arg.StartsWith(@”/offset”))
                    {
                        useOffsets = true;
                    }
                    else if (arg.StartsWith(@”/os”))
                    {
                        writeStations = true;
                    }
                    else if (arg.StartsWith(@”/ocs”))        // note: must come before “-oc” because of StartsWith()
                    {
                        writeCellStations = true;
                    }
                    else if (arg.StartsWith(@”/oc”))
                    {
                        writeCells = true;
                    }
                    else if (arg.StartsWith(@”/om”))
                    {
                        writeMonthly = true;
                    }
                    else if (arg.StartsWith(@”/oy”))
                    {
                        writeYearly = true;
                    }
                    else
                    {
                        OpenTemp.WriteLine(string.Format(”!!! Unrecognized command-line parameter ‘{0}’”, arg));
                    }
                }
                if ((dataFile.Length == 0) || (stationsFile.Length == 0))
                {
                    OpenTemp.WriteLine(”Usage:”);
                    OpenTemp.WriteLine(”   GHCNParser /ghcn=[GHCN] /stn=[stations] /rgn=[region] {/offset} {/os} {/oc} {/ocs} {/oo} {/om} {/oy}”);
                    OpenTemp.WriteLine(”     where”);
                    OpenTemp.WriteLine(”       [GHCN]     is the name of the GHCN data file to read”);
                    OpenTemp.WriteLine(”                  (GHCNv2 monthly data files are supported)”);
                    OpenTemp.WriteLine(”       [stations] is the name of a file with a list of stations to analyze”);
                    OpenTemp.WriteLine(”                  (one station per line with: stationID, latitude, longitude)”);
                    OpenTemp.WriteLine(”       [rgn]      NOT IMPLEMENTED: is the name of a file that defines the regions to be analyzed”);
                    OpenTemp.WriteLine(”                  (currently the program is hard-coded to analyze the USA lower 48)”);
                    OpenTemp.WriteLine(”       {/offset}  true to calculate and use series offsets to the region average”);
                    OpenTemp.WriteLine(”                  (offsets will be written to offsets.csv)”);
                    OpenTemp.WriteLine(”       {/os}      include this flag to write station details for all requested stations”);
                    OpenTemp.WriteLine(”       {/oc}      include this flag to write cell data for the region (cell location and size)”);
                    OpenTemp.WriteLine(”       {/ocs}     include this flag to write cell-stations (stations that can affect each cell)”);
                    OpenTemp.WriteLine(”       {/om}      include this flag to write monthly averages for each region”);
                    OpenTemp.WriteLine(”       {/oy}      include this flag to write yearly averages for each region”);
                    OpenTemp.WriteLine();
                    OpenTemp.WriteLine(”Results will be written to data files with the following names:”);
                    OpenTemp.WriteLine(”   monthly.csv contains monthly overall averages for each region”);
                    OpenTemp.WriteLine(”   yearly.csv  contains yearly overall averages for each region”);
                    OpenTemp.WriteLine(”   station.csv contains monthly readings for every station in a convenient format”);
                    OpenTemp.WriteLine(”   cell.csv contains cell information for the entire region”);
                    OpenTemp.WriteLine(”   cellstation.csv contains cell-station interaction results”);
                    OpenTemp.WriteLine(”   offsets.csv contains the static offsets applied to each series”);
                    OpenTemp.WriteLine(”   opentemp.log contains a complete processing log (same as console output)”);
                    OpenTemp.WriteLine();
                    OpenTemp.WriteLine(”Notes:”);
                    OpenTemp.WriteLine(”   - Each output file is written only if the appropriae /o option is used”);
                    OpenTemp.WriteLine(”   - If the /offset option is used:”);
                    OpenTemp.WriteLine(”       - Monthly and yearly data includes a static offset applied to each series”);
                    OpenTemp.WriteLine(”         (Offset is equal to the average difference between the series and the monthly averages)”);
                    OpenTemp.WriteLine(”       - The offsets.csv file is written if the /offset option is used”);
                    Console.ReadKey();
                    return -1;
                }

                // Parsing object
                OpenTemp parser = new OpenTemp(dataFile, stationsFile);

                // Parse stations file
                if (writeStations || writeCellStations || writeYearly || writeMonthly || useOffsets)
                {
                    status = parser.ParseStations();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when parsing stations file”, status));
                        Console.ReadKey();
                        return status;
                    }
                }
                // Parse data file
                if (writeMonthly || writeYearly || writeStations || writeCellStations || useOffsets)
                {
                    status = parser.ParseGHCNv2();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when parsing data file”, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Write station results
                if (writeStations)
                {
                    status = parser.WriteStationResults();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when writing station output file”, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Generate mesh
                if (writeCells || writeCellStations || writeYearly || writeMonthly || useOffsets)
                {
                    status = parser._MeshUSALower48();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when generating mesh for the USA lower 48″, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Write cell information to file
                if (writeCells)
                {
                    status = parser.WriteCellInfo();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when writing cell data”, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Write cell-stations to file
                if (writeCellStations)
                {
                    status = parser.WriteCellStationResults();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when writing cell-station results”, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Compute overall average for every month
                if (writeMonthly || writeYearly || useOffsets)
                {
                    status = parser.CalculateMonthlyAverages(false);
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when calculating overall monthly averages”, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Compute overall offset for each series
                // (Compensates for the introduction or removal of stations with average temperatures different than the overall average)
                if (writeMonthly || writeYearly || useOffsets)
                {
                    status = parser.CalculateSeriesOffsets();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when calculating offsets for each series”, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Write series offsets
                if (useOffsets)
                {
                    status = parser.WriteSeriesOffsets();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when writing series offsets file”, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Re-calculate overall average for every month including series offsets
                if (useOffsets)
                {
                    status = parser.CalculateMonthlyAverages(true);
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when calculating overall monthly averages”, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Write monthly results
                if (writeMonthly)
                {
                    status = parser.WriteMonthlyResults();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when writing monthly output file”, status));
                        Console.ReadKey();
                        return status;
                    }
                }

                // Write yearly results
                if (writeYearly)
                {
                    status = parser.WriteYearlyResults();
                    if (status < 0)
                    {
                        OpenTemp.WriteLine(”!!!”);
                        OpenTemp.WriteLine(string.Format(”ERROR <{0}> when writing yearly output file”, status));
                        Console.ReadKey();
                        return status;
                    }
                }
                // Done
                //parser.Close();
                OpenTemp.Write(”Press any key to continue”);
                Console.ReadKey();
                return 0;
           
            } // using StreamWriter
        }

        /// <summary>
        /// Append a string to the console output and log file.
        /// </summary>
        internal static void Write(string msg)
        {
            Console.Write(msg);
            _logSW.Write(msg);
        }

        /// <summary>
        /// Append a string to the console output and log file, followed by a new line.
        /// </summary>
        internal static void WriteLine(string msg)
        {
            Console.WriteLine(msg);
            _logSW.WriteLine(msg);
        }

        /// <summary>
        /// Append a newline to the console output and log file.
        /// </summary>
        internal static void WriteLine()
        {
            Console.WriteLine();
            _logSW.WriteLine();
        }
       
        /// <summary>
        /// Constructor.
        /// </summary>
        OpenTemp(string dataFile, string stationsFile)
        {
            _dataFile = dataFile;
            _stationsFile = stationsFile;

            _stations = new Dictionary<string, Station>();
            _cells = new List<Cell>();
            _monthlyAverages = new SortedList<DateTime, float>();
        }