public TiffCubeReader(string FilepathWildcard, IFilenameDateParser FilenameDateParserObject, DateTime?MinDate, DateTime?MaxDate)
        {
            m_FileWildCard       = FilepathWildcard;
            m_FilenameDateParser = FilenameDateParserObject;
            m_MinDateToRead      = MinDate;
            m_MaxDateToRead      = MaxDate;

            PopulateFilenamesAndDates();
            if (m_FileDates.Count > 0)
            {
                PopulateRasterProperties();
            }
        }
        // see also https://www.codeproject.com/Articles/14465/Specify-a-Configuration-File-at-Runtime-for-a-C-Co


        private TSModelRunner(IFilenameDateParser _parser, TSIModelConfig cfg)
        {
            _fnParser = _parser;
            //var set = Properties.Settings.Default;
            //System.Console.WriteLine("Looking for files in " + m_FileWildCard);
            //var d = new System.Diagnostics.DefaultTraceListener();

            _maxReader = new TiffCubeReader(cfg.dataPathConfig.MaxTempFiles, _fnParser,
                                            cfg.modelRunConfig.ReadFromDate, cfg.modelRunConfig.ReadToDate);
            var nMax = _maxReader.Filenames.Count;

            Console.WriteLine("Looking for max temp files in " + cfg.dataPathConfig.MaxTempFiles +
                              " - found " + nMax.ToString());
            _minReader = new TiffCubeReader(cfg.dataPathConfig.MinTempFiles, _fnParser,
                                            cfg.modelRunConfig.ReadFromDate, cfg.modelRunConfig.ReadToDate);
            var nMin = _minReader.Filenames.Count;

            Console.WriteLine("Looking for min temp files in " + cfg.dataPathConfig.MinTempFiles +
                              " - found " + nMin.ToString());

            if (nMax == 0 || nMin == 0)
            {
                throw new ArgumentException("Can't continue without data");
                // I don't see any reason not to continue if the numbers for day and night aren't actually equal
            }
            if (!_maxReader.GeoTransform.SequenceEqual(_minReader.GeoTransform))
            {
                throw new ArgumentException("max and min temp image transforms do not match!");
            }
            if (!GDAL_Operations.GetGeoTransform(cfg.dataPathConfig.MaskFile).SequenceEqual(_maxReader.GeoTransform))
            {
                throw new ArgumentException("Land-sea mask doesn't match images!");
            }
            if (!System.IO.Directory.Exists(cfg.dataPathConfig.OutputFolder))
            {
                System.IO.Directory.CreateDirectory(cfg.dataPathConfig.OutputFolder);
            }
            _cfg = cfg;
        }
        static List <Tuple <string, DateTime> > GetFilenamesAndDates(string filenamePath, IFilenameDateParser filenameParser)
        {
            string _dir       = System.IO.Path.GetDirectoryName(filenamePath);
            string _fnPattern = System.IO.Path.GetFileName(filenamePath);
            // add in new parser classes for different file formats

            List <string> _files = System.IO.Directory.GetFiles(_dir, _fnPattern).ToList();
            List <Tuple <string, DateTime> > _fileDates =
                _files.Select(fn => new Tuple <string, DateTime?>(fn, filenameParser.TryParseFilenameDate(fn)))
                .Where(tpl => tpl.Item2.HasValue)
                .Select(tpl => new Tuple <string, DateTime>(tpl.Item1, tpl.Item2.Value))
                .ToList();

            // sort the list of filename/date pairs by date
            _fileDates.Sort((x, y) => x.Item2.CompareTo(y.Item2));
            return(_fileDates);
        }