using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Data;
using DotSpatial.Data;

namespace SMAT_CE
{
    class DailyPMCommonClass
    {
        public static DateTime _beginTime;//记录开始时间
        public static DateTime _endTime;//记录结束时间
        //----结果文件夹-------------
        public static string _resultFilePath = "";
        public static PM25Monitors ClonePM25Monitors(PM25Monitors pm25MonitorsBase)
        {
            PM25Monitors pmClone=new PM25Monitors()
            {
                year          =pm25MonitorsBase.year          ,
bPM25         =pm25MonitorsBase.bPM25         ,
fPM25         =pm25MonitorsBase.fPM25         ,
epaFlag       =pm25MonitorsBase.epaFlag       ,
userFlag      =pm25MonitorsBase.userFlag      ,
completionCode=pm25MonitorsBase.completionCode,
rank98        =pm25MonitorsBase.rank98        ,
percentile_98 =pm25MonitorsBase.percentile_98 ,
bBlankmass    =pm25MonitorsBase.bBlankmass    ,
bCrustal      =pm25MonitorsBase.bCrustal      ,
bEC           =pm25MonitorsBase.bEC           ,
bNH4          =pm25MonitorsBase.bNH4          ,
bOCMmb        =pm25MonitorsBase.bOCMmb        ,
bSO4          =pm25MonitorsBase.bSO4          ,
bNO3          =pm25MonitorsBase.bNO3          ,
bNO3r         =pm25MonitorsBase.bNO3r         ,
bWater        =pm25MonitorsBase.bWater        ,
bSalt         =pm25MonitorsBase.bSalt         ,
bDON          =pm25MonitorsBase.bDON          ,
fBlankmass    =pm25MonitorsBase.fBlankmass    ,
fCrustal      =pm25MonitorsBase.fCrustal      ,
fEC           =pm25MonitorsBase.fEC           ,
fNH4          =pm25MonitorsBase.fNH4          ,
fOCMmb        =pm25MonitorsBase.fOCMmb        ,
fSO4          =pm25MonitorsBase.fSO4          ,
fNO3r         =pm25MonitorsBase.fNO3r         ,
fWater        =pm25MonitorsBase.fWater        ,
fSalt         =pm25MonitorsBase.fSalt         ,
rrfCrustal    =pm25MonitorsBase.rrfCrustal    ,
rrfEC         =pm25MonitorsBase.rrfEC         ,
rrfNH4        =pm25MonitorsBase.rrfNH4        ,
rrfOC         =pm25MonitorsBase.rrfOC         ,
rrfSO4        =pm25MonitorsBase.rrfSO4        ,
rrfNO3        =pm25MonitorsBase.rrfNO3        ,
rrfWater      =pm25MonitorsBase.rrfWater      ,
rrfSalt       =pm25MonitorsBase.rrfSalt       
                 
            };
            return pmClone;
        }
        public static bool DailyVNA(ref Dictionary<string, NeighborInfoDaily> dicNeighborDistance, string quarter, string pollutantName, string interpolationMethod, double distanceInterpolation, ref double dVNA, Dictionary<string, float> fsoutStringSpecies, Dictionary<string, Monitors> dicSpeciesMonitors)
        {
            try
            {
                double distanceSpecies = 0, distanceSumSpecies = 0, vnaSum = 0;
                int n = 0;
                Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>();
                switch (interpolationMethod)
                {
                    case "Equal Weighting of Monitors":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                //------------10个------------
                                #region
                                if (pollutantName == "SO4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].so4))) continue;
                                if (pollutantName == "NO3r" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3r))) continue;
                                if (pollutantName == "OCb" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ocb))) continue;
                                if (pollutantName == "EC" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ec))) continue;
                                if (pollutantName == "CRUSTAL" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].crustal))) continue;
                                if (pollutantName == "SALT" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].salt))) continue;
                                if (pollutantName == "NO3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3))) continue;
                                if (pollutantName == "NH4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].nh4))) continue;
                                if (pollutantName == "DON" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].don))) continue;
                                #endregion
                                if (dicNeighborDistance.ContainsKey(s.Key))
                                {
                                    dicNeighborDistance[s.Key].distance = s.Value;
                                    if (dicNeighborDistance[s.Key].lstPollutants == null)
                                        dicNeighborDistance[s.Key].lstPollutants = new List<string>();
                                    dicNeighborDistance[s.Key].lstPollutants.Add(pollutantName);
                                }
                                else
                                {
                                    dicNeighborDistance.Add(s.Key, new NeighborInfoDaily()
                                    {
                                        distance = s.Value,
                                        lstPollutants = new List<string>(),
                                    });
                                    dicNeighborDistance[s.Key].lstPollutants.Add(pollutantName);
                                }
                                n++;
                                switch (pollutantName)
                                {
                                    //---------10个-------
                                    #region
                                    case "SO4":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].so4;
                                        break;
                                    case "NO3r":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3r;
                                        break;
                                    case "OCb":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ocb;
                                        break;
                                    case "EC":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ec;
                                        break;
                                    case "CRUSTAL":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].crustal;
                                        break;
                                    case "SALT":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].salt;
                                        break;
                                    case "NO3":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3;
                                        break;
                                    case "NH4":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].nh4;
                                        break;
                                    case "DON":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].don;
                                        break;
                                    #endregion
                                }
                            }
                            catch { }
                        }
                        try
                        {
                            dVNA = vnaSum / n;
                        }
                        catch { }
                        #endregion
                        break;
                    case "Inverse Distance Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                //------------10个------------
                                #region
                                if (pollutantName == "SO4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].so4))) continue;
                                if (pollutantName == "NO3r" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3r))) continue;
                                if (pollutantName == "OCb" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ocb))) continue;
                                if (pollutantName == "EC" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ec))) continue;
                                if (pollutantName == "CRUSTAL" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].crustal))) continue;
                                if (pollutantName == "SALT" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].salt))) continue;
                                if (pollutantName == "NO3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3))) continue;
                                if (pollutantName == "NH4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].nh4))) continue;
                                if (pollutantName == "DON" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].don))) continue;
                                #endregion
                                if (dicNeighborDistance.ContainsKey(s.Key))
                                {
                                    dicNeighborDistance[s.Key].distance = s.Value;
                                    if (dicNeighborDistance[s.Key].lstPollutants == null)
                                        dicNeighborDistance[s.Key].lstPollutants = new List<string>();
                                    dicNeighborDistance[s.Key].lstPollutants.Add(pollutantName);
                                }
                                else
                                {
                                    dicNeighborDistance.Add(s.Key, new NeighborInfoDaily()
                                    {
                                        distance = s.Value,
                                        lstPollutants = new List<string>(),
                                    });
                                    dicNeighborDistance[s.Key].lstPollutants.Add(pollutantName);
                                }
                                distanceSpecies = s.Value == 0 ? 1 : 1.0000 / s.Value;
                                distanceSumSpecies += distanceSpecies;
                                switch (pollutantName)
                                {
                                    //---------10个
                                    #region
                                    case "SO":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].so4 * distanceSpecies;
                                        break;
                                    case "NO3r":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3r * distanceSpecies;
                                        break;
                                    case "OCb":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ocb * distanceSpecies;
                                        break;
                                    case "EC":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ec * distanceSpecies;
                                        break;
                                    case "CRUSTAL":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].crustal * distanceSpecies;
                                        break;
                                    case "SALT":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].salt * distanceSpecies;
                                        break;
                                    case "NO3":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3 * distanceSpecies;
                                        break;
                                    case "NH4":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].nh4 * distanceSpecies;
                                        break;
                                    case "DON":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].don * distanceSpecies;
                                        break;
                                    #endregion
                                }
                            }
                            catch { }
                        }
                        try
                        {
                            dVNA = vnaSum / distanceSumSpecies;
                        }
                        catch { }
                        #endregion
                        break;
                    case "Inverse Distance Squared Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringSpecies)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                //------------10个------------
                                #region
                                if (pollutantName == "SO4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].so4))) continue;
                                if (pollutantName == "NO3r" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3r))) continue;
                                if (pollutantName == "OCb" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ocb))) continue;
                                if (pollutantName == "EC" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ec))) continue;
                                if (pollutantName == "CRUSTAL" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].crustal))) continue;
                                if (pollutantName == "SALT" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].salt))) continue;
                                if (pollutantName == "NO3" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3))) continue;
                                if (pollutantName == "NH4" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].nh4))) continue;
                                if (pollutantName == "DON" && (!dicSpeciesMonitors.ContainsKey(id) || !dicSpeciesMonitors[id].dicSpeciesMonitors.ContainsKey(quarter) || Double.IsNaN(dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].don))) continue;
                                #endregion
                                if (dicNeighborDistance.ContainsKey(s.Key))
                                {
                                    dicNeighborDistance[s.Key].distance = s.Value;
                                    if (dicNeighborDistance[s.Key].lstPollutants == null)
                                        dicNeighborDistance[s.Key].lstPollutants = new List<string>();
                                    dicNeighborDistance[s.Key].lstPollutants.Add(pollutantName);
                                }
                                else
                                {
                                    dicNeighborDistance.Add(s.Key, new NeighborInfoDaily()
                                    {
                                        distance = s.Value,
                                        lstPollutants = new List<string>(),
                                    });
                                    dicNeighborDistance[s.Key].lstPollutants.Add(pollutantName);
                                }
                                distanceSpecies = s.Value == 0 ? 1 : 1.0000 / Math.Pow(s.Value, 2);
                                distanceSumSpecies += distanceSpecies;
                                switch (pollutantName)
                                {
                                    //---------10个
                                    #region
                                    case "SO4":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].so4 * distanceSpecies;
                                        break;
                                    case "NO3r":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3r * distanceSpecies;
                                        break;
                                    case "OCb":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ocb * distanceSpecies;
                                        break;
                                    case "EC":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].ec * distanceSpecies;
                                        break;
                                    case "CRUSTAL":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].crustal * distanceSpecies;
                                        break;
                                    case "SALT":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].salt * distanceSpecies;
                                        break;
                                    case "NO3":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].no3 * distanceSpecies;
                                        break;
                                    case "NH4":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].nh4 * distanceSpecies;
                                        break;
                                    case "DON":
                                        vnaSum += dicSpeciesMonitors[id].dicSpeciesMonitors[quarter].don * distanceSpecies;
                                        break;
                                    #endregion
                                }
                            }
                            catch
                            {
                            }
                        }
                        try
                        {
                            dVNA = vnaSum / distanceSumSpecies;
                        }
                        catch { }
                        #endregion
                        break;
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        public static bool DailyAnalysis(BaseScenario baseScenario, SMAT_CE mats)
        {
            if (!(baseScenario.configuration is DailyPMAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                _beginTime = DateTime.Now;
                DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = (baseScenario.configuration) as DailyPMAnalysisConfiguration;
                Dictionary<string, DailyModelMonitor> dicQuarterlyPeakModel = new Dictionary<string, DailyModelMonitor>();
                string baseYear = "", futureYear = "";
                bool isSalt = false;
                //-----保存文件前先生成相应的文件夹---------------
                #region
                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);
                #endregion
                #region quarterly peak model data
                //---quarterly
                string isOK = "";
                CommonClass.CurrentLog = "Read model data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.baselineModelFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                if (dailyPMAnalysisConfiguration.dataInputD.doQuarterlyPeakModelDataInput)
                {
                    baseYear = ""; futureYear = "";
                    isOK = GetModelDataQuarterly(dailyPMAnalysisConfiguration, ref dicQuarterlyPeakModel, ref isSalt, ref baseYear, ref futureYear);
                    switch (isOK)//error message when loading file
                    {
                        case "wrongBaseline":
                            CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.baselineModelFile) + "\".";
                            CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                            return false;
                        case "wrongFuture":
                            CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.forecastModelFile) + "\".";
                            CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                            return false;
                        case "unknow":
                            CommonClass.CurrentLog = "Fail to read model data.";
                            CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                            return false;
                    }
                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doQuarterlyPeakModelData)
                    {
                        SaveQuarterlyPeakModelDataCopyDirectly(CommonClass.CurrentBaseScenario,dicQuarterlyPeakModel,isSalt);
                    }
                }
                else if (!(dailyPMAnalysisConfiguration.dataInputD.doQuarterlyPeakModelDataInput) && dailyPMAnalysisConfiguration.dataInputD.doDailyModelDataInput)
                {
                    #region read daily baseline/future model data from csv
                    baseYear = ""; futureYear = "";
                    //------------读取文件----------baseline/forecast model data 
                    Dictionary<string, Dictionary<string, List<string>>> dicBaseDays = new Dictionary<string, Dictionary<string, List<string>>>();//记录date
                    isOK = GetModelDataDailyBaseline(dailyPMAnalysisConfiguration, ref dicQuarterlyPeakModel, ref isSalt, ref baseYear, ref dicBaseDays);
                    if (!string.IsNullOrEmpty(isOK))//error message when loading file
                    {
                        CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.baselineModelFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    }
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentLog = "Finish reading model data: " + CommonClass.TotalTime + " s.";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    _beginTime = DateTime.Now;
                    CommonClass.CurrentLog = "Read model data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.forecastModelFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    isOK = GetModelDataDailyFuture(dailyPMAnalysisConfiguration, ref dicQuarterlyPeakModel, ref isSalt, ref futureYear, dicBaseDays);
                    if (!string.IsNullOrEmpty(isOK))//error message when loading file
                    {
                        CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.forecastModelFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    }
                    dicBaseDays.Clear();
                    GC.Collect();
                    #endregion
                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doQuarterlyPeakModelData)
                    {
                        SaveQuarterlyPeakModelData(CommonClass.CurrentBaseScenario, dicQuarterlyPeakModel, isSalt, baseYear, futureYear);
                    }
                    #region 注释
                    //------------增加一个变量chek，用于表示每个gridcell 的一个新季度的开始：id*100+quarter,然后根据chek对pm25降序排列
                    //----------确定每个gridcell的starting point-----
                    //---------变量x,根据chek确定每个gridcell的第一条记录，若为第一条则x=1，后面的x依次增加
                    //---------根据model data options窗体中的条件：（1）只保留满足指定的天数的季度（指定的天数每个季度可以不同）中的天，满足条件（X小于等于该季度总天数的top x percent）则markForDelete=0,反之为1.
                    //（2）若pm小于设定的最小值，则markfordelete=1
                    //（3）类似于（1）
                    //保留所有markfordelete=0的数据。注意，在计算过程中可能存在下面这种情况：季度1中的第23个值与第24个值一样，那么我们需要同时保留两者。因此，保留更低的peak value，并看他是否与删掉的数据一致。
                    //然后根据chek，pm25进行排序。降序

                    //-----求季度均值--------
                    //-----若选择的为大于指定的value，则需要确保values的最小数目要满足设定的阈值
                    #endregion
                }
                else if (!(dailyPMAnalysisConfiguration.dataInputD.doQuarterlyPeakModelDataInput) && !(dailyPMAnalysisConfiguration.dataInputD.doDailyModelDataInput)
                    && dailyPMAnalysisConfiguration.dataInputD.doInputfromCmaq)
                {
                    GetModelDataFromCMAQ(dailyPMAnalysisConfiguration);
                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doQuarterlyPeakModelData)
                    {
                    }
                }
                _endTime = DateTime.Now;
                CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                CommonClass.CurrentLog = "Finish reading model data: " + CommonClass.TotalTime + " s.";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                //change project - write in dictionary (lat,long to lambert) - for draw map
                DataTable dt = new DataTable();
                dt.Columns.Add("id");
                dt.Columns.Add("lat");
                dt.Columns.Add("long");
                foreach (KeyValuePair<string, DailyModelMonitor> keyvalue in dicQuarterlyPeakModel)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = keyvalue.Key;
                    dr[1] = keyvalue.Value.lat;
                    dr[2] = keyvalue.Value.longitude;
                    dt.Rows.Add(dr);
                }
                mats.changeProject(dt, "USA");
                #endregion
                //_endTime = DateTime.Now;
                //CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                //CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish reading model data: " + CommonClass.TotalTime + " s.");
                //CommonClass.CurrentLog = "Finish reading model data: " + CommonClass.TotalTime + " s";

                //CommonClass.CurrentBaseScenario.log.lstLog.Add("Loading FRM and STN/Improve monitor data.");
                //CommonClass.CurrentLog = "Loading FRM and STN/Improve monitor data....";
                _beginTime = DateTime.Now;
                #region standard analysis
                #region step1: official FRM monitor data
                List<string> dicDesignValuePeriod = new List<string>();
                int startYearPM = Convert.ToInt32(dailyPMAnalysisConfiguration.pm25CalculationOptionsD.officialPM25StartYear);
                int endYearPM = Convert.ToInt32(dailyPMAnalysisConfiguration.pm25CalculationOptionsD.officialPM25EndYear);
                if (endYearPM < startYearPM + 2)
                {
                    dicDesignValuePeriod.Add(startYearPM.ToString() + "-" + endYearPM.ToString());
                }
                else
                {
                    for (int i = 0; i < endYearPM - startYearPM - 1; i++)
                    {
                        dicDesignValuePeriod.Add((startYearPM + i).ToString() + "-" + (startYearPM + i + 2).ToString());
                    }
                }
                Dictionary<string, Monitors> dicMonitorStateCounty = new Dictionary<string, Monitors>();
                Dictionary<string, Monitors> dicOfficialMonitors = new Dictionary<string, Monitors>();
                Dictionary<string, Monitors> dicOfficialPeriod = new Dictionary<string, Monitors>();
                //Dictionary<string, List<string>> dicPeriodsValue = new Dictionary<string, List<string>>();
                List<string> lstYear = null;
                List<Dictionary<string, Monitors>> lstAllYearsAllDaysPeriod = new List<Dictionary<string, Monitors>>();
                if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                {
                    for (int i = 0; i < dicDesignValuePeriod.Count; i++)
                    {
                        lstAllYearsAllDaysPeriod.Add(new Dictionary<string, Monitors>());
                    }
                }
                Dictionary<string, Dictionary<string, int>> dicComCodePeriod = new Dictionary<string, Dictionary<string, int>>();
                if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doStandardAnalysis)
                {
                    _beginTime = DateTime.Now;
                    CommonClass.CurrentLog = "Read official PM data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.officialMonitorFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    Dictionary<string, Monitors> dicOfficialPMDaily = new Dictionary<string, Monitors>();
                    isOK = GetOfficialPM(dailyPMAnalysisConfiguration, ref dicMonitorStateCounty, ref dicOfficialPMDaily);
                    if (dicOfficialPMDaily.Count <= 0 || isOK == "unknow")//error message when loading file
                    {
                        CommonClass.CurrentLog = "Fail to read official PM data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.officialMonitorFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    }
                    //else
                    //{
                    //    if (isOK == "errorRow")
                    //    {
                    //        CommonClass.CurrentLog = "There are errors in the monitor file of " + dailyPMAnalysisConfiguration.dataInputD.officialMonitorFile + ". The error rows were removed.";
                    //        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    //    }
                    //}
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentLog = "Finish reading official PM data: " + CommonClass.TotalTime + " s.";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    #region min number of DV periods
                    Dictionary<string, Monitors> dicMinNumPeriodsOfficial = new Dictionary<string, Monitors>();
                    Dictionary<string, List<string>> dicValidYear = new Dictionary<string, List<string>>();
                    //判断3年DV是否有效：末尾年的comCode为1或2，且年份都存在,默认情况下只考虑三个dv period的情况
                    //首先获取设置的开始年和结束年，然后求出dv periods的数目
                    GetValidPeriods(dailyPMAnalysisConfiguration, dicOfficialPMDaily, dicDesignValuePeriod, ref dicValidYear, ref lstAllYearsAllDaysPeriod, ref dicComCodePeriod);
                    #endregion

                    #region get monitor in model
                    Dictionary<string, string> dicOfficialMonitorInModel = new Dictionary<string, string>();
                    GetGridCellOfficialMonitor(ref dicOfficialMonitorInModel, dicQuarterlyPeakModel, dicOfficialPMDaily);
                    #endregion

                    #region select top 8 values according to pm25(descending order) for each year each quarter
                    dicOfficialMonitors = new Dictionary<string, Monitors>();
                    foreach (KeyValuePair<string, Monitors> k in dicOfficialPMDaily)
                    {
                        if (!dicValidYear.ContainsKey(k.Key)) continue;
                        dicOfficialMonitors.Add(k.Key, new Monitors()
                        {
                            id = k.Value.id,
                            type = k.Value.type,
                            lat = k.Value.lat,
                            longitude = k.Value.longitude,
                            stateName = k.Value.stateName,
                            countyName = k.Value.countyName,
                            //percentile_98 = k.Value.percentile_98,
                            //rank98 = k.Value.rank98,
                            monitorGridcell = dicOfficialMonitorInModel[k.Key],
                            dicOfficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                        });
                        foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kin in dicOfficialPMDaily[k.Key].dicOfficialPM25Daily)
                        {
                            dicOfficialMonitors[k.Key].dicOfficialPM25Daily.Add(kin.Key, new Dictionary<string, Dictionary<string, PM25Monitors>>());
                            foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> item in dicOfficialPMDaily[k.Key].dicOfficialPM25Daily[kin.Key])
                            {
                                if (!dicValidYear[k.Key].Contains(item.Key)) continue;
                                dicOfficialMonitors[k.Key].dicOfficialPM25Daily[kin.Key].Add(item.Key, item.Value.OrderByDescending(p => p.Value.bPM25).Take(8).ToDictionary(p => p.Key, p => p.Value));
                            }
                        }
                    }
                    dicOfficialPMDaily.Clear();
                    GC.Collect();

                    if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                    {
                        for (int i = 0; i < lstAllYearsAllDaysPeriod.Count; i++)
                        {
                            foreach (KeyValuePair<string, Monitors> k in lstAllYearsAllDaysPeriod[i])
                            {
                                k.Value.monitorGridcell = dicOfficialMonitorInModel[k.Key];
                                Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>> dicQ = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>();
                                foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQ in k.Value.dicOfficialPM25Daily)
                                {
                                    Dictionary<string, Dictionary<string, PM25Monitors>> dic = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                    foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kY in kQ.Value)
                                    {
                                        dic.Add(kY.Key, kY.Value.OrderByDescending(p => p.Value.bPM25).Take(8).ToDictionary(p => p.Key, p => p.Value));
                                    }
                                    dicQ.Add(kQ.Key, dic);
                                }
                                k.Value.dicOfficialPM25Daily = dicQ;
                            }
                        }
                    }
                    #endregion
                }
                #endregion

                #region step2: quarterly peak speciated monitors
                Dictionary<string, Monitors> dicUnofficialPMDaily = new Dictionary<string, Monitors>();
                Dictionary<string, Monitors> dicSpeciesDaily = new Dictionary<string, Monitors>();
                Dictionary<string, Monitors> dicSpeciatedMonitors = new Dictionary<string, Monitors>();
                Dictionary<string, Monitors> dicUnofficialPM = new Dictionary<string, Monitors>();
                Dictionary<string, Monitors> dicSpeciesFractions = new Dictionary<string, Monitors>();
                Dictionary<string, string> dicMonitorInModelFRM = new Dictionary<string, string>();
                #region unofficial PM25---FRM monitors for species fractions
                _beginTime = DateTime.Now;
                CommonClass.CurrentLog = "Read unofficial PM data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.unofficialMonitorFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                isOK = GetUnofficialPM(dailyPMAnalysisConfiguration, ref dicUnofficialPMDaily);
                if (dicUnofficialPMDaily.Count <= 0 || isOK == "unknow")//error message when loading file
                {
                    _beginTime = DateTime.Now;
                    CommonClass.CurrentLog = "Fail to read unofficial PM data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.unofficialMonitorFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    return false;
                }
                //else
                //{
                //    if (isOK == "errorRow")
                //    {
                //        CommonClass.CurrentLog = "There are errors in the monitor file of " + dailyPMAnalysisConfiguration.dataInputD.unofficialMonitorFile + ". The error rows were removed.";
                //        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                //    }
                //}
                _endTime = DateTime.Now;
                CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                CommonClass.CurrentLog = "Finish reading unofficial PM data: " + CommonClass.TotalTime + " s.";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                //iID = iType = iLat = iLong = iDate = iPM25 = iEPA = -1;
                #region  min requirement
                //判断每个季度是否满足每个季度的最小天数
                Dictionary<string, Dictionary<string, Dictionary<string, string>>> dicMinDays = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
                Dictionary<string, Dictionary<string, string>> dicMin = new Dictionary<string, Dictionary<string, string>>();
                Dictionary<string, string> dicYearQuarter = new Dictionary<string, string>();
                foreach (KeyValuePair<string, Monitors> k in dicUnofficialPMDaily)
                {
                    dicMin = new Dictionary<string, Dictionary<string, string>>();
                    foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQuarter in k.Value.dicUnofficialPM25Daily)
                    {
                        dicYearQuarter = new Dictionary<string, string>();
                        foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kYear in kQuarter.Value)
                        {
                            if (kYear.Value.Count >= dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialMinDays)
                            {
                                dicYearQuarter.Add(kYear.Key, kQuarter.Key);
                            }
                        }
                        if (dicYearQuarter.Count > 0)
                        {
                            dicMin.Add(kQuarter.Key, dicYearQuarter);
                        }
                    }
                    if (dicMin.Count > 0)
                        dicMinDays.Add(k.Key, dicMin);
                }

                Dictionary<string, Dictionary<string, Dictionary<string, string>>> dicMinQuarters = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
                lstYear = new List<string>();
                foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, string>>> k in dicMinDays)
                {
                    dicMin = new Dictionary<string, Dictionary<string, string>>();
                    foreach (KeyValuePair<string, Dictionary<string, string>> kQ in k.Value)
                    {
                        foreach (KeyValuePair<string, string> kY in kQ.Value)
                        {
                            dicYearQuarter = new Dictionary<string, string>();
                            if (dicMin.ContainsKey(kY.Key))
                            {
                                dicMin[kY.Key].Add(kQ.Key, kY.Key);
                            }
                            else
                            {
                                dicYearQuarter.Add(kQ.Key, kY.Key);
                                dicMin.Add(kY.Key, dicYearQuarter);
                            }
                        }
                    }
                    Dictionary<string, Dictionary<string, string>> dicMinValid = new Dictionary<string, Dictionary<string, string>>();
                    lstYear = new List<string>();
                    foreach (KeyValuePair<string, Dictionary<string, string>> iY in dicMin)
                    {
                        //判断每年的最小季度数是否满足要求
                        if (iY.Value.Count >= dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialMinQuartersPoint)
                        {
                            //对于quarterly pm monitors的计算，每年的季度数最小值为1
                            lstYear.Add(iY.Key);
                            foreach (KeyValuePair<string, string> iQ in iY.Value)
                            {
                                dicYearQuarter = new Dictionary<string, string>();
                                if (dicMinValid.ContainsKey(iQ.Key))
                                {
                                    dicMinValid[iQ.Key].Add(iY.Key, iQ.Key);
                                }
                                else
                                {
                                    dicYearQuarter.Add(iY.Key, iQ.Key);
                                    dicMinValid.Add(iQ.Key, dicYearQuarter);
                                }
                            }
                        }
                    }
                    //判断每个有效的监测点是否满足最小年份数
                    if (dicMinValid.Count > 0 && lstYear.Count() >= dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialMinYears)
                    {
                        dicMinQuarters.Add(k.Key, dicMinValid);
                    }
                }
                #endregion

                #region monitor in model
                Dictionary<string, string> dicMonitorInModelUnofficial = new Dictionary<string, string>();
                GetGridCellUnofficialMonitors(ref dicMonitorInModelUnofficial, dicQuarterlyPeakModel, dicUnofficialPMDaily, ref dicMonitorInModelFRM);
                #endregion

                #region
                dicUnofficialPM = new Dictionary<string, Monitors>();
                GetQuarterlyPeakPmMonitors(dailyPMAnalysisConfiguration, ref dicUnofficialPM, dicUnofficialPMDaily, dicMinQuarters, dicMonitorInModelUnofficial);
                #endregion
                //--------------修正dicUnofficialPM的坐标系！-------------------
                #region
                double[] dConvertArrayUnofficial = null;
                List<double> lstConvertArrayUnofficial = new List<double>();
                List<string> lstKeyUnofficial = dicUnofficialPM.Keys.ToList();
                for (int iLstKey = 0; iLstKey < dicUnofficialPM.Keys.Count; iLstKey++)
                {
                    lstConvertArrayUnofficial.Add(dicUnofficialPM[lstKeyUnofficial[iLstKey]].longitude);
                    lstConvertArrayUnofficial.Add(dicUnofficialPM[lstKeyUnofficial[iLstKey]].lat);
                }
                dConvertArrayUnofficial = lstConvertArrayUnofficial.ToArray();
                DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArrayUnofficial, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984,
                   DotSpatial.Projections.ProjectionInfo.FromProj4String(CommonClass.projUSACMAQ), 0, dConvertArrayUnofficial.Length / 2);
                for (int iLstKey = 0; iLstKey < dicUnofficialPM.Keys.Count; iLstKey++)
                {
                    dicUnofficialPM[lstKeyUnofficial[iLstKey]].longitudeLamber = dConvertArrayUnofficial[2 * iLstKey] / 100.00;
                    dicUnofficialPM[lstKeyUnofficial[iLstKey]].latitudeLamber = dConvertArrayUnofficial[2 * iLstKey + 1] / 100.00;
                }
                #endregion
                //------------------------------------------------

                if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doQuarterlyPeakSpeciatedMonitors)
                {
                    SaveQuarterlyPeakPMMonitors(CommonClass.CurrentBaseScenario, dicUnofficialPM);
                }
                #endregion

                if (dailyPMAnalysisConfiguration.dataInputD.doSpeciesMonitorDataFile)
                {
                    #region speciated monitors
                    _beginTime = DateTime.Now;
                    CommonClass.CurrentLog = "Read species monitor data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.speciesMonitorDataFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    isOK = GetSpeciesMonitors(dailyPMAnalysisConfiguration, ref dicSpeciesDaily);
                    if (dicSpeciesDaily.Count <= 0 || isOK == "unknow")//error message when loading file
                    {
                        CommonClass.CurrentLog = "Fail to read species monitor data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.speciesMonitorDataFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    }
                    //else
                    //{
                    //    if (isOK == "errorRow")
                    //    {
                    //        CommonClass.CurrentLog = "There are errors in the monitor file of " + dailyPMAnalysisConfiguration.dataInputD.speciesMonitorDataFile + ". The error rows were removed.";
                    //        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                    //    }
                    //}
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentLog = "Finish reading species monitor data: " + CommonClass.TotalTime + " s.";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    #region min data requirement
                    //判断满足是否满足每个季度的最小天数
                    #region
                    dicMinDays = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
                    dicMin = new Dictionary<string, Dictionary<string, string>>();
                    dicYearQuarter = new Dictionary<string, string>();
                    foreach (KeyValuePair<string, Monitors> k in dicSpeciesDaily)
                    {
                        dicMin = new Dictionary<string, Dictionary<string, string>>();
                        foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, SpeciesForFractions>>> kQuarter in dicSpeciesDaily[k.Key].dicSpeciesDailyQuarterYear)
                        {
                            dicYearQuarter = new Dictionary<string, string>();
                            foreach (KeyValuePair<string, Dictionary<string, SpeciesForFractions>> kYear in dicSpeciesDaily[k.Key].dicSpeciesDailyQuarterYear[kQuarter.Key])
                            {
                                if (kYear.Value.Count >= dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_MinDays)
                                {
                                    dicYearQuarter.Add(kYear.Key, kQuarter.Key);
                                }
                            }
                            if (dicYearQuarter.Count > 0)
                            {
                                dicMin.Add(kQuarter.Key, dicYearQuarter);
                            }
                        }
                        if (dicMin.Count > 0)
                            dicMinDays.Add(k.Key, dicMin);
                    }
                    #endregion
                    //判断是否满足每一年的最小季度数
                    #region
                    dicMinQuarters = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();

                    foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, string>>> k in dicMinDays)
                    {
                        dicMin = new Dictionary<string, Dictionary<string, string>>();
                        foreach (KeyValuePair<string, Dictionary<string, string>> kQ in k.Value)
                        {
                            foreach (KeyValuePair<string, string> kY in kQ.Value)
                            {
                                dicYearQuarter = new Dictionary<string, string>();
                                if (dicMin.ContainsKey(kY.Key))
                                {
                                    dicMin[kY.Key].Add(kQ.Key, kY.Key);
                                }
                                else
                                {
                                    dicYearQuarter.Add(kQ.Key, kY.Key);
                                    dicMin.Add(kY.Key, dicYearQuarter);
                                }
                            }
                        }
                        Dictionary<string, Dictionary<string, string>> dicMinValid = new Dictionary<string, Dictionary<string, string>>();
                        lstYear = new List<string>();
                        foreach (KeyValuePair<string, Dictionary<string, string>> iY in dicMin)
                        {
                            //判断每年的最小季度数是否满足要求
                            if (iY.Value.Count >= dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_MinQuarters)
                            {
                                lstYear.Add(iY.Key);
                                foreach (KeyValuePair<string, string> iQ in iY.Value)
                                {
                                    dicYearQuarter = new Dictionary<string, string>();
                                    if (dicMinValid.ContainsKey(iQ.Key))
                                    {
                                        dicMinValid[iQ.Key].Add(iY.Key, iQ.Key);
                                    }
                                    else
                                    {
                                        dicYearQuarter.Add(iY.Key, iQ.Key);
                                        dicMinValid.Add(iQ.Key, dicYearQuarter);
                                    }
                                }
                            }
                        }
                        //判断每个有效的监测点是否满足最小年份数
                        if (dicMinValid.Count > 0 && lstYear.Count() >= dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_MinYear)
                        {
                            dicMinQuarters.Add(k.Key, dicMinValid);
                        }
                    }
                    #endregion
                    #endregion

                    #region monitor in model
                    Dictionary<string, string> dicMonitorInModelSpecies = new Dictionary<string, string>();
                    GetGridCellSpeciatedMonitors(ref dicMonitorInModelSpecies, dicQuarterlyPeakModel, dicSpeciesDaily);
                    #endregion

                    //根据在species fractions options窗体中选择的方法来计算相应的species
                    dicSpeciatedMonitors = new Dictionary<string, Monitors>();
                    CalculateQuarterlyPeakSpeciatedMonitors(dailyPMAnalysisConfiguration, ref dicSpeciatedMonitors, dicSpeciesDaily, dicMinQuarters, dicMonitorInModelSpecies);
                    dicSpeciesDaily.Clear();
                    //---------修正dicSpeciatedMonitors的坐标系-----------
                    #region
                    double[] dConvertArraySpecies = null;
                    List<string> lstKeySpeciesMonitors = dicSpeciatedMonitors.Keys.ToList();
                    List<double> lstConvertArray = new List<double>();
                    for (int iLstKey = 0; iLstKey < dicSpeciatedMonitors.Keys.Count; iLstKey++)
                    {
                        lstConvertArray.Add(dicSpeciatedMonitors[lstKeySpeciesMonitors[iLstKey]].longitude);
                        lstConvertArray.Add(dicSpeciatedMonitors[lstKeySpeciesMonitors[iLstKey]].lat);
                    }
                    dConvertArraySpecies = lstConvertArray.ToArray();
                    DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArraySpecies, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984,
                       DotSpatial.Projections.ProjectionInfo.FromProj4String(CommonClass.projUSACMAQ), 0, dConvertArraySpecies.Length / 2);
                    for (int iLstKey = 0; iLstKey < dicSpeciatedMonitors.Keys.Count; iLstKey++)
                    {
                        dicSpeciatedMonitors[lstKeySpeciesMonitors[iLstKey]].longitudeLamber = dConvertArraySpecies[2 * iLstKey] / 100.00;
                        dicSpeciatedMonitors[lstKeySpeciesMonitors[iLstKey]].latitudeLamber = dConvertArraySpecies[2 * iLstKey + 1] / 100.00;
                    }
                    #endregion
                    //------------------------------------------------------

                    if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doQuarterlyPeakSpeciatedMonitors)
                    {
                        SaveQuarterlyPeakSpeciatedMonitors(CommonClass.CurrentBaseScenario, dicSpeciatedMonitors);
                    }
                    #endregion

                    #region Species Fractions
                    //根据FRM PM25得到其周围的species monitors，根据公式计算species fractions=species/(FRM PM-blank mass)
                    Dictionary<string, Monitors> dicSpeciesLongLat = new Dictionary<string, Monitors>();
                    Dictionary<string, List<string>> dicSpeciatedMonitorsNH4DON = new Dictionary<string, List<string>>();
                    Dictionary<string, Monitors> dicNh4DonLongLat = new Dictionary<string, Monitors>();
                    foreach (KeyValuePair<string, Monitors> iSpecies in dicSpeciatedMonitors)
                    {
                        if (!dicSpeciesLongLat.ContainsKey(iSpecies.Value.longitudeLamber + "," + iSpecies.Value.latitudeLamber))
                        {
                            dicSpeciesLongLat.Add(iSpecies.Value.longitudeLamber + "," + iSpecies.Value.latitudeLamber, iSpecies.Value);
                        }
                        foreach (KeyValuePair<string, SpeciesForFractions> kin in iSpecies.Value.dicSpeciesMonitors)
                        {
                            if (!Double.IsNaN(kin.Value.don))
                            {
                                if (dicSpeciatedMonitorsNH4DON.ContainsKey(iSpecies.Key))
                                {
                                    dicSpeciatedMonitorsNH4DON[iSpecies.Key].Add(kin.Key);
                                }
                                else
                                {
                                    dicSpeciatedMonitorsNH4DON.Add(iSpecies.Key, new List<string> { kin.Key });
                                }
                            }
                        }
                    }
                    Dictionary<string, Monitors> dicNeighborFilePoint = new Dictionary<string, Monitors>();
                    foreach (KeyValuePair<string, Monitors> iPM in dicUnofficialPM)
                    {
                        #region neighbor file point
                        dicNeighborFilePoint.Add(iPM.Key, new Monitors()
                        {
                            id = iPM.Key,
                            lat = iPM.Value.lat,
                            longitude = iPM.Value.longitude,
                            monitorGridcell = iPM.Value.monitorGridcell,
                            dicNeighborInfo = new Dictionary<string, Dictionary<string, NeighborInfoDaily>>(),
                        });
                        if (dicMonitorStateCounty.ContainsKey(iPM.Key))
                        {
                            dicNeighborFilePoint[iPM.Key].stateName = dicMonitorStateCounty[iPM.Key].stateName;
                            dicNeighborFilePoint[iPM.Key].countyName = dicMonitorStateCounty[iPM.Key].countyName;
                        }
                        else
                        {
                            dicNeighborFilePoint[iPM.Key].stateName = "";
                            dicNeighborFilePoint[iPM.Key].countyName = "";
                        }
                        #endregion
                        foreach (KeyValuePair<string, PM25Monitors> kQ in iPM.Value.dicPM)
                        {
                            //------------------每个季度分别进行VNA------------
                            #region
                            //--------------NH4 DON 的VNA插值要与其他的species分开-------------
                            List<double> fsInterSpecies = new List<double>();
                            fsInterSpecies.Add(iPM.Value.longitudeLamber);
                            fsInterSpecies.Add(iPM.Value.latitudeLamber);

                            List<double> fsInterNH4DON = new List<double>();
                            fsInterNH4DON.Add(iPM.Value.longitudeLamber);
                            fsInterNH4DON.Add(iPM.Value.latitudeLamber);

                            #region species except nh4 & don
                            bool isSame = false;
                            List<double> fsOutSpecies = new List<double>();
                            if (dicSpeciesLongLat.ContainsKey(iPM.Value.longitudeLamber + "," + iPM.Value.latitudeLamber)
                                && dicSpeciesLongLat[iPM.Value.longitudeLamber + "," + iPM.Value.latitudeLamber].dicSpeciesMonitors.ContainsKey(kQ.Key))
                                isSame = true;
                            if (!isSame)
                            {
                                //简化VNA算法：求指定半径内的监测点做VNA,一开始是以5个经纬度来算，一直达到10个为止
                                Dictionary<string, double> dicDistanceMonitorSpecies = new Dictionary<string, double>();
                                foreach (KeyValuePair<string, Monitors> kin in dicSpeciatedMonitors)
                                {
                                    if (!kin.Value.dicSpeciesMonitors.ContainsKey(kQ.Key)) continue;
                                    dicDistanceMonitorSpecies.Add(kin.Key, (iPM.Value.longitude - kin.Value.longitude) * (iPM.Value.longitude - kin.Value.longitude) + (iPM.Value.lat - kin.Value.lat) * (iPM.Value.lat - kin.Value.lat));
                                }
                                var query = dicDistanceMonitorSpecies.Where(p => p.Value > 0).ToList();

                                foreach (KeyValuePair<string, double> item in query)
                                {
                                    fsInterSpecies.Add(dicSpeciatedMonitors[item.Key].longitudeLamber);
                                    fsInterSpecies.Add(dicSpeciatedMonitors[item.Key].latitudeLamber);
                                }
                                //---------end VNA-------------------
                                CommonClass.VoronoiPoints(fsInterSpecies.ToArray(), ref fsOutSpecies);
                            }
                            else
                            {
                                fsOutSpecies.Add(iPM.Value.longitudeLamber);
                                fsOutSpecies.Add(iPM.Value.latitudeLamber);
                            }
                            //----根据得到的neighbor计算数值----
                            Dictionary<string, float> fsoutString = new Dictionary<string, float>();
                            for (int ifsout = 0; ifsout < fsOutSpecies.Count; ifsout++)
                            {
                                if (ifsout % 2 == 1)
                                {
                                    float distance = CommonClass.getDistanceFrom2Point(iPM.Value.longitude, iPM.Value.lat, dicSpeciesLongLat[fsOutSpecies[ifsout - 1] + "," + fsOutSpecies[ifsout]].longitude, dicSpeciesLongLat[fsOutSpecies[ifsout - 1] + "," + fsOutSpecies[ifsout]].lat);
                                    fsoutString.Add(dicSpeciesLongLat[fsOutSpecies[ifsout - 1] + "," + fsOutSpecies[ifsout]].id + "," + dicSpeciesLongLat[fsOutSpecies[ifsout - 1] + "," + fsOutSpecies[ifsout]].monitorGridcell, distance);
                                }
                            }
                            #endregion
                            if (fsoutString.Count == 0) continue;
                            #region nh4 && don
                            isSame = false;
                            List<double> fsOutNH4DON = new List<double>();
                            if (dicSpeciatedMonitorsNH4DON.ContainsKey(iPM.Value.longitudeLamber + "," + iPM.Value.latitudeLamber)
                                && dicSpeciatedMonitorsNH4DON[iPM.Value.longitudeLamber + "," + iPM.Value.latitudeLamber].Contains(kQ.Key))
                                isSame = true;
                            if (!isSame)
                            {
                                //简化VNA算法：求指定半径内的监测点做VNA,一开始是以5个经纬度来算，一直达到10个为止
                                Dictionary<string, double> dicDistanceNh4Don = new Dictionary<string, double>();
                                foreach (KeyValuePair<string, List<string>> kin in dicSpeciatedMonitorsNH4DON)
                                {
                                    if (!kin.Value.Contains(kQ.Key)) continue;
                                    dicDistanceNh4Don.Add(kin.Key, (iPM.Value.longitude - dicSpeciatedMonitors[kin.Key].longitude) * (iPM.Value.longitude - dicSpeciatedMonitors[kin.Key].longitude) + (iPM.Value.lat - dicSpeciatedMonitors[kin.Key].lat) * (iPM.Value.lat - dicSpeciatedMonitors[kin.Key].lat));
                                }
                                var query = dicDistanceNh4Don.Where(p => p.Value > 0).ToList();

                                foreach (KeyValuePair<string, double> item in query)
                                {
                                    fsInterNH4DON.Add(dicSpeciatedMonitors[item.Key].longitudeLamber);
                                    fsInterNH4DON.Add(dicSpeciatedMonitors[item.Key].latitudeLamber);
                                }
                                //---------end VNA-------------------
                                CommonClass.VoronoiPoints(fsInterNH4DON.ToArray(), ref fsOutNH4DON);
                            }
                            else
                            {
                                fsOutNH4DON.Add(iPM.Value.longitudeLamber);
                                fsOutNH4DON.Add(iPM.Value.latitudeLamber);
                            }
                            //----根据得到的neighbor计算数值----
                            Dictionary<string, float> fsoutStringNH4DON = new Dictionary<string, float>();
                            for (int ifsout = 0; ifsout < fsOutNH4DON.Count; ifsout++)
                            {
                                if (ifsout % 2 == 1)
                                {
                                    float distance = CommonClass.getDistanceFrom2Point(iPM.Value.longitude, iPM.Value.lat, dicSpeciesLongLat[fsOutNH4DON[ifsout - 1] + "," + fsOutNH4DON[ifsout]].longitude, dicSpeciesLongLat[fsOutNH4DON[ifsout - 1] + "," + fsOutNH4DON[ifsout]].lat);
                                    fsoutStringNH4DON.Add(dicSpeciesLongLat[fsOutNH4DON[ifsout - 1] + "," + fsOutNH4DON[ifsout]].id + "," + dicSpeciesLongLat[fsOutNH4DON[ifsout - 1] + "," + fsOutNH4DON[ifsout]].monitorGridcell, distance);
                                }
                            }
                            #endregion
                            if (fsoutString.Count == 0 || fsoutStringNH4DON.Count == 0) continue;
                            #endregion
                            Dictionary<string, NeighborInfoDaily> dicNeighborInfo = new Dictionary<string, NeighborInfoDaily>();
                            double vnaCrustal = 0, vnaEC = 0, vnaNH4 = 0, vnaSO4 = 0, vnaOC = 0, vnaSalt = 0, vnaNO3r = 0, vnaDON = 0, vnaPBW = 0, vnaNO3 = 0;
                            //----------对于每种species分别按照不同的季度进行单独计算，因为每种species所选择的插值方法都有可能不同-----------
                            DailyVNA(ref dicNeighborInfo, kQ.Key, "CRUSTAL", dailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, dailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaCrustal, fsoutString, dicSpeciatedMonitors);
                            DailyVNA(ref dicNeighborInfo, kQ.Key, "DON", dailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, dailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaDON, fsoutStringNH4DON, dicSpeciatedMonitors);
                            DailyVNA(ref dicNeighborInfo, kQ.Key, "EC", dailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, dailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaEC, fsoutString, dicSpeciatedMonitors);
                            DailyVNA(ref dicNeighborInfo, kQ.Key, "NH4", dailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, dailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaNH4, fsoutStringNH4DON, dicSpeciatedMonitors);
                            DailyVNA(ref dicNeighborInfo, kQ.Key, "NO3", dailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, dailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaNO3, fsoutString, dicSpeciatedMonitors);
                            DailyVNA(ref dicNeighborInfo, kQ.Key, "NO3r", dailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, dailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaNO3r, fsoutString, dicSpeciatedMonitors);
                            DailyVNA(ref dicNeighborInfo, kQ.Key, "OCb", dailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, dailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaOC, fsoutString, dicSpeciatedMonitors);
                            DailyVNA(ref dicNeighborInfo, kQ.Key, "SALT", dailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, dailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaSalt, fsoutString, dicSpeciatedMonitors);
                            DailyVNA(ref dicNeighborInfo, kQ.Key, "SO4", dailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, dailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaSO4, fsoutString, dicSpeciatedMonitors);
                            dicNeighborFilePoint[iPM.Key].dicNeighborInfo.Add(kQ.Key, dicNeighborInfo);
                            #region
                            SpecFracPM sfDaily = new SpecFracPM
                            {
                                iCrustal = vnaCrustal,
                                iNH4 = vnaNH4,
                                iEC = vnaEC,
                                iNO3 = vnaNO3,
                                iNO3r = vnaNO3r,
                                iSO4 = vnaSO4,
                                iSalt = vnaSalt,
                                iOcb = vnaOC,
                                iDON = vnaDON,
                                don = vnaDON,
                                pm25MassFrac = kQ.Value.bPM25,
                            };
                            #endregion
                            #region nh4
                            if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.doUseDonValues)
                            {
                                vnaNH4 = vnaDON * vnaSO4 + 0.29 * vnaNO3r;
                            }
                            else if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.doUseMeasuredAmmonium)
                            {
                                double nh4_adj = vnaNH4 - (dailyPMAnalysisConfiguration.speciesFractionOptionsD.nh4PercentageEvaporating * 0.29 * (vnaNO3 - vnaNO3r));
                                double nh4_so4 = nh4_adj - 0.29 * vnaNO3r;
                                double don_calc = nh4_so4 / vnaSO4;
                                vnaNH4 = don_calc * vnaSO4 + 0.29 * vnaNO3r;
                                vnaDON = don_calc;
                            }
                            #endregion
                            //------------pbw-------------------
                            CommonClass.CalculationWater(vnaSO4, vnaNO3r, vnaNH4, vnaDON, ref vnaPBW);
                            #region adjustment OCMmb
                            double oc_floor = 0, nonBlankMass = 0, oc_max = 0, oc_ceiling = 0, oc = 0, checkOC = 0, change = 0;
                            nonBlankMass = kQ.Value.bPM25 - Convert.ToDouble(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass);
                            oc = nonBlankMass - (vnaCrustal + vnaSO4 + vnaNO3r + vnaNH4 + vnaPBW + vnaSalt + vnaEC);
                            oc_floor = Convert.ToDouble(dailyPMAnalysisConfiguration.speciesFractionOptionsD.floorOCMMB) * vnaOC;
                            oc_max = Math.Max(oc, oc_floor);
                            oc_ceiling = Convert.ToDouble(dailyPMAnalysisConfiguration.speciesFractionOptionsD.ceilingOCMMB) * nonBlankMass;
                            vnaOC = Math.Min(oc_max, oc_ceiling);
                            //--------当各species的和大于或小于NonBlankMass时调整OCMmb-------------SO4 + NO3r + NH4r + PBW + crustal + EC + OCMmb_calc + salt
                            checkOC = nonBlankMass - (vnaCrustal + vnaSO4 + vnaNO3r + vnaNH4 + vnaPBW + vnaSalt + vnaEC + vnaOC);
                            change = checkOC / (vnaCrustal + vnaSO4 + vnaNO3r + vnaNH4 + vnaPBW + vnaSalt + vnaEC);
                            vnaCrustal = (1 + change) * vnaCrustal;
                            vnaEC = (1 + change) * vnaEC;
                            vnaNH4 = (1 + change) * vnaNH4;
                            vnaNO3r = (1 + change) * vnaNO3r;
                            vnaSO4 = (1 + change) * vnaSO4;
                            vnaSalt = (1 + change) * vnaSalt;
                            vnaPBW = (1 + change) * vnaPBW;
                            #endregion
                            #region
                            sfDaily.fCr = vnaCrustal / nonBlankMass;
                            sfDaily.fNH4 = vnaNH4 / nonBlankMass;
                            sfDaily.fEC = vnaEC / nonBlankMass;
                            sfDaily.fNO3 = vnaNO3 / nonBlankMass;
                            sfDaily.fNO3r = vnaNO3r / nonBlankMass;
                            sfDaily.fSO4 = vnaSO4 / nonBlankMass;
                            sfDaily.fSalt = vnaSalt / nonBlankMass;
                            sfDaily.fOcm = vnaOC / nonBlankMass;
                            sfDaily.fWater = vnaPBW / nonBlankMass;
                            if (dicSpeciesFractions.ContainsKey(iPM.Key))
                            {
                                dicSpeciesFractions[iPM.Key].dicSpeciesFractions.Add(kQ.Key, sfDaily);
                            }
                            else
                            {
                                dicSpeciesFractions.Add(iPM.Key, new Monitors()
                                {
                                    id = iPM.Value.id,
                                    stateName = iPM.Value.stateName,
                                    countyName = iPM.Value.countyName,
                                    lat = iPM.Value.lat,
                                    longitude = iPM.Value.longitude,
                                    dicSpeciesFractions = new Dictionary<string, SpecFracPM>(),
                                });
                                if (!dicMonitorStateCounty.ContainsKey(iPM.Key))
                                {
                                    dicSpeciesFractions[iPM.Key].stateName = "";
                                    dicSpeciesFractions[iPM.Key].countyName = "";
                                }
                                else
                                {
                                    dicSpeciesFractions[iPM.Key].stateName = dicMonitorStateCounty[iPM.Key].stateName;
                                    dicSpeciesFractions[iPM.Key].countyName = dicMonitorStateCounty[iPM.Key].countyName;
                                }
                                dicSpeciesFractions[iPM.Key].dicSpeciesFractions.Add(kQ.Key, sfDaily);
                            }
                            #endregion
                        }
                    }
                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doSpeciesFraction)
                    {
                        SaveSpeciesFractions(CommonClass.CurrentBaseScenario, dicSpeciesFractions, "");
                        if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                        {
                            for (int i = 0; i < dicDesignValuePeriod.Count; i++)
                            {
                                SaveSpeciesFractions(CommonClass.CurrentBaseScenario, dicSpeciesFractions, " Period " + (i + 1).ToString());
                            }
                        }
                    }

                    if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doNeighborFilePoint)
                    {
                        SaveNeighborFilePoint(CommonClass.CurrentBaseScenario, dicNeighborFilePoint, "");
                        if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                        {
                            for (int i = 0; i < dicDesignValuePeriod.Count; i++)
                            {
                                SaveNeighborFilePoint(CommonClass.CurrentBaseScenario, dicNeighborFilePoint, " Period " + (i + 1).ToString());
                            }
                        }
                    }
                    dicNeighborFilePoint.Clear();
                    GC.Collect();
                    #endregion
                }
                else if (dailyPMAnalysisConfiguration.dataInputD.doSpeciesFractionFile)
                {
                    _beginTime = DateTime.Now;
                    CommonClass.CurrentLog = "Read species fraction data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.specFracPointFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    isOK = GetSpeciesFractions(dailyPMAnalysisConfiguration, ref dicSpeciesFractions);
                    if (!string.IsNullOrEmpty(isOK))//error message when loading file
                    {
                        CommonClass.CurrentLog = "Fail to read species fraction data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.specFracPointFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        return false;
                    }
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentLog = "Finish reading species fraction data: " + CommonClass.TotalTime + " s.";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doSpeciesFraction)
                    {
                        SaveSpeciesFractionCopyDirectly(CommonClass.CurrentBaseScenario);
                    }
                }
                #endregion

                _beginTime = DateTime.Now;
                #region use species fractions to calculate baseline top32 species values
                #region
                double blankMass = Convert.ToDouble(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass);
                Dictionary<string, Monitors> dicPMMonitors = new Dictionary<string, Monitors>();
                foreach (KeyValuePair<string, Monitors> k in dicOfficialMonitors)
                {
                    if (!dicMonitorInModelFRM.ContainsKey(k.Key) || k.Value.stateName.Replace("\"", "") == "Alaska"
                        || k.Value.stateName.Replace("\"", "") == "Puerto Rico" || k.Value.stateName.Replace("\"", "") == "Hawaii"
                        || k.Value.type.Replace("\"", "") != "FRM" || !dicSpeciesFractions.ContainsKey(k.Key) || !dicMonitorStateCounty.ContainsKey(k.Key)) continue;
                    dicPMMonitors.Add(k.Key, new Monitors()
                    {
                        id = k.Key,
                        type = k.Value.type,
                        lat = k.Value.lat,
                        longitude = k.Value.longitude,
                        monitorGridcell = k.Value.monitorGridcell,
                        stateName = k.Value.stateName,
                        countyName = k.Value.countyName,
                        dicOfficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                    });
                    if (k.Key == "211170007")
                    { 
                    }
                    foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQ in k.Value.dicOfficialPM25Daily)
                    {
                        Dictionary<string, PM25Monitors> dic = new Dictionary<string, PM25Monitors>();
                        Dictionary<string, Dictionary<string, PM25Monitors>> dicYear = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                        foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kY in kQ.Value)
                        {
                            string rank = "";
                            dic = new Dictionary<string, PM25Monitors>();
                            foreach (KeyValuePair<string, PM25Monitors> kD in kY.Value)
                            {
                                if (rank == "") rank = kD.Value.rank98.ToString();
                                PM25Monitors pM25Monitors = new PM25Monitors();
                                pM25Monitors.percentile_98 = kD.Value.percentile_98;
                                pM25Monitors.bPM25 = kD.Value.bPM25;
                                pM25Monitors.bCrustal = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fCr);
                                pM25Monitors.bEC = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fEC);
                                pM25Monitors.bNH4 = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fNH4);
                                pM25Monitors.bOCMmb = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fOcm);
                                pM25Monitors.bSO4 = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fSO4);
                                pM25Monitors.bNO3 = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fNO3);
                                pM25Monitors.bNO3r = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fNO3r);
                                pM25Monitors.bWater = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fWater);
                                pM25Monitors.bSalt = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fSalt);
                                pM25Monitors.bDON = Convert.ToSingle(dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].don);
                                dic.Add(kD.Key, pM25Monitors);
                            }
                            dicYear.Add(kY.Key + "," + rank, dic);
                        }
                        dicPMMonitors[k.Key].dicOfficialPM25Daily.Add(kQ.Key, dicYear);
                    }
                }
                #endregion
                #region dv period
                for (int i = 0; i < lstAllYearsAllDaysPeriod.Count; i++)
                {
                    List<string> lstRemove = new List<string>();
                    foreach (KeyValuePair<string, Monitors> k in lstAllYearsAllDaysPeriod[i])
                    {
                        if (!dicMonitorInModelFRM.ContainsKey(k.Key) || k.Value.stateName.Replace("\"", "") == "Alaska"
                       || k.Value.stateName.Replace("\"", "") == "Puerto Rico" || k.Value.stateName.Replace("\"", "") == "Hawaii"
                       || k.Value.type.Replace("\"", "") != "FRM" || !dicSpeciesFractions.ContainsKey(k.Key) || !dicMonitorStateCounty.ContainsKey(k.Key))
                        {
                            k.Value.dicOfficialPM25Daily = null;
                            lstRemove.Add(k.Key);
                            continue;
                        }
                        if (k.Value.dicOfficialPM25Daily == null) continue;
                        foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQ in k.Value.dicOfficialPM25Daily)
                        {
                            foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kY in kQ.Value)
                            {
                                foreach (KeyValuePair<string, PM25Monitors> kD in kY.Value)
                                {
                                    double pm = kD.Value.bPM25 - blankMass;
                                    //kD.Value.percentile_98=

                                    kD.Value.bCrustal = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fCr);
                                    kD.Value.bEC = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fEC);
                                    kD.Value.bNH4 = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fNH4);
                                    kD.Value.bOCMmb = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fOcm);
                                    kD.Value.bSO4 = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fSO4);
                                    kD.Value.bNO3 = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fNO3);
                                    kD.Value.bNO3r = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fNO3r);
                                    kD.Value.bWater = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fWater);
                                    kD.Value.bSalt = Convert.ToSingle((kD.Value.bPM25 - blankMass) * dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].fSalt);
                                    kD.Value.bDON = Convert.ToSingle(dicSpeciesFractions[k.Key].dicSpeciesFractions[kQ.Key].don);
                                }
                            }
                        }
                    }
                    foreach (string s in lstRemove)
                    {
                        lstAllYearsAllDaysPeriod[i].Remove(s);
                    }
                }
                dicSpeciesFractions.Clear();
                GC.Collect();
                #endregion
                #endregion
                //_endTime = DateTime.Now;
                //CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                //CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish reading monitor data (FRM & CSN/IMPROVE): " + CommonClass.TotalTime + " s.");
                //CommonClass.CurrentLog = "Finish reading monitor data (FRM & CSN/IMPROVE): " + CommonClass.TotalTime + " s";

                //CommonClass.CurrentBaseScenario.log.lstLog.Add("Start computing RRFs.");
                //CommonClass.CurrentLog = "Start computing RRFs...";
                //_beginTime = DateTime.Now;
                //CommonClass.CurrentBaseScenario.log.lstLog.Add("Loading model future data.");
                //CommonClass.CurrentLog = "Loading model future data...";
                //CommonClass.CurrentBaseScenario.log.lstLog.Add(" Interpolate to FRM sites.");
                //CommonClass.CurrentLog = "Interpolate to FRM sites.";
                #region step3: calculate RRF，future species values and pm25
                List<string> lstUsedModelData = new List<string>();
                Dictionary<string, DailyModelMonitor> dicModelDataPeriod = new Dictionary<string, DailyModelMonitor>();
                foreach (KeyValuePair<string, Monitors> k in dicPMMonitors)
                {
                    if (!dicQuarterlyPeakModel.ContainsKey(k.Value.monitorGridcell)) continue;
                    int Col = Convert.ToInt32(k.Value.monitorGridcell) / 1000;
                    int Row = Convert.ToInt32(k.Value.monitorGridcell) % 1000;
                    List<string> lstArround = new List<string>();
                    //首先根据gridtype获取周围的网格数
                    switch (dailyPMAnalysisConfiguration.modelDataOptionsD.temporalAdjustmentAtMonitorGridPoint)
                    {
                        case "1x1":
                            lstArround.Add(k.Value.monitorGridcell);
                            break;
                        case "3x3":
                            for (int i3 = -1; i3 <= 1; i3++)
                            {
                                for (int j3 = -1; j3 <= 1; j3++)
                                {
                                    lstArround.Add(((Col + i3) * 1000 + (Row + j3)).ToString());
                                }
                            }
                            break;
                        case "5x5":
                            for (int i5 = -2; i5 <= 2; i5++)
                            {
                                for (int j5 = -2; j5 <= 2; j5++)
                                {
                                    lstArround.Add(((Col + i5) * 1000 + (Row + j5)).ToString());
                                }
                            }
                            break;
                        case "7x7":
                            for (int i7 = -3; i7 <= 3; i7++)
                            {
                                for (int j7 = -3; j7 <= 3; j7++)
                                {
                                    lstArround.Add(((Col + i7) * 1000 + (Row + j7)).ToString());
                                }
                            }
                            break;
                    }
                    //used model data
                    for (int i = 0; i < lstArround.Count; i++)
                    {
                        if (!lstUsedModelData.Contains(lstArround[i]))
                            lstUsedModelData.Add(lstArround[i]);
                    }
                    //然后根据选择的统计方法求所有网格的baseline和control的值：mean、max
                    var query = dicQuarterlyPeakModel.Where(p => lstArround.Contains(p.Key));
                    int iQueryCount = query.Count();
                    if (iQueryCount > 0)
                    {
                        dicModelDataPeriod.Add(k.Key, new DailyModelMonitor()
                        {
                            id = k.Value.id,
                            dicBaseSpecies = new Dictionary<string, ModelDataSpecies>(),
                            dicFutureSpecies = new Dictionary<string, ModelDataSpecies>(),
                        });

                        Dictionary<string, ModelDataSpecies> dicDmBaseline = new Dictionary<string, ModelDataSpecies>();
                        Dictionary<string, ModelDataSpecies> dicDmFuture = new Dictionary<string, ModelDataSpecies>();
                        //根据选项求结果:mean/max
                        #region
                        switch (dailyPMAnalysisConfiguration.modelDataOptionsD.temporalAdjustmentType)
                        {
                            case "Mean":
                                for (int i = 0; i < iQueryCount; i++)
                                {
                                    KeyValuePair<string, DailyModelMonitor> kin = query.ToArray()[i];
                                    foreach (KeyValuePair<string, ModelDataSpecies> kBase in kin.Value.dicBaseSpecies)
                                    {
                                        if (dicDmBaseline.ContainsKey(kBase.Key))
                                        {
                                            dicDmBaseline[kBase.Key].crustal += kBase.Value.crustal;
                                            dicDmBaseline[kBase.Key].nh4 += kBase.Value.nh4;
                                            dicDmBaseline[kBase.Key].so4 += kBase.Value.so4;
                                            dicDmBaseline[kBase.Key].ec += kBase.Value.ec;
                                            dicDmBaseline[kBase.Key].no3 += kBase.Value.no3;
                                            dicDmBaseline[kBase.Key].oc += kBase.Value.oc;
                                            dicDmBaseline[kBase.Key].cm += kBase.Value.cm;
                                            dicDmBaseline[kBase.Key].salt += kBase.Value.salt;
                                        }
                                        else
                                        {
                                            dicDmBaseline.Add(kBase.Key, new ModelDataSpecies()
                                            {
                                                crustal = kBase.Value.crustal,
                                                nh4 = kBase.Value.nh4,
                                                so4 = kBase.Value.so4,
                                                ec = kBase.Value.ec,
                                                no3 = kBase.Value.no3,
                                                oc = kBase.Value.oc,
                                                cm = kBase.Value.cm,
                                                salt = kBase.Value.salt,
                                            });
                                        }
                                    }
                                    foreach (KeyValuePair<string, ModelDataSpecies> kControl in kin.Value.dicFutureSpecies)
                                    {
                                        if (dicDmFuture.ContainsKey(kControl.Key))
                                        {
                                            dicDmFuture[kControl.Key].crustal += kControl.Value.crustal;
                                            dicDmFuture[kControl.Key].nh4 += kControl.Value.nh4;
                                            dicDmFuture[kControl.Key].so4 += kControl.Value.so4;
                                            dicDmFuture[kControl.Key].ec += kControl.Value.ec;
                                            dicDmFuture[kControl.Key].no3 += kControl.Value.no3;
                                            dicDmFuture[kControl.Key].oc += kControl.Value.oc;
                                            dicDmFuture[kControl.Key].cm += kControl.Value.cm;
                                            dicDmFuture[kControl.Key].salt += kControl.Value.salt;
                                        }
                                        else
                                        {
                                            dicDmFuture.Add(kControl.Key, new ModelDataSpecies()
                                            {
                                                crustal = kControl.Value.crustal,
                                                nh4 = kControl.Value.nh4,
                                                so4 = kControl.Value.so4,
                                                ec = kControl.Value.ec,
                                                no3 = kControl.Value.no3,
                                                oc = kControl.Value.oc,
                                                cm = kControl.Value.cm,
                                                salt = kControl.Value.salt,
                                            });
                                        }
                                    }
                                }
                                //------------calculate mean--------------
                                foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicDmBaseline)
                                {
                                    dicDmBaseline[kBase.Key].crustal = dicDmBaseline[kBase.Key].crustal / iQueryCount;
                                    dicDmBaseline[kBase.Key].nh4 = dicDmBaseline[kBase.Key].nh4 / iQueryCount;
                                    dicDmBaseline[kBase.Key].so4 = dicDmBaseline[kBase.Key].so4 / iQueryCount;
                                    dicDmBaseline[kBase.Key].ec = dicDmBaseline[kBase.Key].ec / iQueryCount;
                                    dicDmBaseline[kBase.Key].no3 = dicDmBaseline[kBase.Key].no3 / iQueryCount;
                                    dicDmBaseline[kBase.Key].oc = dicDmBaseline[kBase.Key].oc / iQueryCount;
                                    dicDmBaseline[kBase.Key].cm = dicDmBaseline[kBase.Key].cm / iQueryCount;
                                    dicDmBaseline[kBase.Key].salt = dicDmBaseline[kBase.Key].salt / iQueryCount;
                                }
                                foreach (KeyValuePair<string, ModelDataSpecies> kControl in dicDmFuture)
                                {
                                    dicDmFuture[kControl.Key].crustal = dicDmFuture[kControl.Key].crustal / iQueryCount;
                                    dicDmFuture[kControl.Key].nh4 = dicDmFuture[kControl.Key].nh4 / iQueryCount;
                                    dicDmFuture[kControl.Key].so4 = dicDmFuture[kControl.Key].so4 / iQueryCount;
                                    dicDmFuture[kControl.Key].ec = dicDmFuture[kControl.Key].ec / iQueryCount;
                                    dicDmFuture[kControl.Key].no3 = dicDmFuture[kControl.Key].no3 / iQueryCount;
                                    dicDmFuture[kControl.Key].oc = dicDmFuture[kControl.Key].oc / iQueryCount;
                                    dicDmFuture[kControl.Key].cm = dicDmFuture[kControl.Key].cm / iQueryCount;
                                    dicDmFuture[kControl.Key].salt = dicDmFuture[kControl.Key].salt / iQueryCount;
                                }
                                dicModelDataPeriod[k.Key].dicBaseSpecies = dicDmBaseline;
                                dicModelDataPeriod[k.Key].dicFutureSpecies = dicDmFuture;
                                break;
                            case "Maximum":
                                for (int i = 0; i < query.Count(); i++)
                                {
                                    KeyValuePair<string, DailyModelMonitor> kin = query.ToArray()[i];
                                    foreach (KeyValuePair<string, ModelDataSpecies> kBase in kin.Value.dicBaseSpecies)
                                    {
                                        if (!dicDmBaseline.ContainsKey(kBase.Key))
                                        {
                                            dicDmBaseline.Add(kBase.Key, new ModelDataSpecies()
                                            {
                                                crustal = kBase.Value.crustal,
                                                nh4 = kBase.Value.nh4,
                                                so4 = kBase.Value.so4,
                                                ec = kBase.Value.ec,
                                                no3 = kBase.Value.no3,
                                                oc = kBase.Value.oc,
                                                cm = kBase.Value.cm,
                                                salt = kBase.Value.salt,
                                            });
                                        }
                                        else
                                        {
                                            if (dicDmBaseline[kBase.Key].crustal < kBase.Value.crustal)
                                                dicDmBaseline[kBase.Key].crustal = kBase.Value.crustal;
                                            if (dicDmBaseline[kBase.Key].nh4 < kBase.Value.nh4)
                                                dicDmBaseline[kBase.Key].nh4 = kBase.Value.nh4;
                                            if (dicDmBaseline[kBase.Key].so4 < kBase.Value.so4)
                                                dicDmBaseline[kBase.Key].so4 = kBase.Value.so4;
                                            if (dicDmBaseline[kBase.Key].ec < kBase.Value.ec)
                                                dicDmBaseline[kBase.Key].ec = kBase.Value.ec;
                                            if (dicDmBaseline[kBase.Key].no3 < kBase.Value.no3)
                                                dicDmBaseline[kBase.Key].no3 = kBase.Value.no3;
                                            if (dicDmBaseline[kBase.Key].oc < kBase.Value.oc)
                                                dicDmBaseline[kBase.Key].oc = kBase.Value.oc;
                                            if (dicDmBaseline[kBase.Key].cm < kBase.Value.cm)
                                                dicDmBaseline[kBase.Key].cm = kBase.Value.cm;
                                            if (dicDmBaseline[kBase.Key].salt < kBase.Value.salt)
                                                dicDmBaseline[kBase.Key].salt = kBase.Value.salt;
                                        }
                                    }
                                    foreach (KeyValuePair<string, ModelDataSpecies> kControl in kin.Value.dicFutureSpecies)
                                    {
                                        if (!dicDmFuture.ContainsKey(kControl.Key))
                                        {
                                            dicDmFuture.Add(kControl.Key, new ModelDataSpecies()
                                            {
                                                crustal = kControl.Value.crustal,
                                                nh4 = kControl.Value.nh4,
                                                so4 = kControl.Value.so4,
                                                ec = kControl.Value.ec,
                                                no3 = kControl.Value.no3,
                                                oc = kControl.Value.oc,
                                                cm = kControl.Value.cm,
                                                salt = kControl.Value.salt,
                                            });
                                        }
                                        else
                                        {
                                            if (dicDmFuture[kControl.Key].crustal < kControl.Value.crustal)
                                                dicDmFuture[kControl.Key].crustal = kControl.Value.crustal;
                                            if (dicDmFuture[kControl.Key].nh4 < kControl.Value.nh4)
                                                dicDmFuture[kControl.Key].nh4 = kControl.Value.nh4;
                                            if (dicDmFuture[kControl.Key].so4 < kControl.Value.so4)
                                                dicDmFuture[kControl.Key].so4 = kControl.Value.so4;
                                            if (dicDmFuture[kControl.Key].ec < kControl.Value.ec)
                                                dicDmFuture[kControl.Key].ec = kControl.Value.ec;
                                            if (dicDmFuture[kControl.Key].no3 < kControl.Value.no3)
                                                dicDmFuture[kControl.Key].no3 = kControl.Value.no3;
                                            if (dicDmFuture[kControl.Key].oc < kControl.Value.oc)
                                                dicDmFuture[kControl.Key].oc = kControl.Value.oc;
                                            if (dicDmFuture[kControl.Key].cm < kControl.Value.cm)
                                                dicDmFuture[kControl.Key].cm = kControl.Value.cm;
                                            if (dicDmFuture[kControl.Key].salt < kControl.Value.salt)
                                                dicDmFuture[kControl.Key].salt = kControl.Value.salt;
                                        }
                                    }
                                }
                                foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicDmBaseline)
                                {
                                    dicDmBaseline[kBase.Key].crustal = dicDmBaseline[kBase.Key].crustal / iQueryCount;
                                    dicDmBaseline[kBase.Key].nh4 = dicDmBaseline[kBase.Key].nh4 / iQueryCount;
                                    dicDmBaseline[kBase.Key].so4 = dicDmBaseline[kBase.Key].so4 / iQueryCount;
                                    dicDmBaseline[kBase.Key].ec = dicDmBaseline[kBase.Key].ec / iQueryCount;
                                    dicDmBaseline[kBase.Key].no3 = dicDmBaseline[kBase.Key].no3 / iQueryCount;
                                    dicDmBaseline[kBase.Key].oc = dicDmBaseline[kBase.Key].oc / iQueryCount;
                                    dicDmBaseline[kBase.Key].cm = dicDmBaseline[kBase.Key].cm / iQueryCount;
                                    dicDmBaseline[kBase.Key].salt = dicDmBaseline[kBase.Key].salt / iQueryCount;
                                }
                                foreach (KeyValuePair<string, ModelDataSpecies> kControl in dicDmFuture)
                                {
                                    dicDmFuture[kControl.Key].crustal = dicDmFuture[kControl.Key].crustal / iQueryCount;
                                    dicDmFuture[kControl.Key].nh4 = dicDmFuture[kControl.Key].nh4 / iQueryCount;
                                    dicDmFuture[kControl.Key].so4 = dicDmFuture[kControl.Key].so4 / iQueryCount;
                                    dicDmFuture[kControl.Key].ec = dicDmFuture[kControl.Key].ec / iQueryCount;
                                    dicDmFuture[kControl.Key].no3 = dicDmFuture[kControl.Key].no3 / iQueryCount;
                                    dicDmFuture[kControl.Key].oc = dicDmFuture[kControl.Key].oc / iQueryCount;
                                    dicDmFuture[kControl.Key].cm = dicDmFuture[kControl.Key].cm / iQueryCount;
                                    dicDmFuture[kControl.Key].salt = dicDmFuture[kControl.Key].salt / iQueryCount;
                                }
                                dicModelDataPeriod[k.Key].dicBaseSpecies = dicDmBaseline;
                                dicModelDataPeriod[k.Key].dicFutureSpecies = dicDmFuture;
                                break;
                            case "Maximum-paired in space":
                                for (int i = 0; i < query.Count(); i++)
                                {
                                    KeyValuePair<string, DailyModelMonitor> kin = query.ToArray()[i];
                                    foreach (KeyValuePair<string, ModelDataSpecies> kBase in kin.Value.dicBaseSpecies)
                                    {
                                        if (!dicDmBaseline.ContainsKey(kBase.Key))
                                        {
                                            dicDmBaseline.Add(kBase.Key, new ModelDataSpecies()
                                            {
                                                crustal = kBase.Value.crustal,
                                                nh4 = kBase.Value.nh4,
                                                so4 = kBase.Value.so4,
                                                ec = kBase.Value.ec,
                                                no3 = kBase.Value.no3,
                                                oc = kBase.Value.oc,
                                                cm = kBase.Value.cm,
                                                salt = kBase.Value.salt,
                                            });
                                            dicDmFuture.Add(kBase.Key, new ModelDataSpecies()
                                            {
                                                crustal = kin.Value.dicFutureSpecies[kBase.Key].crustal,
                                                nh4 = kin.Value.dicFutureSpecies[kBase.Key].nh4,
                                                so4 = kin.Value.dicFutureSpecies[kBase.Key].so4,
                                                ec = kin.Value.dicFutureSpecies[kBase.Key].ec,
                                                no3 = kin.Value.dicFutureSpecies[kBase.Key].no3,
                                                oc = kin.Value.dicFutureSpecies[kBase.Key].oc,
                                                cm = kin.Value.dicFutureSpecies[kBase.Key].cm,
                                                salt = kin.Value.dicFutureSpecies[kBase.Key].salt,
                                            });
                                        }
                                        else
                                        {
                                            if (dicDmBaseline[kBase.Key].crustal < kBase.Value.crustal)
                                            {
                                                dicDmBaseline[kBase.Key].crustal = kBase.Value.crustal;
                                                dicDmFuture[kBase.Key].crustal = kin.Value.dicFutureSpecies[kBase.Key].crustal;
                                            }
                                            if (dicDmBaseline[kBase.Key].nh4 < kBase.Value.nh4)
                                            {
                                                dicDmBaseline[kBase.Key].nh4 = kBase.Value.nh4;
                                                dicDmFuture[kBase.Key].nh4 = kin.Value.dicFutureSpecies[kBase.Key].nh4;
                                            }
                                            if (dicDmBaseline[kBase.Key].so4 < kBase.Value.so4)
                                            {
                                                dicDmBaseline[kBase.Key].so4 = kBase.Value.so4;
                                                dicDmFuture[kBase.Key].so4 = kin.Value.dicFutureSpecies[kBase.Key].so4;
                                            }
                                            if (dicDmBaseline[kBase.Key].ec < kBase.Value.ec)
                                            {
                                                dicDmBaseline[kBase.Key].ec = kBase.Value.ec;
                                                dicDmFuture[kBase.Key].ec = kin.Value.dicFutureSpecies[kBase.Key].ec;
                                            }
                                            if (dicDmBaseline[kBase.Key].no3 < kBase.Value.no3)
                                            {
                                                dicDmBaseline[kBase.Key].no3 = kBase.Value.no3;
                                                dicDmFuture[kBase.Key].no3 = kin.Value.dicFutureSpecies[kBase.Key].no3;
                                            }
                                            if (dicDmBaseline[kBase.Key].oc < kBase.Value.oc)
                                            {
                                                dicDmBaseline[kBase.Key].oc = kBase.Value.oc;
                                                dicDmFuture[kBase.Key].oc = kin.Value.dicFutureSpecies[kBase.Key].oc;
                                            }
                                            if (dicDmBaseline[kBase.Key].cm < kBase.Value.cm)
                                            {
                                                dicDmBaseline[kBase.Key].cm = kBase.Value.cm;
                                                dicDmFuture[kBase.Key].cm = kin.Value.dicFutureSpecies[kBase.Key].cm;
                                            }
                                            if (dicDmBaseline[kBase.Key].salt < kBase.Value.salt)
                                            {
                                                dicDmBaseline[kBase.Key].salt = kBase.Value.salt;
                                                dicDmFuture[kBase.Key].salt = kin.Value.dicFutureSpecies[kBase.Key].salt;
                                            }
                                        }
                                    }
                                }

                                //foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicDmBaseline)
                                //{
                                //    dicDmBaseline[kBase.Key].crustal = dicDmBaseline[kBase.Key].crustal / iQueryCount;
                                //    dicDmBaseline[kBase.Key].nh4 = dicDmBaseline[kBase.Key].nh4 / iQueryCount;
                                //    dicDmBaseline[kBase.Key].so4 = dicDmBaseline[kBase.Key].so4 / iQueryCount;
                                //    dicDmBaseline[kBase.Key].ec = dicDmBaseline[kBase.Key].ec / iQueryCount;
                                //    dicDmBaseline[kBase.Key].no3 = dicDmBaseline[kBase.Key].no3 / iQueryCount;
                                //    dicDmBaseline[kBase.Key].oc = dicDmBaseline[kBase.Key].oc / iQueryCount;
                                //    dicDmBaseline[kBase.Key].cm = dicDmBaseline[kBase.Key].cm / iQueryCount;
                                //    dicDmBaseline[kBase.Key].salt = dicDmBaseline[kBase.Key].salt / iQueryCount;
                                //}
                                //foreach (KeyValuePair<string, ModelDataSpecies> kControl in dicDmFuture)
                                //{
                                //    dicDmFuture[kControl.Key].crustal = dicDmFuture[kControl.Key].crustal / iQueryCount;
                                //    dicDmFuture[kControl.Key].nh4 = dicDmFuture[kControl.Key].nh4 / iQueryCount;
                                //    dicDmFuture[kControl.Key].so4 = dicDmFuture[kControl.Key].so4 / iQueryCount;
                                //    dicDmFuture[kControl.Key].ec = dicDmFuture[kControl.Key].ec / iQueryCount;
                                //    dicDmFuture[kControl.Key].no3 = dicDmFuture[kControl.Key].no3 / iQueryCount;
                                //    dicDmFuture[kControl.Key].oc = dicDmFuture[kControl.Key].oc / iQueryCount;
                                //    dicDmFuture[kControl.Key].cm = dicDmFuture[kControl.Key].cm / iQueryCount;
                                //    dicDmFuture[kControl.Key].salt = dicDmFuture[kControl.Key].salt / iQueryCount;
                                //}
                                dicModelDataPeriod[k.Key].dicBaseSpecies = dicDmBaseline;
                                dicModelDataPeriod[k.Key].dicFutureSpecies = dicDmFuture;
                                break;
                        }
                        #endregion
                        #region
                        if (k.Key == "371830014")
                        { 
                        }
                        foreach (KeyValuePair<string, ModelDataSpecies> kSpecies in dicDmBaseline)
                        {
                            //CRUSTAL_b NH4_b SO4_b EC_b NO3_b OC_b salt_b PM25_b
                            if (kSpecies.Value.crustal < CommonClass.RrfLimit) kSpecies.Value.crustal =Convert.ToSingle( CommonClass.RrfLimit);
                            if (kSpecies.Value.nh4 < CommonClass.RrfLimit) kSpecies.Value.nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.so4 < CommonClass.RrfLimit) kSpecies.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.ec < CommonClass.RrfLimit) kSpecies.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.no3 < CommonClass.RrfLimit) kSpecies.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.oc < CommonClass.RrfLimit) kSpecies.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                            if (Double.IsNaN(kSpecies.Value.salt)||kSpecies.Value.salt < CommonClass.RrfLimit) kSpecies.Value.salt = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.pm25 < CommonClass.RrfLimit) kSpecies.Value.pm25 = Convert.ToSingle(CommonClass.RrfLimit);
                        }
                        foreach (KeyValuePair<string, ModelDataSpecies> kSpecies in dicDmFuture)
                        {
                            //CRUSTAL_b NH4_b SO4_b EC_b NO3_b OC_b salt_b PM25_b
                            if (kSpecies.Value.crustal < CommonClass.RrfLimit) 
                                kSpecies.Value.crustal = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.nh4 < CommonClass.RrfLimit) kSpecies.Value.nh4 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.so4 < CommonClass.RrfLimit) kSpecies.Value.so4 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.ec < CommonClass.RrfLimit) kSpecies.Value.ec = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.no3 < CommonClass.RrfLimit) kSpecies.Value.no3 = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.oc < CommonClass.RrfLimit) kSpecies.Value.oc = Convert.ToSingle(CommonClass.RrfLimit);
                            if (Double.IsNaN(kSpecies.Value.salt) || kSpecies.Value.salt < CommonClass.RrfLimit) kSpecies.Value.salt = Convert.ToSingle(CommonClass.RrfLimit);
                            if (kSpecies.Value.pm25 < CommonClass.RrfLimit) kSpecies.Value.pm25 = Convert.ToSingle(CommonClass.RrfLimit);
                        }
                        foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> ipmQuarter in dicPMMonitors[k.Key].dicOfficialPM25Daily)
                        {
                            foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> ipmYear in dicPMMonitors[k.Key].dicOfficialPM25Daily[ipmQuarter.Key])
                            {
                                foreach (KeyValuePair<string, PM25Monitors> ipmDay in ipmYear.Value)
                                {
                                    ipmDay.Value.rrfCrustal = Math.Round((dicDmFuture[ipmQuarter.Key].crustal < CommonClass.RrfLimit ? CommonClass.RrfLimit : dicDmFuture[ipmQuarter.Key].crustal) / (dicDmBaseline[ipmQuarter.Key].crustal< CommonClass.RrfLimit ? CommonClass.RrfLimit :dicDmBaseline[ipmQuarter.Key].crustal), 4);
                                    ipmDay.Value.rrfEC = Math.Round((dicDmFuture[ipmQuarter.Key].ec < CommonClass.RrfLimit ? CommonClass.RrfLimit :dicDmFuture[ipmQuarter.Key].ec) / (dicDmBaseline[ipmQuarter.Key].ec< CommonClass.RrfLimit ? CommonClass.RrfLimit :dicDmBaseline[ipmQuarter.Key].ec), 4);
                                    ipmDay.Value.rrfOC = Math.Round((dicDmFuture[ipmQuarter.Key].oc < CommonClass.RrfLimit ? CommonClass.RrfLimit :dicDmFuture[ipmQuarter.Key].oc) / (dicDmBaseline[ipmQuarter.Key].oc< CommonClass.RrfLimit ? CommonClass.RrfLimit :dicDmBaseline[ipmQuarter.Key].oc), 4);
                                    ipmDay.Value.rrfSO4 = Math.Round((dicDmFuture[ipmQuarter.Key].so4< CommonClass.RrfLimit ? CommonClass.RrfLimit :  dicDmFuture[ipmQuarter.Key].so4)/ (dicDmBaseline[ipmQuarter.Key].so4< CommonClass.RrfLimit ? CommonClass.RrfLimit :dicDmBaseline[ipmQuarter.Key].so4), 4);
                                    ipmDay.Value.rrfNO3 = Math.Round((dicDmFuture[ipmQuarter.Key].no3 < CommonClass.RrfLimit ? CommonClass.RrfLimit :dicDmFuture[ipmQuarter.Key].no3)/ (dicDmBaseline[ipmQuarter.Key].no3< CommonClass.RrfLimit ? CommonClass.RrfLimit :dicDmBaseline[ipmQuarter.Key].no3), 4);
                                    ipmDay.Value.rrfNH4 = Math.Round((dicDmFuture[ipmQuarter.Key].nh4 < CommonClass.RrfLimit ? CommonClass.RrfLimit : dicDmFuture[ipmQuarter.Key].nh4) / (dicDmBaseline[ipmQuarter.Key].nh4 < CommonClass.RrfLimit ? CommonClass.RrfLimit : dicDmBaseline[ipmQuarter.Key].nh4), 4);
                                    //salt的RRF要分不同的情况：若salt为NaN,则设为1
                                    if (Double.IsNaN(dicDmBaseline[ipmQuarter.Key].salt))
                                        ipmDay.Value.rrfSalt = 1;
                                    else
                                        ipmDay.Value.rrfSalt = CommonClass.ToFixed(dicDmFuture[ipmQuarter.Key].salt / dicDmBaseline[ipmQuarter.Key].salt, 4);

                                    ipmDay.Value.fCrustal = ipmDay.Value.bCrustal * ipmDay.Value.rrfCrustal;
                                    ipmDay.Value.fEC = ipmDay.Value.bEC * ipmDay.Value.rrfEC;
                                    ipmDay.Value.fOCMmb = ipmDay.Value.bOCMmb * ipmDay.Value.rrfOC;
                                    ipmDay.Value.fSO4 = ipmDay.Value.bSO4 * ipmDay.Value.rrfSO4;
                                    ipmDay.Value.fNO3r = ipmDay.Value.bNO3r * ipmDay.Value.rrfNO3;
                                    ipmDay.Value.fSalt = ipmDay.Value.bSalt * ipmDay.Value.rrfSalt;
                                    //calculate NH4
                                    #region NH4
                                    if (dailyPMAnalysisConfiguration.pm25CalculationOptionsD.doCalcNH4fromDON)
                                    {
                                        ipmDay.Value.fNH4 = ipmDay.Value.bDON * ipmDay.Value.fSO4 + 0.29 * ipmDay.Value.fNO3r;
                                    }
                                    else if (dailyPMAnalysisConfiguration.pm25CalculationOptionsD.doCalcNH4fromRRF)
                                    {
                                        ipmDay.Value.fNH4 = ipmDay.Value.bNH4 * ipmDay.Value.rrfNH4;
                                    }
                                    #endregion
                                    //--------------pbw--------------
                                    CommonClass.CalculationWater(ipmDay.Value.fSO4, ipmDay.Value.fNO3r, ipmDay.Value.fNH4, ipmDay.Value.bDON, ref ipmDay.Value.fWater);
                                    ipmDay.Value.fWater = Double.IsNaN(ipmDay.Value.fWater) ? -9 : ipmDay.Value.fWater;
                                    ipmDay.Value.rrfWater = (ipmDay.Value.fWater == -9 || ipmDay.Value.bWater == 0) ? -9 : Math.Round(ipmDay.Value.fWater / ipmDay.Value.bWater, 4);
                                    //对于daily 分析中的future pm25，不包括salt。
                                    ipmDay.Value.fPM25 = (ipmDay.Value.fCrustal == -9 || ipmDay.Value.fNH4 == -9 || ipmDay.Value.fSO4 == -9 || ipmDay.Value.fEC == -9 || ipmDay.Value.fNO3r == -9 || ipmDay.Value.fOCMmb == -9 || ipmDay.Value.fWater == -9 || ipmDay.Value.fSalt == -9) ? -9 : ipmDay.Value.fCrustal + ipmDay.Value.fNH4 + ipmDay.Value.fSO4 + ipmDay.Value.fEC + ipmDay.Value.fNO3r + ipmDay.Value.fOCMmb + ipmDay.Value.fWater + ipmDay.Value.fSalt + Convert.ToDouble(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass);
                                }
                            }
                        }
                        #endregion
                    }
                }
                #region dv period
                if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                {
                    for (int i = 0; i < lstAllYearsAllDaysPeriod.Count; i++)
                    {
                        foreach (KeyValuePair<string, Monitors> k in lstAllYearsAllDaysPeriod[i])
                        {
                            if (k.Value.dicOfficialPM25Daily == null) continue;
                            if (!dicModelDataPeriod.ContainsKey(k.Key))
                            {
                                #region
                                if (!dicQuarterlyPeakModel.ContainsKey(k.Value.monitorGridcell)) continue;
                                int Col = Convert.ToInt32(k.Value.monitorGridcell) / 1000;
                                int Row = Convert.ToInt32(k.Value.monitorGridcell) % 1000;
                                List<string> lstArround = new List<string>();
                                //首先根据gridtype获取周围的网格数
                                switch (dailyPMAnalysisConfiguration.modelDataOptionsD.temporalAdjustmentAtMonitorGridPoint)
                                {
                                    case "1x1":
                                        lstArround.Add(k.Value.monitorGridcell);
                                        break;
                                    case "3x3":
                                        for (int i3 = -1; i3 <= 1; i3++)
                                        {
                                            for (int j3 = -1; j3 <= 1; j3++)
                                            {
                                                lstArround.Add(((Col + i3) * 1000 + (Row + j3)).ToString());
                                            }
                                        }
                                        break;
                                    case "5x5":
                                        for (int i5 = -2; i5 <= 2; i5++)
                                        {
                                            for (int j5 = -2; j5 <= 2; j5++)
                                            {
                                                lstArround.Add(((Col + i5) * 1000 + (Row + j5)).ToString());
                                            }
                                        }
                                        break;
                                    case "7x7":
                                        for (int i7 = -3; i7 <= 3; i7++)
                                        {
                                            for (int j7 = -3; j7 <= 3; j7++)
                                            {
                                                lstArround.Add(((Col + i7) * 1000 + (Row + j7)).ToString());
                                            }
                                        }
                                        break;
                                }
                                #endregion
                                #region
                                var query = dicQuarterlyPeakModel.Where(p => lstArround.Contains(p.Key));
                                int iQueryCount = query.Count();
                                if (iQueryCount > 0)
                                {
                                    dicModelDataPeriod.Add(k.Key, new DailyModelMonitor()
                                    {
                                        id = k.Value.id,
                                        dicBaseSpecies = new Dictionary<string, ModelDataSpecies>(),
                                        dicFutureSpecies = new Dictionary<string, ModelDataSpecies>(),
                                    });

                                    Dictionary<string, ModelDataSpecies> dicDmBaseline = new Dictionary<string, ModelDataSpecies>();
                                    Dictionary<string, ModelDataSpecies> dicDmFuture = new Dictionary<string, ModelDataSpecies>();
                                    //根据选项求结果:mean/max
                                    #region
                                    switch (dailyPMAnalysisConfiguration.modelDataOptionsD.temporalAdjustmentType)
                                    {
                                        case "Mean":
                                            for (int j = 0; j < iQueryCount; j++)
                                            {
                                                KeyValuePair<string, DailyModelMonitor> kin = query.ToArray()[j];
                                                foreach (KeyValuePair<string, ModelDataSpecies> kBase in kin.Value.dicBaseSpecies)
                                                {
                                                    if (dicDmBaseline.ContainsKey(kBase.Key))
                                                    {
                                                        dicDmBaseline[kBase.Key].crustal += kBase.Value.crustal;
                                                        dicDmBaseline[kBase.Key].nh4 += kBase.Value.nh4;
                                                        dicDmBaseline[kBase.Key].so4 += kBase.Value.so4;
                                                        dicDmBaseline[kBase.Key].ec += kBase.Value.ec;
                                                        dicDmBaseline[kBase.Key].no3 += kBase.Value.no3;
                                                        dicDmBaseline[kBase.Key].oc += kBase.Value.oc;
                                                        dicDmBaseline[kBase.Key].cm += kBase.Value.cm;
                                                        dicDmBaseline[kBase.Key].salt += kBase.Value.salt;
                                                    }
                                                    else
                                                    {
                                                        dicDmBaseline.Add(kBase.Key, new ModelDataSpecies()
                                                        {
                                                            crustal = kBase.Value.crustal,
                                                            nh4 = kBase.Value.nh4,
                                                            so4 = kBase.Value.so4,
                                                            ec = kBase.Value.ec,
                                                            no3 = kBase.Value.no3,
                                                            oc = kBase.Value.oc,
                                                            cm = kBase.Value.cm,
                                                            salt = kBase.Value.salt,
                                                        });
                                                    }
                                                }
                                                foreach (KeyValuePair<string, ModelDataSpecies> kControl in kin.Value.dicFutureSpecies)
                                                {
                                                    if (dicDmFuture.ContainsKey(kControl.Key))
                                                    {
                                                        dicDmFuture[kControl.Key].crustal += kControl.Value.crustal;
                                                        dicDmFuture[kControl.Key].nh4 += kControl.Value.nh4;
                                                        dicDmFuture[kControl.Key].so4 += kControl.Value.so4;
                                                        dicDmFuture[kControl.Key].ec += kControl.Value.ec;
                                                        dicDmFuture[kControl.Key].no3 += kControl.Value.no3;
                                                        dicDmFuture[kControl.Key].oc += kControl.Value.oc;
                                                        dicDmFuture[kControl.Key].cm += kControl.Value.cm;
                                                        dicDmFuture[kControl.Key].salt += kControl.Value.salt;
                                                    }
                                                    else
                                                    {
                                                        dicDmFuture.Add(kControl.Key, new ModelDataSpecies()
                                                        {
                                                            crustal = kControl.Value.crustal,
                                                            nh4 = kControl.Value.nh4,
                                                            so4 = kControl.Value.so4,
                                                            ec = kControl.Value.ec,
                                                            no3 = kControl.Value.no3,
                                                            oc = kControl.Value.oc,
                                                            cm = kControl.Value.cm,
                                                            salt = kControl.Value.salt,
                                                        });
                                                    }
                                                }
                                            }
                                            //------------calculate mean--------------
                                            foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicDmBaseline)
                                            {
                                                dicDmBaseline[kBase.Key].crustal = dicDmBaseline[kBase.Key].crustal / iQueryCount;
                                                dicDmBaseline[kBase.Key].nh4 = dicDmBaseline[kBase.Key].nh4 / iQueryCount;
                                                dicDmBaseline[kBase.Key].so4 = dicDmBaseline[kBase.Key].so4 / iQueryCount;
                                                dicDmBaseline[kBase.Key].ec = dicDmBaseline[kBase.Key].ec / iQueryCount;
                                                dicDmBaseline[kBase.Key].no3 = dicDmBaseline[kBase.Key].no3 / iQueryCount;
                                                dicDmBaseline[kBase.Key].oc = dicDmBaseline[kBase.Key].oc / iQueryCount;
                                                dicDmBaseline[kBase.Key].cm = dicDmBaseline[kBase.Key].cm / iQueryCount;
                                                dicDmBaseline[kBase.Key].salt = dicDmBaseline[kBase.Key].salt / iQueryCount;
                                            }
                                            foreach (KeyValuePair<string, ModelDataSpecies> kControl in dicDmFuture)
                                            {
                                                dicDmFuture[kControl.Key].crustal = dicDmFuture[kControl.Key].crustal / iQueryCount;
                                                dicDmFuture[kControl.Key].nh4 = dicDmFuture[kControl.Key].nh4 / iQueryCount;
                                                dicDmFuture[kControl.Key].so4 = dicDmFuture[kControl.Key].so4 / iQueryCount;
                                                dicDmFuture[kControl.Key].ec = dicDmFuture[kControl.Key].ec / iQueryCount;
                                                dicDmFuture[kControl.Key].no3 = dicDmFuture[kControl.Key].no3 / iQueryCount;
                                                dicDmFuture[kControl.Key].oc = dicDmFuture[kControl.Key].oc / iQueryCount;
                                                dicDmFuture[kControl.Key].cm = dicDmFuture[kControl.Key].cm / iQueryCount;
                                                dicDmFuture[kControl.Key].salt = dicDmFuture[kControl.Key].salt / iQueryCount;
                                            }
                                            dicModelDataPeriod[k.Key].dicBaseSpecies = dicDmBaseline;
                                            dicModelDataPeriod[k.Key].dicFutureSpecies = dicDmFuture;
                                            break;
                                        case "Maximum":
                                            for (int j = 0; j < query.Count(); j++)
                                            {
                                                KeyValuePair<string, DailyModelMonitor> kin = query.ToArray()[j];
                                                foreach (KeyValuePair<string, ModelDataSpecies> kBase in kin.Value.dicBaseSpecies)
                                                {
                                                    if (!dicDmBaseline.ContainsKey(kBase.Key))
                                                    {
                                                        dicDmBaseline.Add(kBase.Key, new ModelDataSpecies()
                                                        {
                                                            crustal = kBase.Value.crustal,
                                                            nh4 = kBase.Value.nh4,
                                                            so4 = kBase.Value.so4,
                                                            ec = kBase.Value.ec,
                                                            no3 = kBase.Value.no3,
                                                            oc = kBase.Value.oc,
                                                            cm = kBase.Value.cm,
                                                            salt = kBase.Value.salt,
                                                        });
                                                    }
                                                    else
                                                    {
                                                        if (dicDmBaseline[kBase.Key].crustal < kBase.Value.crustal)
                                                            dicDmBaseline[kBase.Key].crustal = kBase.Value.crustal;
                                                        if (dicDmBaseline[kBase.Key].nh4 < kBase.Value.nh4)
                                                            dicDmBaseline[kBase.Key].nh4 = kBase.Value.nh4;
                                                        if (dicDmBaseline[kBase.Key].so4 < kBase.Value.so4)
                                                            dicDmBaseline[kBase.Key].so4 = kBase.Value.so4;
                                                        if (dicDmBaseline[kBase.Key].ec < kBase.Value.ec)
                                                            dicDmBaseline[kBase.Key].ec = kBase.Value.ec;
                                                        if (dicDmBaseline[kBase.Key].no3 < kBase.Value.no3)
                                                            dicDmBaseline[kBase.Key].no3 = kBase.Value.no3;
                                                        if (dicDmBaseline[kBase.Key].oc < kBase.Value.oc)
                                                            dicDmBaseline[kBase.Key].oc = kBase.Value.oc;
                                                        if (dicDmBaseline[kBase.Key].cm < kBase.Value.cm)
                                                            dicDmBaseline[kBase.Key].cm = kBase.Value.cm;
                                                        if (dicDmBaseline[kBase.Key].salt < kBase.Value.salt)
                                                            dicDmBaseline[kBase.Key].salt = kBase.Value.salt;
                                                    }
                                                }
                                                foreach (KeyValuePair<string, ModelDataSpecies> kControl in kin.Value.dicFutureSpecies)
                                                {
                                                    if (!dicDmFuture.ContainsKey(kControl.Key))
                                                    {
                                                        dicDmFuture.Add(kControl.Key, new ModelDataSpecies()
                                                        {
                                                            crustal = kControl.Value.crustal,
                                                            nh4 = kControl.Value.nh4,
                                                            so4 = kControl.Value.so4,
                                                            ec = kControl.Value.ec,
                                                            no3 = kControl.Value.no3,
                                                            oc = kControl.Value.oc,
                                                            cm = kControl.Value.cm,
                                                            salt = kControl.Value.salt,
                                                        });
                                                    }
                                                    else
                                                    {
                                                        if (dicDmFuture[kControl.Key].crustal < kControl.Value.crustal)
                                                            dicDmFuture[kControl.Key].crustal = kControl.Value.crustal;
                                                        if (dicDmFuture[kControl.Key].nh4 < kControl.Value.nh4)
                                                            dicDmFuture[kControl.Key].nh4 = kControl.Value.nh4;
                                                        if (dicDmFuture[kControl.Key].so4 < kControl.Value.so4)
                                                            dicDmFuture[kControl.Key].so4 = kControl.Value.so4;
                                                        if (dicDmFuture[kControl.Key].ec < kControl.Value.ec)
                                                            dicDmFuture[kControl.Key].ec = kControl.Value.ec;
                                                        if (dicDmFuture[kControl.Key].no3 < kControl.Value.no3)
                                                            dicDmFuture[kControl.Key].no3 = kControl.Value.no3;
                                                        if (dicDmFuture[kControl.Key].oc < kControl.Value.oc)
                                                            dicDmFuture[kControl.Key].oc = kControl.Value.oc;
                                                        if (dicDmFuture[kControl.Key].cm < kControl.Value.cm)
                                                            dicDmFuture[kControl.Key].cm = kControl.Value.cm;
                                                        if (dicDmFuture[kControl.Key].salt < kControl.Value.salt)
                                                            dicDmFuture[kControl.Key].salt = kControl.Value.salt;
                                                    }
                                                }
                                            }
                                            foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicDmBaseline)
                                            {
                                                dicDmBaseline[kBase.Key].crustal = dicDmBaseline[kBase.Key].crustal / iQueryCount;
                                                dicDmBaseline[kBase.Key].nh4 = dicDmBaseline[kBase.Key].nh4 / iQueryCount;
                                                dicDmBaseline[kBase.Key].so4 = dicDmBaseline[kBase.Key].so4 / iQueryCount;
                                                dicDmBaseline[kBase.Key].ec = dicDmBaseline[kBase.Key].ec / iQueryCount;
                                                dicDmBaseline[kBase.Key].no3 = dicDmBaseline[kBase.Key].no3 / iQueryCount;
                                                dicDmBaseline[kBase.Key].oc = dicDmBaseline[kBase.Key].oc / iQueryCount;
                                                dicDmBaseline[kBase.Key].cm = dicDmBaseline[kBase.Key].cm / iQueryCount;
                                                dicDmBaseline[kBase.Key].salt = dicDmBaseline[kBase.Key].salt / iQueryCount;
                                            }
                                            foreach (KeyValuePair<string, ModelDataSpecies> kControl in dicDmFuture)
                                            {
                                                dicDmFuture[kControl.Key].crustal = dicDmFuture[kControl.Key].crustal / iQueryCount;
                                                dicDmFuture[kControl.Key].nh4 = dicDmFuture[kControl.Key].nh4 / iQueryCount;
                                                dicDmFuture[kControl.Key].so4 = dicDmFuture[kControl.Key].so4 / iQueryCount;
                                                dicDmFuture[kControl.Key].ec = dicDmFuture[kControl.Key].ec / iQueryCount;
                                                dicDmFuture[kControl.Key].no3 = dicDmFuture[kControl.Key].no3 / iQueryCount;
                                                dicDmFuture[kControl.Key].oc = dicDmFuture[kControl.Key].oc / iQueryCount;
                                                dicDmFuture[kControl.Key].cm = dicDmFuture[kControl.Key].cm / iQueryCount;
                                                dicDmFuture[kControl.Key].salt = dicDmFuture[kControl.Key].salt / iQueryCount;
                                            }
                                            dicModelDataPeriod[k.Key].dicBaseSpecies = dicDmBaseline;
                                            dicModelDataPeriod[k.Key].dicFutureSpecies = dicDmFuture;
                                            break;
                                    }
                                    #endregion
                                }
                                #endregion
                            }
                            #region
                            foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQ in k.Value.dicOfficialPM25Daily)
                            {
                                foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kY in kQ.Value)
                                {
                                    foreach (KeyValuePair<string, PM25Monitors> kD in kY.Value)
                                    {
                                        kD.Value.rrfCrustal = CommonClass.ToFixed(dicModelDataPeriod[k.Key].dicFutureSpecies[kQ.Key].crustal / dicModelDataPeriod[k.Key].dicBaseSpecies[kQ.Key].crustal, 4);
                                        kD.Value.rrfEC = CommonClass.ToFixed(dicModelDataPeriod[k.Key].dicFutureSpecies[kQ.Key].ec / dicModelDataPeriod[k.Key].dicBaseSpecies[kQ.Key].ec, 4);
                                        kD.Value.rrfOC = CommonClass.ToFixed(dicModelDataPeriod[k.Key].dicFutureSpecies[kQ.Key].oc / dicModelDataPeriod[k.Key].dicBaseSpecies[kQ.Key].oc, 4);
                                        kD.Value.rrfSO4 = CommonClass.ToFixed(dicModelDataPeriod[k.Key].dicFutureSpecies[kQ.Key].so4 / dicModelDataPeriod[k.Key].dicBaseSpecies[kQ.Key].so4, 4);
                                        kD.Value.rrfNO3 = CommonClass.ToFixed(dicModelDataPeriod[k.Key].dicFutureSpecies[kQ.Key].no3 / dicModelDataPeriod[k.Key].dicBaseSpecies[kQ.Key].no3, 4);
                                        kD.Value.rrfNH4 = CommonClass.ToFixed(dicModelDataPeriod[k.Key].dicFutureSpecies[kQ.Key].nh4 / dicModelDataPeriod[k.Key].dicBaseSpecies[kQ.Key].nh4, 4);
                                        //salt的RRF要分不同的情况：若salt为NaN,则设为1
                                        if (Double.IsNaN(dicModelDataPeriod[k.Key].dicBaseSpecies[kQ.Key].salt))
                                            kD.Value.rrfSalt = 1;
                                        else
                                            kD.Value.rrfSalt = CommonClass.ToFixed(dicModelDataPeriod[k.Key].dicFutureSpecies[kQ.Key].salt / dicModelDataPeriod[k.Key].dicBaseSpecies[kQ.Key].salt, 4);

                                        kD.Value.fCrustal = kD.Value.bCrustal * kD.Value.rrfCrustal;
                                        kD.Value.fEC = kD.Value.bEC * kD.Value.rrfEC;
                                        kD.Value.fOCMmb = kD.Value.bOCMmb * kD.Value.rrfOC;
                                        kD.Value.fSO4 = kD.Value.bSO4 * kD.Value.rrfSO4;
                                        kD.Value.fNO3r = kD.Value.bNO3r * kD.Value.rrfNO3;
                                        kD.Value.fSalt = kD.Value.bSalt * kD.Value.rrfSalt;
                                        //calculate NH4
                                        #region NH4
                                        if (dailyPMAnalysisConfiguration.pm25CalculationOptionsD.doCalcNH4fromDON)
                                        {
                                            kD.Value.fNH4 = kD.Value.bDON * kD.Value.fSO4 + 0.29 * kD.Value.fNO3r;
                                        }
                                        else if (dailyPMAnalysisConfiguration.pm25CalculationOptionsD.doCalcNH4fromRRF)
                                        {
                                            kD.Value.fNH4 = kD.Value.bNH4 * kD.Value.rrfNH4;
                                        }
                                        #endregion
                                        //----------pbw------------
                                        CommonClass.CalculationWater(kD.Value.fSO4, kD.Value.fNO3r, kD.Value.fNH4, kD.Value.bDON, ref kD.Value.fWater);
                                        kD.Value.rrfWater = (kD.Value.fWater == -9 || kD.Value.bWater == 0) ? -9 : Math.Round(kD.Value.fWater / kD.Value.bWater, 4);
                                        //对于daily 分析中的future pm25，包括salt。
                                        kD.Value.fPM25 = (kD.Value.fCrustal == -9 || kD.Value.fNH4 == -9 || kD.Value.fSO4 == -9 || kD.Value.fEC == -9 || kD.Value.fNO3r == -9 || kD.Value.fOCMmb == -9 || kD.Value.fWater == -9 || kD.Value.fSalt == -9) ? -9 : kD.Value.fCrustal + kD.Value.fNH4 + kD.Value.fSO4 + kD.Value.fEC + kD.Value.fNO3r + kD.Value.fOCMmb + kD.Value.fWater + kD.Value.fSalt + Convert.ToDouble(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass);
                                    }
                                }
                            }
                            #endregion
                        }
                    }
                }
                dicModelDataPeriod.Clear();
                GC.Collect();
                #endregion

                //转换数据存储格式
                #region
                Dictionary<string, Monitors> dicAllYearsAllDaysDaily = new Dictionary<string, Monitors>();
                //Dictionary<string, PM25Monitors> dicDays = new Dictionary<string, PM25Monitors>();
                Dictionary<string, Dictionary<string, PM25Monitors>> dicYears = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                #region
                foreach (KeyValuePair<string, Monitors> k in dicPMMonitors)
                {
                    if (k.Value.id == "371830014")
                    {
                    }
                    foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQuarter in dicPMMonitors[k.Key].dicOfficialPM25Daily)
                    {
                        foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kYear in dicPMMonitors[k.Key].dicOfficialPM25Daily[kQuarter.Key])
                        {
                            Dictionary<string, PM25Monitors> dicDays = new Dictionary<string, PM25Monitors>();// kYear.Value;
                            foreach (KeyValuePair<string, PM25Monitors> kYearValue in kYear.Value)
                            {
                                dicDays.Add(kYearValue.Key, ClonePM25Monitors(kYearValue.Value));
                            }
                            dicYears = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                            if (dicAllYearsAllDaysDaily.ContainsKey(k.Key))
                            {
                                if (dicAllYearsAllDaysDaily[k.Key].dicOfficialPM25Daily.ContainsKey(kYear.Key))
                                {
                                    dicAllYearsAllDaysDaily[k.Key].dicOfficialPM25Daily[kYear.Key].Add(kQuarter.Key, dicDays);
                                }
                                else
                                {
                                    dicYears.Add(kQuarter.Key, dicDays);
                                    dicAllYearsAllDaysDaily[k.Key].dicOfficialPM25Daily.Add(kYear.Key, dicYears);
                                }
                            }
                            else
                            {
                                dicAllYearsAllDaysDaily.Add(k.Key, new Monitors()
                                {
                                    id = k.Value.id,
                                    type = k.Value.type,
                                    lat = k.Value.lat,
                                    stateName = k.Value.stateName,
                                    countyName = k.Value.countyName,
                                    longitude = k.Value.longitude,
                                    monitorGridcell = k.Value.monitorGridcell,
                                    rank98 = k.Value.rank98,
                                    dicOfficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                                    dicPMDaily = new Dictionary<string, Dictionary<string, PM25Monitors>>(),
                                });
                                dicYears.Add(kQuarter.Key, dicDays);
                                dicAllYearsAllDaysDaily[k.Key].dicOfficialPM25Daily.Add(kYear.Key, dicYears);
                            }
                        }
                    }
                    if (dicAllYearsAllDaysDaily.ContainsKey(k.Key))
                    {
                        foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> iYear in dicAllYearsAllDaysDaily[k.Key].dicOfficialPM25Daily)
                        {
                            Dictionary<string, PM25Monitors> dicDays =  new Dictionary<string, PM25Monitors>();
                            foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> iQuarter in dicAllYearsAllDaysDaily[k.Key].dicOfficialPM25Daily[iYear.Key])
                            {
                                foreach (KeyValuePair<string, PM25Monitors> iDays in iQuarter.Value)
                                {
                                    dicDays.Add(iDays.Key,ClonePM25Monitors( iDays.Value));
                                }
                            }
                            dicAllYearsAllDaysDaily[k.Key].dicPMDaily.Add(iYear.Key, dicDays);
                        }
                    }
                }
                #endregion
                #region dv period
                List<Dictionary<string, Monitors>> lstDailyFilePeriod = new List<Dictionary<string, Monitors>>();
                if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                {
                    for (int i = 0; i < lstAllYearsAllDaysPeriod.Count; i++)
                    {
                        lstDailyFilePeriod.Add(new Dictionary<string, Monitors>());
                    }
                    for (int i = 0; i < lstAllYearsAllDaysPeriod.Count; i++)
                    {
                        foreach (KeyValuePair<string, Monitors> k in lstAllYearsAllDaysPeriod[i])
                        {
                            if (k.Value.dicOfficialPM25Daily == null) continue;
                            foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQ in k.Value.dicOfficialPM25Daily)
                            {
                                foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kY in kQ.Value)
                                {
                                    Dictionary<string, PM25Monitors> dicDays = new Dictionary<string, PM25Monitors>();// ClonePM25Monitors(kY.Value);
                                    foreach (KeyValuePair<string, PM25Monitors> kTmp in kY.Value)
                                    {
                                        dicDays.Add(kTmp.Key, ClonePM25Monitors(kTmp.Value));
                                    }
                                    dicYears = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                    if (lstDailyFilePeriod[i].ContainsKey(k.Key))
                                    {
                                        if (lstDailyFilePeriod[i][k.Key].dicOfficialPM25Daily.ContainsKey(kY.Key))
                                        {
                                            lstDailyFilePeriod[i][k.Key].dicOfficialPM25Daily[kY.Key].Add(kQ.Key, dicDays);
                                        }
                                        else
                                        {
                                            dicYears.Add(kQ.Key, dicDays);
                                            lstDailyFilePeriod[i][k.Key].dicOfficialPM25Daily.Add(kY.Key, dicYears);
                                        }
                                    }
                                    else
                                    {
                                        lstDailyFilePeriod[i].Add(k.Key, new Monitors()
                                        {
                                            id = k.Value.id,
                                            type = k.Value.type,
                                            lat = k.Value.lat,
                                            stateName = k.Value.stateName,
                                            countyName = k.Value.countyName,
                                            longitude = k.Value.longitude,
                                            monitorGridcell = k.Value.monitorGridcell,
                                            rank98 = k.Value.rank98,
                                            dicOfficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                                            dicPMDaily = new Dictionary<string, Dictionary<string, PM25Monitors>>(),
                                        });
                                        dicYears.Add(kQ.Key, dicDays);
                                        lstDailyFilePeriod[i][k.Key].dicOfficialPM25Daily.Add(kY.Key, dicYears);
                                    }
                                }
                            }
                            if (lstDailyFilePeriod[i][k.Key].dicOfficialPM25Daily.Count < lstAllYearsAllDaysPeriod.Count)//3)
                            {
                                lstDailyFilePeriod[i][k.Key].dicOfficialPM25Daily = null;
                                lstDailyFilePeriod[i][k.Key].dicPMDaily = null;
                                continue;
                            }
                            if (lstDailyFilePeriod[i].ContainsKey(k.Key))
                            {
                                foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> iYear in lstDailyFilePeriod[i][k.Key].dicOfficialPM25Daily)
                                {
                                    Dictionary<string, PM25Monitors> dicDays =  new Dictionary<string, PM25Monitors>();
                                    foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> iQuarter in lstDailyFilePeriod[i][k.Key].dicOfficialPM25Daily[iYear.Key])
                                    {
                                        foreach (KeyValuePair<string, PM25Monitors> iDays in iQuarter.Value)
                                        {
                                            dicDays.Add(iDays.Key,ClonePM25Monitors( iDays.Value));
                                        }
                                    }
                                    lstDailyFilePeriod[i][k.Key].dicPMDaily.Add(iYear.Key, dicDays);
                                }
                            }
                        }
                    }
                }
                #endregion
                #endregion
                dicPMMonitors.Clear();
                lstAllYearsAllDaysPeriod.Clear();
                GC.Collect();
                if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doQuarterlyPeakFilesPoint)
                {
                    SaveDailyFiles(CommonClass.CurrentBaseScenario, dicAllYearsAllDaysDaily, "");
                    if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                    {
                        for (int i = 0; i < lstDailyFilePeriod.Count; i++)
                        {
                            SaveDailyFiles(CommonClass.CurrentBaseScenario, lstDailyFilePeriod[i], " Period " + (i + 1).ToString());
                        }
                    }
                }
                GC.Collect();
                #endregion

                #region
                //---------get All Years High Days--------------
                Dictionary<string, Monitors> dicHighDaysDaily = new Dictionary<string, Monitors>();
                GetAllYearHighDays(dailyPMAnalysisConfiguration, ref dicHighDaysDaily, dicAllYearsAllDaysDaily);
                #region
                List<Dictionary<string, Monitors>> lstHighDaysPeriod = new List<Dictionary<string, Monitors>>();
                if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                {
                    GetAllYearHighDaysPeriod(ref lstHighDaysPeriod, lstDailyFilePeriod, dicDesignValuePeriod.Count);
                }
                #endregion
                if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doQuarterlyPeakFilesPoint)
                {
                    SaveAllYearHighDays(CommonClass.CurrentBaseScenario, dicHighDaysDaily, "");
                    if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                    {
                        for (int i = 0; i < lstHighDaysPeriod.Count; i++)
                        {
                            SaveAllYearHighDays(CommonClass.CurrentBaseScenario, lstHighDaysPeriod[i], " Period " + (i + 1).ToString());
                        }
                    }
                }
                #endregion

                #region get forecasted pm25 value for each year according to rank98
                List<Dictionary<string, PMPoint>> lstDailyPointPeriod = new List<Dictionary<string, PMPoint>>();
                if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                {
                    for (int i = 0; i < dicDesignValuePeriod.Count; i++)
                    {
                        lstDailyPointPeriod.Add(new Dictionary<string, PMPoint>());
                    }
                }
                Dictionary<string, PMPoint> dicDailyPoint = new Dictionary<string, PMPoint>();
                GetDailyPointFutureVlues(dailyPMAnalysisConfiguration, dicHighDaysDaily, dicDesignValuePeriod, dicComCodePeriod, ref dicDailyPoint, ref lstDailyPointPeriod);
                dicAllYearsAllDaysDaily.Clear();
                GC.Collect();

                if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doStandardAnalysis)
                {
                    SaveDailyPmPoint(CommonClass.CurrentBaseScenario, dicDailyPoint, "");
                    if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                    {
                        for (int i = 0; i < lstDailyPointPeriod.Count; i++)
                        {
                            SaveDailyPmPoint(CommonClass.CurrentBaseScenario, lstDailyPointPeriod[i], " Period " + (i + 1).ToString());
                        }
                    }
                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doQuarterlyPeakModelData)
                    {
                        SaveUsedModelData(CommonClass.CurrentBaseScenario, lstUsedModelData, dicQuarterlyPeakModel, isSalt, baseYear, futureYear);
                    }
                }
                dicQuarterlyPeakModel.Clear();
                GC.Collect();

                if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doHighCountySites)
                {
                    SaveHighCountySites(CommonClass.CurrentBaseScenario, dicDailyPoint, "");
                    if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                    {
                        for (int i = 0; i < lstDailyPointPeriod.Count; i++)
                        {
                            SaveHighCountySites(CommonClass.CurrentBaseScenario, lstDailyPointPeriod[i], " Period " + (i + 1).ToString());
                        }
                    }
                }
                lstDailyPointPeriod.Clear();
                GC.Collect();
                #endregion
                _endTime = DateTime.Now;
                CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish interpolating FRM sites temporal adj: " + CommonClass.TotalTime + " s.");
                CommonClass.CurrentLog = "Finish interpolating FRM sites temporal adj: " + CommonClass.TotalTime + " s.";
                #endregion
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        #region get files from csv
        public static string GetModelDataDailyBaseline(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, DailyModelMonitor> dicQuarterlyPeakModel, ref  bool isSalt, ref string baseYear, ref Dictionary<string, Dictionary<string, List<string>>> dicBaseDays)
        {
            try
            {
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iCrustal = -1, iNH4 = -1, iSO4 = -1, iEC = -1, iNO3 = -1, iOC = -1, iPM25 = -1, iCM = -1, iSalt = -1;//index of fields
                string quarter = "";
                Dictionary<string, Dictionary<string, int>> dicDayCount = new Dictionary<string, Dictionary<string, int>>();//记录天数
                #region read daily baseline model data
                FileStream fs = new FileStream(dailyPMAnalysisConfiguration.dataInputD.baselineModelFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                    int i = 0;
                    #region
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Trim().ToLower().Replace("\"", ""))
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_type":
                                iType = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "date":
                                iDate = i;
                                break;
                            case "crustal":
                                iCrustal = i;
                                break;
                            case "nh4":
                                iNH4 = i;
                                break;
                            case "so4":
                                iSO4 = i;
                                break;
                            case "ec":
                                iEC = i;
                                break;
                            case "no3":
                                iNO3 = i;
                                break;
                            case "oc":
                                iOC = i;
                                break;
                            case "pm25":
                                iPM25 = i;
                                break;
                            case "cm":
                                iCM = i;
                                break;
                            case "salt":
                                iSalt = i;
                                break;
                        }
                        i++;
                    }
                    #endregion
                    if (iSalt != -1) isSalt = true;
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        strLineArray = strLine.Split(new char[] { ',' });
                        if (baseYear == "")
                            baseYear = strLineArray[iDate].ToString().Replace("\"", "").Substring(0, 4);
                        switch (strLineArray[iDate].ToString().Replace("\"", "").Substring(4, 2))
                        {
                            case "01":
                            case "02":
                            case "03":
                                quarter = "1";
                                break;
                            case "04":
                            case "05":
                            case "06":
                                quarter = "2";
                                break;
                            case "07":
                            case "08":
                            case "09":
                                quarter = "3";
                                break;
                            case "10":
                            case "11":
                            case "12":
                                quarter = "4";
                                break;
                        }
                        #region
                        Dictionary<string, ModelDataSpecies> dicDailySpecies = new Dictionary<string, ModelDataSpecies>();
                        if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseXTopPercent)
                        {
                            #region
                            int topXpercentCount = Convert.ToInt32(Math.Round(Convert.ToDouble(92 * 0.01 * dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_UseXTopPercent)));
                            if (dicQuarterlyPeakModel.ContainsKey(strLineArray[iID].ToString().Replace("\"", "").Trim()))
                            {
                                if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Replace("\"", "").Trim()].dicBaseDailySpecies.ContainsKey(quarter))
                                {
                                    //--------当天数＜设定的天数时直接将其加入到dictionary中，反之则需要进行判断：若降序排列的最后一个pm值小于读取的pm值，则将其去掉，添加新的天；若等于最末尾的值则将其加入到其中。
                                    //--------小于读取数值时还需要判断是否有值相同的天，相同的则也需要去掉
                                    if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Replace("\"", "").Trim()].dicBaseDailySpecies[quarter].Count < topXpercentCount)
                                    {
                                        dicQuarterlyPeakModel[strLineArray[iID].ToString().Replace("\"", "").Trim()].dicBaseDailySpecies[quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                        {
                                            crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                            nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                            so4 = Convert.ToSingle(strLineArray[iSO4]),
                                            oc = Convert.ToSingle(strLineArray[iOC]),
                                            no3 = Convert.ToSingle(strLineArray[iNO3]),
                                            ec = Convert.ToSingle(strLineArray[iEC]),
                                            pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                            cm = Convert.ToSingle(strLineArray[iCM]),
                                        });
                                    }
                                    else
                                    {
                                        if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Replace("\"", "").Trim()].dicBaseDailySpecies[quarter].OrderByDescending(p => p.Value.pm25).Last().Value.pm25 == Convert.ToSingle(strLineArray[iPM25]))
                                        {
                                            dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                            {
                                                crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                                nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                                so4 = Convert.ToSingle(strLineArray[iSO4]),
                                                oc = Convert.ToSingle(strLineArray[iOC]),
                                                no3 = Convert.ToSingle(strLineArray[iNO3]),
                                                ec = Convert.ToSingle(strLineArray[iEC]),
                                                pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                                cm = Convert.ToSingle(strLineArray[iCM]),
                                            });
                                        }
                                        else if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].OrderByDescending(p => p.Value.pm25).Last().Value.pm25 < Convert.ToSingle(strLineArray[iPM25]))
                                        {
                                            float pm = dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].OrderByDescending(p => p.Value.pm25).Last().Value.pm25;
                                            List<string> lstKeySmall = dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Where(p => p.Value.pm25 == pm).Select(p => p.Key).ToList();
                                            if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Count - lstKeySmall.Count() + 1 < topXpercentCount)
                                            {
                                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                                {
                                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                                });
                                            }
                                            else
                                            {
                                                for (int iCount = 0; iCount < lstKeySmall.Count(); iCount++)
                                                {
                                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Remove(lstKeySmall[iCount]);
                                                }
                                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                                {
                                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                                });
                                            }
                                        }
                                    }
                                    dicDayCount[strLineArray[iID].ToString().Trim().Replace("\"", "")][quarter] += 1;
                                }
                                else
                                {
                                    dicDailySpecies.Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                    {
                                        crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                        nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                        so4 = Convert.ToSingle(strLineArray[iSO4]),
                                        oc = Convert.ToSingle(strLineArray[iOC]),
                                        no3 = Convert.ToSingle(strLineArray[iNO3]),
                                        ec = Convert.ToSingle(strLineArray[iEC]),
                                        pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                        cm = Convert.ToSingle(strLineArray[iCM]),
                                    });
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies.Add(quarter, dicDailySpecies);
                                    dicDayCount[strLineArray[iID].ToString().Trim().Replace("\"", "")].Add(quarter, 1);
                                }
                            }
                            else
                            {
                                dicQuarterlyPeakModel.Add(strLineArray[iID].ToString().Trim().Replace("\"", ""), new DailyModelMonitor()
                                {
                                    id = strLineArray[iID].ToString().Trim().Replace("\"", ""),
                                    type = strLineArray[iType].ToString().Replace("\"", ""),
                                    lat = Convert.ToDouble(strLineArray[iLat]),
                                    longitude = Convert.ToDouble(strLineArray[iLong]),
                                    dicBaseDailySpecies = new Dictionary<string, Dictionary<string, ModelDataSpecies>>(),
                                });
                                dicDailySpecies.Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                {
                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                });
                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies.Add(quarter, dicDailySpecies);
                                dicDayCount.Add(strLineArray[iID].ToString().Trim().Replace("\"", ""), new Dictionary<string, int>());
                                dicDayCount[strLineArray[iID].ToString().Trim().Replace("\"", "")].Add(quarter, 1);
                            }
                            #endregion
                        }
                        else if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseTopXNumber)
                        {
                            #region
                            if (dicQuarterlyPeakModel.ContainsKey(strLineArray[iID].ToString().Trim().Replace("\"", "")))
                            {
                                if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies.ContainsKey(quarter))
                                {
                                    if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Count < dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_UseTopXNumber)
                                    {
                                        dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                        {
                                            crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                            nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                            so4 = Convert.ToSingle(strLineArray[iSO4]),
                                            oc = Convert.ToSingle(strLineArray[iOC]),
                                            no3 = Convert.ToSingle(strLineArray[iNO3]),
                                            ec = Convert.ToSingle(strLineArray[iEC]),
                                            pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                            cm = Convert.ToSingle(strLineArray[iCM]),
                                        });
                                    }
                                    else
                                    {
                                        if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].OrderByDescending(p => p.Value.pm25).Last().Value.pm25 == Convert.ToSingle(strLineArray[iPM25]))
                                        {
                                            dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                            {
                                                crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                                nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                                so4 = Convert.ToSingle(strLineArray[iSO4]),
                                                oc = Convert.ToSingle(strLineArray[iOC]),
                                                no3 = Convert.ToSingle(strLineArray[iNO3]),
                                                ec = Convert.ToSingle(strLineArray[iEC]),
                                                pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                                cm = Convert.ToSingle(strLineArray[iCM]),
                                            });
                                        }
                                        else if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].OrderByDescending(p => p.Value.pm25).Last().Value.pm25 < Convert.ToSingle(strLineArray[iPM25]))
                                        {
                                            float pm = dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].OrderByDescending(p => p.Value.pm25).Last().Value.pm25;
                                            List<string> lstKeySmall = dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Where(p => p.Value.pm25 == pm).Select(p => p.Key).ToList();
                                            if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Count - lstKeySmall.Count() + 1 < dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_UseTopXNumber)
                                            {
                                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                                {
                                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                                });
                                            }
                                            else
                                            {
                                                for (int iCount = 0; iCount < lstKeySmall.Count(); iCount++)
                                                {
                                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Remove(lstKeySmall[iCount]);
                                                }
                                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies[quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                                {
                                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                                });
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    dicDailySpecies.Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                    {
                                        crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                        nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                        so4 = Convert.ToSingle(strLineArray[iSO4]),
                                        oc = Convert.ToSingle(strLineArray[iOC]),
                                        no3 = Convert.ToSingle(strLineArray[iNO3]),
                                        ec = Convert.ToSingle(strLineArray[iEC]),
                                        pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                        cm = Convert.ToSingle(strLineArray[iCM]),
                                    });
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies.Add(quarter, dicDailySpecies);
                                }
                            }
                            else
                            {
                                dicQuarterlyPeakModel.Add(strLineArray[iID].ToString().Trim().Replace("\"", ""), new DailyModelMonitor()
                                {
                                    id = strLineArray[iID].ToString().Trim().Replace("\"", ""),
                                    type = strLineArray[iType].ToString().Replace("\"", ""),
                                    lat = Convert.ToDouble(strLineArray[iLat]),
                                    longitude = Convert.ToDouble(strLineArray[iLong]),
                                    //baseYear = strLineArray[iDate].Substring(0, 4),
                                    dicBaseDailySpecies = new Dictionary<string, Dictionary<string, ModelDataSpecies>>(),
                                });
                                dicDailySpecies.Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""), new ModelDataSpecies()
                                {
                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                });
                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseDailySpecies.Add(quarter, dicDailySpecies);
                            }
                            #endregion
                        }
                        else if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseAllModelDaysGreaterThan)
                        {
                            #region
                            if (Convert.ToSingle(strLineArray[iPM25]) < dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_UseAllModelDaysGreaterThan) continue;
                            if (dicQuarterlyPeakModel.ContainsKey(strLineArray[iID].ToString().Trim().Replace("\"", "")))
                            {
                                if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies.ContainsKey(quarter))
                                {
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies[quarter].crustal += Convert.ToSingle(strLineArray[iCrustal]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies[quarter].nh4 += Convert.ToSingle(strLineArray[iNH4]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies[quarter].so4 += Convert.ToSingle(strLineArray[iSO4]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies[quarter].oc += Convert.ToSingle(strLineArray[iOC]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies[quarter].no3 += Convert.ToSingle(strLineArray[iNO3]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies[quarter].ec += Convert.ToSingle(strLineArray[iEC]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies[quarter].pm25 += Convert.ToSingle(strLineArray[iPM25]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies[quarter].cm += Convert.ToSingle(strLineArray[iCM]);
                                    dicDayCount[strLineArray[iID].ToString().Trim().Replace("\"", "")][quarter] += 1;
                                    dicBaseDays[strLineArray[iID].ToString().Trim().Replace("\"", "")][quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""));
                                }
                                else
                                {
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies.Add(quarter, new ModelDataSpecies()
                                    {
                                        crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                        nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                        so4 = Convert.ToSingle(strLineArray[iSO4]),
                                        oc = Convert.ToSingle(strLineArray[iOC]),
                                        no3 = Convert.ToSingle(strLineArray[iNO3]),
                                        ec = Convert.ToSingle(strLineArray[iEC]),
                                        pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                        cm = Convert.ToSingle(strLineArray[iCM]),
                                    });
                                    dicDayCount[strLineArray[iID].ToString().Trim().Replace("\"", "")].Add(quarter, 1);

                                    dicBaseDays[strLineArray[iID].ToString().Trim().Replace("\"", "")].Add(quarter, new List<string>());
                                    dicBaseDays[strLineArray[iID].ToString().Trim().Replace("\"", "")][quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""));
                                }
                            }
                            else
                            {
                                dicQuarterlyPeakModel.Add(strLineArray[iID].ToString().Trim().Replace("\"", ""), new DailyModelMonitor()
                                {
                                    id = strLineArray[iID].ToString().Trim().Replace("\"", ""),
                                    type = strLineArray[iType].ToString().Replace("\"", ""),
                                    lat = Convert.ToDouble(strLineArray[iLat]),
                                    longitude = Convert.ToDouble(strLineArray[iLong]),
                                    //baseYear = strLineArray[iDate].Substring(0, 4),
                                    dicBaseSpecies = new Dictionary<string, ModelDataSpecies>(),
                                });
                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicBaseSpecies.Add(quarter, new ModelDataSpecies()
                                {
                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                });
                                dicDayCount.Add(strLineArray[iID].ToString().Trim().Replace("\"", ""), new Dictionary<string, int>());
                                dicDayCount[strLineArray[iID].ToString().Trim().Replace("\"", "")].Add(quarter, 1);

                                dicBaseDays.Add(strLineArray[iID].ToString().Trim().Replace("\"", ""), new Dictionary<string, List<string>>());
                                dicBaseDays[strLineArray[iID].ToString().Trim().Replace("\"", "")].Add(quarter, new List<string>());
                                dicBaseDays[strLineArray[iID].ToString().Trim().Replace("\"", "")][quarter].Add(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""));
                            }
                            #endregion
                        }
                        #endregion
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                //---------计算quarterly peak model data--------------
                foreach (KeyValuePair<string, DailyModelMonitor> k in dicQuarterlyPeakModel)
                {
                    if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseAllModelDaysGreaterThan)
                    {
                        #region
                        foreach (KeyValuePair<string, ModelDataSpecies> kQ in k.Value.dicBaseSpecies)
                        {
                            if (dicDayCount[k.Key][kQ.Key] < dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_MinumumNumberOfDaysRequiredAboveFixedAmount)
                            {
                                dicBaseDays[k.Key].Remove(kQ.Key);
                                continue;
                            }
                            int iCount = dicDayCount[k.Key][kQ.Key];
                            kQ.Value.crustal = kQ.Value.crustal / iCount;
                            kQ.Value.nh4 = kQ.Value.nh4 / iCount;
                            kQ.Value.so4 = kQ.Value.so4 / iCount;
                            kQ.Value.ec = kQ.Value.ec / iCount;
                            kQ.Value.no3 = kQ.Value.no3 / iCount;
                            kQ.Value.oc = kQ.Value.oc / iCount;
                            kQ.Value.pm25 = kQ.Value.pm25 / iCount;
                            kQ.Value.cm = kQ.Value.cm / iCount;

                            if (iSalt != -1) kQ.Value.salt = kQ.Value.salt / iCount;
                            else kQ.Value.salt = float.NaN;
                        }
                        #endregion
                    }
                    else if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseXTopPercent)
                    {
                        if (k.Value.dicBaseSpecies == null)
                            k.Value.dicBaseSpecies = new Dictionary<string, ModelDataSpecies>();
                        int percentXCount = 0;
                        Dictionary<string, ModelDataSpecies> dic = new Dictionary<string, ModelDataSpecies>();
                        #region
                        foreach (KeyValuePair<string, Dictionary<string, ModelDataSpecies>> kQ in k.Value.dicBaseDailySpecies)
                        {
                            percentXCount = Convert.ToInt32(Math.Round(Convert.ToDouble(dicDayCount[k.Key][kQ.Key] * 0.01 * dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_UseXTopPercent)));
                            if (kQ.Value.Count <= percentXCount)
                            {
                                #region
                                k.Value.dicBaseSpecies.Add(kQ.Key, new ModelDataSpecies()
                                {
                                    crustal = kQ.Value.Select(p => p.Value.crustal).Average(),
                                    nh4 = kQ.Value.Select(p => p.Value.nh4).Average(),
                                    so4 = kQ.Value.Select(p => p.Value.so4).Average(),
                                    ec = kQ.Value.Select(p => p.Value.ec).Average(),
                                    no3 = kQ.Value.Select(p => p.Value.no3).Average(),
                                    oc = kQ.Value.Select(p => p.Value.oc).Average(),
                                    pm25 = kQ.Value.Select(p => p.Value.pm25).Average(),
                                    cm = kQ.Value.Select(p => p.Value.cm).Average(),
                                });
                                if (iSalt != -1) dicQuarterlyPeakModel[k.Key].dicBaseSpecies[kQ.Key].salt = kQ.Value.Select(p => p.Value.salt).Average();
                                else dicQuarterlyPeakModel[k.Key].dicBaseSpecies[kQ.Key].salt = float.NaN;

                                if (dicBaseDays.ContainsKey(k.Key))
                                {
                                    dicBaseDays[k.Key].Add(kQ.Key, kQ.Value.Select(p => p.Key).ToList());
                                }
                                else
                                {
                                    dicBaseDays.Add(k.Key, new Dictionary<string, List<string>>());
                                    dicBaseDays[k.Key].Add(kQ.Key, kQ.Value.Select(p => p.Key).ToList());
                                }
                                #endregion
                            }
                            else
                            {
                                List<float> lstPM = kQ.Value.OrderByDescending(p => p.Value.pm25).Skip(percentXCount - 1).Take(1).Select(p => p.Value.pm25).ToList();
                                dic = kQ.Value.Where(p => p.Value.pm25 >= lstPM[0]).ToDictionary(P => P.Key, P => P.Value);
                                #region
                                k.Value.dicBaseSpecies.Add(kQ.Key, new ModelDataSpecies()
                                {
                                    crustal = dic.Select(p => p.Value.crustal).Average(),
                                    nh4 = dic.Select(p => p.Value.nh4).Average(),
                                    so4 = dic.Select(p => p.Value.so4).Average(),
                                    ec = dic.Select(p => p.Value.ec).Average(),
                                    no3 = dic.Select(p => p.Value.no3).Average(),
                                    oc = dic.Select(p => p.Value.oc).Average(),
                                    pm25 = dic.Select(p => p.Value.pm25).Average(),
                                    cm = dic.Select(p => p.Value.cm).Average(),
                                });
                                if (iSalt != -1) dicQuarterlyPeakModel[k.Key].dicBaseSpecies[kQ.Key].salt = dic.Select(p => p.Value.salt).Average();
                                else dicQuarterlyPeakModel[k.Key].dicBaseSpecies[kQ.Key].salt = float.NaN;

                                if (dicBaseDays.ContainsKey(k.Key))
                                {
                                    dicBaseDays[k.Key].Add(kQ.Key, dic.Select(p => p.Key).ToList());
                                }
                                else
                                {
                                    dicBaseDays.Add(k.Key, new Dictionary<string, List<string>>());
                                    dicBaseDays[k.Key].Add(kQ.Key, dic.Select(p => p.Key).ToList());
                                }
                                #endregion
                            }
                        }
                        k.Value.dicBaseDailySpecies = null;
                        #endregion
                    }
                    else if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseTopXNumber)
                    {
                        if (k.Value.dicBaseSpecies == null)
                            k.Value.dicBaseSpecies = new Dictionary<string, ModelDataSpecies>();
                        #region
                        foreach (KeyValuePair<string, Dictionary<string, ModelDataSpecies>> kQ in k.Value.dicBaseDailySpecies)
                        {
                            k.Value.dicBaseSpecies.Add(kQ.Key, new ModelDataSpecies()
                            {
                                crustal = kQ.Value.Select(p => p.Value.crustal).Average(),
                                nh4 = kQ.Value.Select(p => p.Value.nh4).Average(),
                                so4 = kQ.Value.Select(p => p.Value.so4).Average(),
                                ec = kQ.Value.Select(p => p.Value.ec).Average(),
                                no3 = kQ.Value.Select(p => p.Value.no3).Average(),
                                oc = kQ.Value.Select(p => p.Value.oc).Average(),
                                pm25 = kQ.Value.Select(p => p.Value.pm25).Average(),
                                cm = kQ.Value.Select(p => p.Value.cm).Average(),
                            });
                            if (iSalt != -1) dicQuarterlyPeakModel[k.Key].dicBaseSpecies[kQ.Key].salt = kQ.Value.Select(p => p.Value.salt).Average();
                            else dicQuarterlyPeakModel[k.Key].dicBaseSpecies[kQ.Key].salt = float.NaN;

                            if (dicBaseDays.ContainsKey(k.Key))
                            {
                                dicBaseDays[k.Key].Add(kQ.Key, kQ.Value.Select(p => p.Key).ToList());
                            }
                            else
                            {
                                dicBaseDays.Add(k.Key, new Dictionary<string, List<string>>());
                                dicBaseDays[k.Key].Add(kQ.Key, kQ.Value.Select(p => p.Key).ToList());
                            }
                        }
                        #endregion
                        k.Value.dicBaseDailySpecies = null;
                    }
                }
                dicDayCount.Clear();
                GC.Collect();
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        public static string GetModelDataDailyFuture(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, DailyModelMonitor> dicQuarterlyPeakModel, ref  bool isSalt, ref string futureYear, Dictionary<string, Dictionary<string, List<string>>> dicBaseDays)
        {
            try
            {
                #region read daily future model data
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iCrustal = -1, iNH4 = -1, iSO4 = -1, iEC = -1, iNO3 = -1, iOC = -1, iPM25 = -1, iCM = -1, iSalt = -1;
                string quarter = "";
                FileStream fs = new FileStream(dailyPMAnalysisConfiguration.dataInputD.forecastModelFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                    int i = 0;
                    #region
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Trim().ToLower().Replace("\"", ""))
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_type":
                                iType = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "date":
                                iDate = i;
                                break;
                            case "crustal":
                                iCrustal = i;
                                break;
                            case "nh4":
                                iNH4 = i;
                                break;
                            case "so4":
                                iSO4 = i;
                                break;
                            case "ec":
                                iEC = i;
                                break;
                            case "no3":
                                iNO3 = i;
                                break;
                            case "oc":
                                iOC = i;
                                break;
                            case "pm25":
                                iPM25 = i;
                                break;
                            case "cm":
                                iCM = i;
                                break;
                            case "salt":
                                iSalt = i;
                                break;
                        }
                        i++;
                    }
                    #endregion
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        strLineArray = strLine.Split(new char[] { ',' });
                        if (futureYear == "")
                            futureYear = strLineArray[iDate].ToString().Substring(0, 4).Replace("\"", "");
                        switch (strLineArray[iDate].ToString().Substring(4, 2).Replace("\"", ""))
                        {
                            case "01":
                            case "02":
                            case "03":
                                quarter = "1";
                                break;
                            case "04":
                            case "05":
                            case "06":
                                quarter = "2";
                                break;
                            case "07":
                            case "08":
                            case "09":
                                quarter = "3";
                                break;
                            case "10":
                            case "11":
                            case "12":
                                quarter = "4";
                                break;
                        }
                        Dictionary<string, ModelDataSpecies> dicDailySpecies = new Dictionary<string, ModelDataSpecies>();
                        if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseXTopPercent)
                        {
                            #region
                            if (dicQuarterlyPeakModel.ContainsKey(strLineArray[iID].ToString().Replace("\"", "").Trim()))
                            {
                                if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies == null)
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies = new Dictionary<string, ModelDataSpecies>();
                                if (!dicBaseDays[strLineArray[iID].ToString().Trim().Replace("\"", "")][quarter].Contains(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""))) continue;
                                if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies.ContainsKey(quarter))
                                {
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].crustal += Convert.ToSingle(strLineArray[iCrustal]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].nh4 += Convert.ToSingle(strLineArray[iNH4]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].so4 += Convert.ToSingle(strLineArray[iSO4]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].oc += Convert.ToSingle(strLineArray[iOC]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].no3 += Convert.ToSingle(strLineArray[iNO3]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].ec += Convert.ToSingle(strLineArray[iEC]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].pm25 += Convert.ToSingle(strLineArray[iPM25]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].cm += Convert.ToSingle(strLineArray[iCM]);
                                }
                                else
                                {
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies.Add(quarter, new ModelDataSpecies()
                                    {
                                        crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                        nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                        so4 = Convert.ToSingle(strLineArray[iSO4]),
                                        oc = Convert.ToSingle(strLineArray[iOC]),
                                        no3 = Convert.ToSingle(strLineArray[iNO3]),
                                        ec = Convert.ToSingle(strLineArray[iEC]),
                                        pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                        cm = Convert.ToSingle(strLineArray[iCM]),
                                    });
                                }
                            }
                            #endregion
                        }
                        else if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseTopXNumber)
                        {
                            #region
                            if (dicQuarterlyPeakModel.ContainsKey(strLineArray[iID].ToString().Trim().Replace("\"", "")))
                            {
                                if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies == null)
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies = new Dictionary<string, ModelDataSpecies>();
                                if (!dicBaseDays[strLineArray[iID].ToString().Trim().Replace("\"", "")][quarter].Contains(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""))) continue;
                                if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies.ContainsKey(quarter))
                                {
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].crustal += Convert.ToSingle(strLineArray[iCrustal]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].nh4 += Convert.ToSingle(strLineArray[iNH4]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].so4 += Convert.ToSingle(strLineArray[iSO4]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].oc += Convert.ToSingle(strLineArray[iOC]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].no3 += Convert.ToSingle(strLineArray[iNO3]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].ec += Convert.ToSingle(strLineArray[iEC]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].pm25 += Convert.ToSingle(strLineArray[iPM25]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].cm += Convert.ToSingle(strLineArray[iCM]);
                                }
                                else
                                {
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies.Add(quarter, new ModelDataSpecies()
                                    {
                                        crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                        nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                        so4 = Convert.ToSingle(strLineArray[iSO4]),
                                        oc = Convert.ToSingle(strLineArray[iOC]),
                                        no3 = Convert.ToSingle(strLineArray[iNO3]),
                                        ec = Convert.ToSingle(strLineArray[iEC]),
                                        pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                        cm = Convert.ToSingle(strLineArray[iCM]),
                                    });
                                }
                            }
                            #endregion
                        }
                        else if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseAllModelDaysGreaterThan)
                        {
                            #region
                            if (dicQuarterlyPeakModel.ContainsKey(strLineArray[iID].ToString().Trim().Replace("\"", "")))
                            {
                                if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies == null)
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies = new Dictionary<string, ModelDataSpecies>();
                                if (!dicBaseDays[strLineArray[iID].ToString().Trim().Replace("\"", "")][quarter].Contains(strLineArray[iDate].Substring(4).ToString().Replace("\"", ""))) continue;
                                if (dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies.ContainsKey(quarter))
                                {
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].crustal += Convert.ToSingle(strLineArray[iCrustal]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].nh4 += Convert.ToSingle(strLineArray[iNH4]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].so4 += Convert.ToSingle(strLineArray[iSO4]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].oc += Convert.ToSingle(strLineArray[iOC]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].no3 += Convert.ToSingle(strLineArray[iNO3]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].ec += Convert.ToSingle(strLineArray[iEC]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].pm25 += Convert.ToSingle(strLineArray[iPM25]);
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies[quarter].cm += Convert.ToSingle(strLineArray[iCM]);
                                }
                                else
                                {
                                    dicQuarterlyPeakModel[strLineArray[iID].ToString().Trim().Replace("\"", "")].dicFutureSpecies.Add(quarter, new ModelDataSpecies()
                                    {
                                        crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                        nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                        so4 = Convert.ToSingle(strLineArray[iSO4]),
                                        oc = Convert.ToSingle(strLineArray[iOC]),
                                        no3 = Convert.ToSingle(strLineArray[iNO3]),
                                        ec = Convert.ToSingle(strLineArray[iEC]),
                                        pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                        cm = Convert.ToSingle(strLineArray[iCM]),
                                    });
                                }
                            }
                            #endregion
                        }
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                //---------计算quarterly peak model data--------------
                #region quarterly peak model data
                foreach (KeyValuePair<string, DailyModelMonitor> k in dicQuarterlyPeakModel)
                {
                    if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseAllModelDaysGreaterThan)
                    {
                        #region
                        foreach (KeyValuePair<string, ModelDataSpecies> kQ in k.Value.dicFutureSpecies)
                        {
                            if (!dicBaseDays[k.Key].ContainsKey(kQ.Key)) continue;
                            int iCount = dicBaseDays[k.Key][kQ.Key].Count;
                            kQ.Value.crustal = kQ.Value.crustal / iCount;
                            kQ.Value.nh4 = kQ.Value.nh4 / iCount;
                            kQ.Value.so4 = kQ.Value.so4 / iCount;
                            kQ.Value.ec = kQ.Value.ec / iCount;
                            kQ.Value.no3 = kQ.Value.no3 / iCount;
                            kQ.Value.oc = kQ.Value.oc / iCount;
                            kQ.Value.pm25 = kQ.Value.pm25 / iCount;
                            kQ.Value.cm = kQ.Value.cm / iCount;

                            if (iSalt != -1) kQ.Value.salt = kQ.Value.salt / iCount;
                            else kQ.Value.salt = float.NaN;
                        }
                        #endregion
                    }
                    else if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseXTopPercent)
                    {
                        #region
                        foreach (KeyValuePair<string, ModelDataSpecies> kQ in k.Value.dicFutureSpecies)
                        {
                            int iCount = dicBaseDays[k.Key][kQ.Key].Count;
                            kQ.Value.crustal = kQ.Value.crustal / iCount;
                            kQ.Value.nh4 = kQ.Value.nh4 / iCount;
                            kQ.Value.so4 = kQ.Value.so4 / iCount;
                            kQ.Value.ec = kQ.Value.ec / iCount;
                            kQ.Value.no3 = kQ.Value.no3 / iCount;
                            kQ.Value.oc = kQ.Value.oc / iCount;
                            kQ.Value.pm25 = kQ.Value.pm25 / iCount;
                            kQ.Value.cm = kQ.Value.cm / iCount;

                            if (iSalt != -1) kQ.Value.salt = kQ.Value.salt / iCount;
                            else kQ.Value.salt = float.NaN;
                        }
                        #endregion
                    }
                    else if (dailyPMAnalysisConfiguration.modelDataOptionsD.RRF_DoUseTopXNumber)
                    {
                        #region
                        foreach (KeyValuePair<string, ModelDataSpecies> kQ in k.Value.dicFutureSpecies)
                        {
                            int iCount = dicBaseDays[k.Key][kQ.Key].Count;
                            kQ.Value.crustal = kQ.Value.crustal / iCount;
                            kQ.Value.nh4 = kQ.Value.nh4 / iCount;
                            kQ.Value.so4 = kQ.Value.so4 / iCount;
                            kQ.Value.ec = kQ.Value.ec / iCount;
                            kQ.Value.no3 = kQ.Value.no3 / iCount;
                            kQ.Value.oc = kQ.Value.oc / iCount;
                            kQ.Value.pm25 = kQ.Value.pm25 / iCount;
                            kQ.Value.cm = kQ.Value.cm / iCount;

                            if (iSalt != -1) kQ.Value.salt = kQ.Value.salt / iCount;
                            else kQ.Value.salt = float.NaN;
                        }
                        #endregion
                    }
                }
                dicBaseDays.Clear();
                GC.Collect();
                #endregion
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        public static string GetModelDataQuarterly(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, DailyModelMonitor> dicQuarterlyPeakModel, ref  bool isSalt, ref string baseModelYear, ref string futureModelYear)
        {
            try
            {
                //----------base model data------------------
                #region baseline quarterly peak model data
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iCrustal = -1, iNH4 = -1, iSO4 = -1, iEC = -1, iNO3 = -1, iOC = -1, iPM25 = -1, iCM = -1, iSalt = -1;//index of fields
                string quarter = "";
                FileStream fs = new FileStream(dailyPMAnalysisConfiguration.dataInputD.baselineModelFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                try
                {
                    using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                    {
                        string strLine = csv.ReadLine();
                        string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                        int i = 0;
                        #region
                        while (i < strLineArray.Length)
                        {
                            string s = strLineArray[i];
                            switch (s.Trim().ToLower().Replace("\"", ""))
                            {
                                case "_id":
                                    iID = i;
                                    break;
                                case "_type":
                                    iType = i;
                                    break;
                                case "lat":
                                    iLat = i;
                                    break;
                                case "long":
                                    iLong = i;
                                    break;
                                case "date":
                                    iDate = i;
                                    break;
                                case "crustal":
                                    iCrustal = i;
                                    break;
                                case "nh4":
                                    iNH4 = i;
                                    break;
                                case "so4":
                                    iSO4 = i;
                                    break;
                                case "ec":
                                    iEC = i;
                                    break;
                                case "no3":
                                    iNO3 = i;
                                    break;
                                case "oc":
                                    iOC = i;
                                    break;
                                case "pm25":
                                    iPM25 = i;
                                    break;
                                case "cm":
                                    iCM = i;
                                    break;
                                case "salt":
                                    iSalt = i;
                                    break;
                            }
                            i++;
                        }
                        #endregion
                        if (iSalt != -1) isSalt = true;
                        while (strLine != null)
                        {
                            strLine = csv.ReadLine();
                            if (strLine == null) break;
                            strLineArray = strLine.Split(new char[] { ',' });
                            if (baseModelYear == "") baseModelYear = strLineArray[iDate].ToString().Replace("\"", "").Substring(0, 4);
                            switch (strLineArray[iDate].ToString().Replace("\"", "").Substring(4, 2))
                            {
                                case "01":
                                case "02":
                                case "03":
                                    quarter = "1";
                                    break;
                                case "04":
                                case "05":
                                case "06":
                                    quarter = "2";
                                    break;
                                case "07":
                                case "08":
                                case "09":
                                    quarter = "3";
                                    break;
                                case "10":
                                case "11":
                                case "12":
                                    quarter = "4";
                                    break;
                            }
                            if (dicQuarterlyPeakModel.ContainsKey(strLineArray[iID].ToString().Replace("\"", "").Trim()))
                            {
                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Replace("\"", "").Trim()].dicBaseSpecies.Add(quarter, new ModelDataSpecies()
                                {
                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                });
                            }
                            else
                            {
                                dicQuarterlyPeakModel.Add(strLineArray[iID].ToString().Replace("\"", "").Trim(), new DailyModelMonitor()
                                {
                                    id = strLineArray[iID].ToString().Replace("\"", "").Trim(),
                                    type = strLineArray[iType].ToString().Replace("\"", ""),
                                    lat = Convert.ToDouble(strLineArray[iLat]),
                                    longitude = Convert.ToDouble(strLineArray[iLong]),
                                    dicBaseSpecies = new Dictionary<string, ModelDataSpecies>(),
                                    dicFutureSpecies = new Dictionary<string, ModelDataSpecies>(),
                                });
                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Replace("\"", "").Trim()].dicBaseSpecies.Add(quarter, new ModelDataSpecies()
                                {
                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                });
                            }
                        }
                        csv.Dispose(); fs.Dispose();
                        GC.Collect();
                    };
                }
                catch
                {
                    return "wrongBaseline";
                }
                #endregion

                _endTime = DateTime.Now;
                CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                CommonClass.CurrentLog = "Finish reading model data: " + CommonClass.TotalTime + " s.";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                _beginTime = DateTime.Now;
                CommonClass.CurrentLog = "Read model data \"" + Path.GetFileName(dailyPMAnalysisConfiguration.dataInputD.forecastModelFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                //---------future model data---------------
                #region future quarterly peak model data
                fs = new FileStream(dailyPMAnalysisConfiguration.dataInputD.forecastModelFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                try
                {
                    using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                    {
                        string strLine = csv.ReadLine();
                        string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                        int i = 0;
                        #region
                        while (i < strLineArray.Length)
                        {
                            string s = strLineArray[i];
                            switch (s.Trim().ToLower().Replace("\"", ""))
                            {
                                case "_id":
                                    iID = i;
                                    break;
                                case "_type":
                                    iType = i;
                                    break;
                                case "lat":
                                    iLat = i;
                                    break;
                                case "long":
                                    iLong = i;
                                    break;
                                case "date":
                                    iDate = i;
                                    break;
                                case "crustal":
                                    iCrustal = i;
                                    break;
                                case "nh4":
                                    iNH4 = i;
                                    break;
                                case "so4":
                                    iSO4 = i;
                                    break;
                                case "ec":
                                    iEC = i;
                                    break;
                                case "no3":
                                    iNO3 = i;
                                    break;
                                case "oc":
                                    iOC = i;
                                    break;
                                case "pm25":
                                    iPM25 = i;
                                    break;
                                case "cm":
                                    iCM = i;
                                    break;
                                case "salt":
                                    iSalt = i;
                                    break;
                            }
                            i++;
                        }
                        #endregion
                        if (iSalt != -1) isSalt = true;
                        while (strLine != null)
                        {
                            strLine = csv.ReadLine();
                            if (strLine == null) break;
                            strLineArray = strLine.Split(new char[] { ',' });
                            if (futureModelYear == "") futureModelYear = strLineArray[iDate].ToString().Replace("\"", "").Substring(0, 4);
                            switch (strLineArray[iDate].ToString().Replace("\"", "").Substring(4, 2))
                            {
                                case "01":
                                case "02":
                                case "03":
                                    quarter = "1";
                                    break;
                                case "04":
                                case "05":
                                case "06":
                                    quarter = "2";
                                    break;
                                case "07":
                                case "08":
                                case "09":
                                    quarter = "3";
                                    break;
                                case "10":
                                case "11":
                                case "12":
                                    quarter = "4";
                                    break;
                            }
                            if (dicQuarterlyPeakModel.ContainsKey(strLineArray[iID].ToString().Replace("\"", "").Trim()))
                            {
                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Replace("\"", "").Trim()].dicFutureSpecies.Add(quarter, new ModelDataSpecies()
                                {
                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                });
                            }
                            else
                            {
                                dicQuarterlyPeakModel[strLineArray[iID].ToString().Replace("\"", "").Trim()].dicFutureSpecies.Add(quarter, new ModelDataSpecies()
                                {
                                    crustal = Convert.ToSingle(strLineArray[iCrustal]),
                                    nh4 = Convert.ToSingle(strLineArray[iNH4]),
                                    so4 = Convert.ToSingle(strLineArray[iSO4]),
                                    oc = Convert.ToSingle(strLineArray[iOC]),
                                    no3 = Convert.ToSingle(strLineArray[iNO3]),
                                    ec = Convert.ToSingle(strLineArray[iEC]),
                                    pm25 = Convert.ToSingle(strLineArray[iPM25]),
                                    cm = Convert.ToSingle(strLineArray[iCM]),
                                });
                            }
                        }
                        csv.Dispose(); fs.Dispose();
                        GC.Collect();
                    };
                }
                catch
                {
                    return "wrongFuture";
                }
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        public static bool GetModelDataFromCMAQ(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration)
        {
            try
            {
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static string GetSpeciesMonitors(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, Monitors> dicSpeciesDaily)
        {
            try
            {
                SpeciesForFractions speciesForFractions = new SpeciesForFractions();
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iPM25 = -1, iEPA = -1, iUser = -1, iCrustal = -1, iNH4 = -1, iEC = -1, iSO4 = -1, iNO3 = -1, iSalt = -1;
                int iOCB = -1, iNO3r = -1, iDON = -1, iMeasuredFM = -1;
                int count = 0, count1 = 0, count2 = 0, count3 = 0, count4 = 0;
                string id = "", type = "", date = "";
                //string errorInfo = "";
                //bool isOKall = true;
                Dictionary<string, SpeciesForFractions> dicSpecies1 = new Dictionary<string, SpeciesForFractions>();
                Dictionary<string, SpeciesForFractions> dicSpecies2 = new Dictionary<string, SpeciesForFractions>();
                Dictionary<string, SpeciesForFractions> dicSpecies3 = new Dictionary<string, SpeciesForFractions>();
                Dictionary<string, SpeciesForFractions> dicSpecies4 = new Dictionary<string, SpeciesForFractions>();
                Dictionary<string, Dictionary<string, SpeciesForFractions>> dicQYSpecies1 = new Dictionary<string, Dictionary<string, SpeciesForFractions>>();
                Dictionary<string, Dictionary<string, SpeciesForFractions>> dicQYSpecies2 = new Dictionary<string, Dictionary<string, SpeciesForFractions>>();
                Dictionary<string, Dictionary<string, SpeciesForFractions>> dicQYSpecies3 = new Dictionary<string, Dictionary<string, SpeciesForFractions>>();
                Dictionary<string, Dictionary<string, SpeciesForFractions>> dicQYSpecies4 = new Dictionary<string, Dictionary<string, SpeciesForFractions>>();
                #region
                FileStream fs = new FileStream(dailyPMAnalysisConfiguration.dataInputD.speciesMonitorDataFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                    int i = 0;
                    #region
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Replace("\"", "").Trim().ToLower())
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_type":
                                iType = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "date":
                                iDate = i;
                                break;
                            case "crustal":
                                iCrustal = i;
                                break;
                            case "ec":
                                iEC = i;
                                break;
                            case "ocb":
                                iOCB = i;
                                break;
                            case "so4":
                                iSO4 = i;
                                break;
                            case "no3":
                                iNO3 = i;
                                break;
                            case "no3r":
                                iNO3r = i;
                                break;
                            case "nh4":
                                iNH4 = i;
                                break;
                            case "salt":
                                iSalt = i;
                                break;
                            case "don":
                                iDON = i;
                                break;
                            case "measured_fm":
                                iMeasuredFM = i;
                                break;
                            case "epa_flag":
                                iEPA = i;
                                break;
                            case "user_flag":
                                iUser = i;
                                break;
                        }
                        i++;
                    }
                    #endregion
                    #region read csv
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        //try
                        //{
                            strLineArray = strLine.Split(new char[] { ',' });
                            #region
                            bool isOK = true;
                            if (Convert.ToInt32(strLineArray[iDate].Substring(0, 4).ToString()) < Convert.ToInt32(dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_StartYear)
                                || Convert.ToInt32(strLineArray[iDate].Substring(0, 4).ToString()) > Convert.ToInt32(dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_EndYear)) continue;
                            if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_EPADeletionChoice && !dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_UserDeletionChoice) //epa,default
                            {
                                if ((strLineArray[iEPA].ToString().Replace("\"", "") == "0" || strLineArray[iEPA].ToString().Replace("\"", "") == "11") && strLineArray[iMeasuredFM].Replace("\"", "") != "" && strLineArray[iMeasuredFM].Length > 0)
                                {
                                    if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_DoUseAlldailyMonitorValuesGreaterThan)
                                        if (Convert.ToDouble(strLineArray[iMeasuredFM]) < dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_UseAlldailyMonitorValuesGreaterThan) continue;
                                    isOK = ReadSpeciatedMonitorsDaily(strLineArray, ref iID, ref iType, ref iLat, ref iLong, ref iDate, ref iPM25, ref iEPA, ref iUser, ref iCrustal, ref iNH4, ref iEC, ref iSO4, ref iNO3, ref iSalt, ref iOCB, ref iNO3r, ref iDON, ref iMeasuredFM, ref id, ref date, ref type, ref speciesForFractions, ref dicSpecies1, ref dicSpecies2, ref dicSpecies3, ref dicSpecies4, ref dicQYSpecies1, ref dicQYSpecies2, ref dicQYSpecies3, ref dicQYSpecies4, ref count, ref count1, ref count2, ref count3, ref count4, ref dicSpeciesDaily);
                                }
                            }
                            else if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_EPADeletionChoice && dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_UserDeletionChoice) //epa,user
                            {
                                if ((strLineArray[iEPA].ToString().Replace("\"", "") == "0" || strLineArray[iEPA].ToString().Replace("\"", "") == "11") && (strLineArray[iUser].ToString().Replace("\"", "") == "0" || strLineArray[iUser].ToString().Replace("\"", "") == "11")
                                        && strLineArray[iMeasuredFM].ToString().Replace("\"", "") != "" && strLineArray[iMeasuredFM].Length > 0)
                                {
                                    if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_DoUseAlldailyMonitorValuesGreaterThan)
                                        if (Convert.ToDouble(strLineArray[iMeasuredFM]) < dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_UseAlldailyMonitorValuesGreaterThan) continue;
                                    isOK = ReadSpeciatedMonitorsDaily(strLineArray, ref iID, ref iType, ref iLat, ref iLong, ref iDate, ref iPM25, ref iEPA, ref iUser, ref iCrustal, ref iNH4, ref iEC, ref iSO4, ref iNO3, ref iSalt, ref iOCB, ref iNO3r, ref iDON, ref iMeasuredFM, ref id, ref date, ref type, ref speciesForFractions, ref dicSpecies1, ref dicSpecies2, ref dicSpecies3, ref dicSpecies4, ref dicQYSpecies1, ref dicQYSpecies2, ref dicQYSpecies3, ref dicQYSpecies4, ref count, ref count1, ref count2, ref count3, ref count4, ref dicSpeciesDaily);
                                }
                            }
                            else if (!dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_EPADeletionChoice && dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_UserDeletionChoice)//user
                            {
                                if ((strLineArray[iUser].ToString().Replace("\"", "") == "0" || strLineArray[iUser].ToString().Replace("\"", "") == "11")
                                        && strLineArray[iMeasuredFM].ToString().Replace("\"", "") != "" && strLineArray[iMeasuredFM].Length > 0)
                                {
                                    if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_DoUseAlldailyMonitorValuesGreaterThan)
                                        if (Convert.ToDouble(strLineArray[iMeasuredFM]) < dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_UseAlldailyMonitorValuesGreaterThan) continue;
                                    isOK = ReadSpeciatedMonitorsDaily(strLineArray, ref iID, ref iType, ref iLat, ref iLong, ref iDate, ref iPM25, ref iEPA, ref iUser, ref iCrustal, ref iNH4, ref iEC, ref iSO4, ref iNO3, ref iSalt, ref iOCB, ref iNO3r, ref iDON, ref iMeasuredFM, ref id, ref date, ref type, ref speciesForFractions, ref dicSpecies1, ref dicSpecies2, ref dicSpecies3, ref dicSpecies4, ref dicQYSpecies1, ref dicQYSpecies2, ref dicQYSpecies3, ref dicQYSpecies4, ref count, ref count1, ref count2, ref count3, ref count4, ref dicSpeciesDaily);
                                }
                            }
                            else if (!dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_EPADeletionChoice && !dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_UserDeletionChoice)//none
                            {
                                if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_DoUseAlldailyMonitorValuesGreaterThan)
                                    if (Convert.ToDouble(strLineArray[iMeasuredFM]) < dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_UseAlldailyMonitorValuesGreaterThan) continue;
                                isOK = ReadSpeciatedMonitorsDaily(strLineArray, ref iID, ref iType, ref iLat, ref iLong, ref iDate, ref iPM25, ref iEPA, ref iUser, ref iCrustal, ref iNH4, ref iEC, ref iSO4, ref iNO3, ref iSalt, ref iOCB, ref iNO3r, ref iDON, ref iMeasuredFM, ref id, ref date, ref type, ref speciesForFractions, ref dicSpecies1, ref dicSpecies2, ref dicSpecies3, ref dicSpecies4, ref dicQYSpecies1, ref dicQYSpecies2, ref dicQYSpecies3, ref dicQYSpecies4, ref count, ref count1, ref count2, ref count3, ref count4, ref dicSpeciesDaily);
                            }
                            if (!isOK)
                                return "unknow";
                            #endregion
                        //}
                        //catch
                        //{
                        //    errorInfo = "errorRow";
                        //}
                    }
                    #region readToEnd
                    if (csv.EndOfStream)
                    {
                        for (int j = 1; j <= 4; j++)
                        {
                            switch (j)
                            {
                                case 1:
                                    dicSpeciesDaily[id].dicSpeciesDailyQuarterYear.Add(Convert.ToString(j), dicQYSpecies1);
                                    break;
                                case 2:
                                    dicSpeciesDaily[id].dicSpeciesDailyQuarterYear.Add(Convert.ToString(j), dicQYSpecies2);
                                    break;
                                case 3:
                                    dicSpeciesDaily[id].dicSpeciesDailyQuarterYear.Add(Convert.ToString(j), dicQYSpecies3);
                                    break;
                                case 4:
                                    dicSpeciesDaily[id].dicSpeciesDailyQuarterYear.Add(Convert.ToString(j), dicQYSpecies4);
                                    break;
                            }
                        }
                    }
                    #endregion
                    #endregion
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                #endregion
                //if (!isOKall)
                //    errorInfo = "errorRow";
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        public static bool ReadSpeciatedMonitorsDaily(string[] strLineArray, ref int iID, ref int iType, ref int iLat, ref int iLong, ref int iDate, ref int iPM25, ref int iEPA, ref int iUser, ref int iCrustal, ref int iNH4, ref int iEC, ref int iSO4, ref int iNO3, ref int iSalt,
               ref int iOCB, ref int iNO3r, ref int iDON, ref int iMeasuredFM, ref string id, ref  string date, ref string type, ref SpeciesForFractions speciesForFractions, ref Dictionary<string, SpeciesForFractions> dicSpecies1, ref Dictionary<string, SpeciesForFractions> dicSpecies2, ref Dictionary<string, SpeciesForFractions> dicSpecies3,
          ref Dictionary<string, SpeciesForFractions> dicSpecies4, ref Dictionary<string, Dictionary<string, SpeciesForFractions>> dicQYSpecies1, ref Dictionary<string, Dictionary<string, SpeciesForFractions>> dicQYSpecies2, ref Dictionary<string, Dictionary<string, SpeciesForFractions>> dicQYSpecies3,
            ref  Dictionary<string, Dictionary<string, SpeciesForFractions>> dicQYSpecies4, ref int count, ref int count1, ref int count2, ref int count3, ref int count4, ref Dictionary<string, Monitors> dicSpeciesDaily)
        {
            try
            {
                #region
                if (strLineArray[iID].Replace("\"", "") == id && strLineArray[iDate].Substring(0, 4).Replace("\"", "") == date && strLineArray[iType].Replace("\"", "") == type)
                {
                    speciesForFractions = new SpeciesForFractions();
                    switch (strLineArray[iDate].Substring(4, 2).ToString().Replace("\"", ""))
                    {
                        case "01":
                        case "02":
                        case "03":
                            speciesForFractions.year = strLineArray[iDate].Substring(0, 4).Replace("\"", "");
                            speciesForFractions.measured_fm = Convert.ToSingle(strLineArray[iMeasuredFM]);
                            speciesForFractions.crustal = strLineArray[iCrustal].Length == 0 && strLineArray[iCrustal] == "" || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]);
                            speciesForFractions.so4 = strLineArray[iSO4].Length == 0 && strLineArray[iSO4] == "" || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]);
                            speciesForFractions.ec = strLineArray[iEC].Length == 0 && strLineArray[iEC] == "" ? float.NaN : Convert.ToSingle(strLineArray[iEC]);
                            speciesForFractions.ocb = strLineArray[iOCB].Length == 0 && strLineArray[iOCB] == "" ? float.NaN : Convert.ToSingle(strLineArray[iOCB]);
                            speciesForFractions.no3 = strLineArray[iNO3].Length == 0 && strLineArray[iNO3] == "" || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]);
                            speciesForFractions.no3r = strLineArray[iNO3r].Length == 0 && strLineArray[iNO3r] == "" || Convert.ToSingle(strLineArray[iNO3r]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3r]);
                            speciesForFractions.nh4 = strLineArray[iNH4].Length == 0 && strLineArray[iNH4] == "" || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]);
                            speciesForFractions.salt = strLineArray[iSalt].Length == 0 && strLineArray[iSalt] == "" || Convert.ToSingle(strLineArray[iSalt]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSalt]);
                            speciesForFractions.don = strLineArray[iDON].Length == 0 && strLineArray[iDON] == "" || Convert.ToSingle(strLineArray[iDON]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iDON]);
                            if (dicQYSpecies1.ContainsKey(speciesForFractions.year))
                            {
                                dicQYSpecies1[speciesForFractions.year].Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                            }
                            else
                            {
                                dicSpecies1 = new Dictionary<string, SpeciesForFractions>();
                                dicSpecies1.Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                                dicQYSpecies1.Add(speciesForFractions.year, dicSpecies1);
                            }
                            count1++;
                            break;
                        case "04":
                        case "05":
                        case "06":
                            speciesForFractions.year = strLineArray[iDate].Substring(0, 4).Replace("\"", "");
                            speciesForFractions.measured_fm = Convert.ToSingle(strLineArray[iMeasuredFM]);
                            speciesForFractions.crustal = strLineArray[iCrustal].Length == 0 && strLineArray[iCrustal] == "" || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]);
                            speciesForFractions.so4 = strLineArray[iSO4].Length == 0 && strLineArray[iSO4] == "" || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]);
                            speciesForFractions.ec = strLineArray[iEC].Length == 0 && strLineArray[iEC] == "" ? float.NaN : Convert.ToSingle(strLineArray[iEC]);
                            speciesForFractions.ocb = strLineArray[iOCB].Length == 0 && strLineArray[iOCB] == "" ? float.NaN : Convert.ToSingle(strLineArray[iOCB]);
                            speciesForFractions.no3 = strLineArray[iNO3].Length == 0 && strLineArray[iNO3] == "" || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]);
                            speciesForFractions.no3r = strLineArray[iNO3r].Length == 0 && strLineArray[iNO3r] == "" || Convert.ToSingle(strLineArray[iNO3r]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3r]);
                            speciesForFractions.nh4 = strLineArray[iNH4].Length == 0 && strLineArray[iNH4] == "" || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]);
                            speciesForFractions.salt = strLineArray[iSalt].Length == 0 && strLineArray[iSalt] == "" || Convert.ToSingle(strLineArray[iSalt]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSalt]);
                            speciesForFractions.don = strLineArray[iDON].Length == 0 && strLineArray[iDON] == "" || Convert.ToSingle(strLineArray[iDON]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iDON]);
                            if (dicQYSpecies2.ContainsKey(speciesForFractions.year))
                            {
                                dicQYSpecies2[speciesForFractions.year].Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                            }
                            else
                            {
                                dicSpecies2 = new Dictionary<string, SpeciesForFractions>();
                                dicSpecies2.Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                                dicQYSpecies2.Add(speciesForFractions.year, dicSpecies2);
                            }
                            count2++;
                            break;
                        case "07":
                        case "08":
                        case "09":
                            speciesForFractions.year = strLineArray[iDate].Substring(0, 4).Replace("\"", "");
                            speciesForFractions.measured_fm = Convert.ToSingle(strLineArray[iMeasuredFM]);
                            speciesForFractions.crustal = strLineArray[iCrustal].Length == 0 && strLineArray[iCrustal] == "" || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]);
                            speciesForFractions.so4 = strLineArray[iSO4].Length == 0 && strLineArray[iSO4] == "" || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]);
                            speciesForFractions.ec = strLineArray[iEC].Length == 0 && strLineArray[iEC] == "" ? float.NaN : Convert.ToSingle(strLineArray[iEC]);
                            speciesForFractions.ocb = strLineArray[iOCB].Length == 0 && strLineArray[iOCB] == "" ? float.NaN : Convert.ToSingle(strLineArray[iOCB]);
                            speciesForFractions.no3 = strLineArray[iNO3].Length == 0 && strLineArray[iNO3] == "" || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]);
                            speciesForFractions.no3r = strLineArray[iNO3r].Length == 0 && strLineArray[iNO3r] == "" || Convert.ToSingle(strLineArray[iNO3r]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3r]);
                            speciesForFractions.nh4 = strLineArray[iNH4].Length == 0 && strLineArray[iNH4] == "" || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]);
                            speciesForFractions.salt = strLineArray[iSalt].Length == 0 && strLineArray[iSalt] == "" || Convert.ToSingle(strLineArray[iSalt]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSalt]);
                            speciesForFractions.don = strLineArray[iDON].Length == 0 && strLineArray[iDON] == "" || Convert.ToSingle(strLineArray[iDON]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iDON]);
                            if (dicQYSpecies3.ContainsKey(speciesForFractions.year))
                            {
                                dicQYSpecies3[speciesForFractions.year].Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                            }
                            else
                            {
                                dicSpecies3 = new Dictionary<string, SpeciesForFractions>();
                                dicSpecies3.Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                                dicQYSpecies3.Add(speciesForFractions.year, dicSpecies3);
                            }
                            count3++;
                            break;
                        case "10":
                        case "11":
                        case "12":
                            speciesForFractions.year = strLineArray[iDate].Substring(0, 4).Replace("\"", "");
                            speciesForFractions.measured_fm = Convert.ToSingle(strLineArray[iMeasuredFM]);
                            speciesForFractions.crustal = strLineArray[iCrustal].Length == 0 && strLineArray[iCrustal] == "" || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]);
                            speciesForFractions.so4 = strLineArray[iSO4].Length == 0 && strLineArray[iSO4] == "" || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]);
                            speciesForFractions.ec = strLineArray[iEC].Length == 0 && strLineArray[iEC] == "" ? float.NaN : Convert.ToSingle(strLineArray[iEC]);
                            speciesForFractions.ocb = strLineArray[iOCB].Length == 0 && strLineArray[iOCB] == "" ? float.NaN : Convert.ToSingle(strLineArray[iOCB]);
                            speciesForFractions.no3 = strLineArray[iNO3].Length == 0 && strLineArray[iNO3] == "" || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]);
                            speciesForFractions.no3r = strLineArray[iNO3r].Length == 0 && strLineArray[iNO3r] == "" || Convert.ToSingle(strLineArray[iNO3r]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3r]);
                            speciesForFractions.nh4 = strLineArray[iNH4].Length == 0 && strLineArray[iNH4] == "" || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]);
                            speciesForFractions.salt = strLineArray[iSalt].Length == 0 && strLineArray[iSalt] == "" || Convert.ToSingle(strLineArray[iSalt]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSalt]);
                            speciesForFractions.don = strLineArray[iDON].Length == 0 && strLineArray[iDON] == "" || Convert.ToSingle(strLineArray[iDON]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iDON]);
                            if (dicQYSpecies4.ContainsKey(speciesForFractions.year))
                            {
                                dicQYSpecies4[speciesForFractions.year].Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                            }
                            else
                            {
                                dicSpecies4 = new Dictionary<string, SpeciesForFractions>();
                                dicSpecies4.Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                                dicQYSpecies4.Add(speciesForFractions.year, dicSpecies4);
                            }
                            count4++;
                            break;
                    }
                    count++;

                }
                else
                {
                    if (count > 0)
                    {
                        if (strLineArray[iID].Replace("\"", "") != id)
                        {
                            //为每年的四个季度添加species的值
                            #region
                            for (int j = 1; j <= 4; j++)
                            {
                                switch (j)
                                {
                                    case 1:
                                        dicSpeciesDaily[id].dicSpeciesDailyQuarterYear.Add(Convert.ToString(j), dicQYSpecies1);
                                        break;
                                    case 2:
                                        dicSpeciesDaily[id].dicSpeciesDailyQuarterYear.Add(Convert.ToString(j), dicQYSpecies2);
                                        break;
                                    case 3:
                                        dicSpeciesDaily[id].dicSpeciesDailyQuarterYear.Add(Convert.ToString(j), dicQYSpecies3);
                                        break;
                                    case 4:
                                        dicSpeciesDaily[id].dicSpeciesDailyQuarterYear.Add(Convert.ToString(j), dicQYSpecies4);
                                        break;
                                }
                            }
                            count = count1 = count2 = count3 = count4 = 0;
                            dicSpecies1 = new Dictionary<string, SpeciesForFractions>();
                            dicSpecies2 = new Dictionary<string, SpeciesForFractions>();
                            dicSpecies3 = new Dictionary<string, SpeciesForFractions>();
                            dicSpecies4 = new Dictionary<string, SpeciesForFractions>();
                            dicQYSpecies1 = new Dictionary<string, Dictionary<string, SpeciesForFractions>>();
                            dicQYSpecies2 = new Dictionary<string, Dictionary<string, SpeciesForFractions>>();
                            dicQYSpecies3 = new Dictionary<string, Dictionary<string, SpeciesForFractions>>();
                            dicQYSpecies4 = new Dictionary<string, Dictionary<string, SpeciesForFractions>>();
                            #endregion
                        }
                    }
                    id = strLineArray[iID].Replace("\"", "");
                    type = strLineArray[iType].Replace("\"", "");
                    date = strLineArray[iDate].Substring(0, 4).ToString().Replace("\"", "");
                    if (!dicSpeciesDaily.ContainsKey(id))
                    {
                        dicSpeciesDaily.Add(id, new Monitors()
                        {
                            id = id,
                            type = strLineArray[iType].Replace("\"", ""),
                            lat = Convert.ToDouble(strLineArray[iLat]),
                            longitude = Convert.ToDouble(strLineArray[iLong]),
                            dicSpeciesDailyQuarterYear = new Dictionary<string, Dictionary<string, Dictionary<string, SpeciesForFractions>>>(),
                        });
                    }
                    speciesForFractions = new SpeciesForFractions();
                    switch (strLineArray[iDate].Substring(4, 2).ToString().Replace("\"", ""))
                    {
                        case "01":
                        case "02":
                        case "03":
                            speciesForFractions.year = strLineArray[iDate].Substring(0, 4).Replace("\"", "");
                            speciesForFractions.measured_fm = Convert.ToSingle(strLineArray[iMeasuredFM]);
                            speciesForFractions.crustal = strLineArray[iCrustal].Length == 0 && strLineArray[iCrustal] == "" || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]);
                            speciesForFractions.so4 = strLineArray[iSO4].Length == 0 && strLineArray[iSO4] == "" || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]);
                            speciesForFractions.ec = strLineArray[iEC].Length == 0 && strLineArray[iEC] == "" ? float.NaN : Convert.ToSingle(strLineArray[iEC]);
                            speciesForFractions.ocb = strLineArray[iOCB].Length == 0 && strLineArray[iOCB] == "" ? float.NaN : Convert.ToSingle(strLineArray[iOCB]);
                            speciesForFractions.no3 = strLineArray[iNO3].Length == 0 && strLineArray[iNO3] == "" || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]);
                            speciesForFractions.no3r = strLineArray[iNO3r].Length == 0 && strLineArray[iNO3r] == "" || Convert.ToSingle(strLineArray[iNO3r]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3r]);
                            speciesForFractions.nh4 = strLineArray[iNH4].Length == 0 && strLineArray[iNH4] == "" || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]);
                            speciesForFractions.salt = strLineArray[iSalt].Length == 0 && strLineArray[iSalt] == "" || Convert.ToSingle(strLineArray[iSalt]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSalt]);
                            speciesForFractions.don = strLineArray[iDON].Length == 0 && strLineArray[iDON] == "" || Convert.ToSingle(strLineArray[iDON]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iDON]);
                            if (dicQYSpecies1.ContainsKey(speciesForFractions.year))
                            {
                                dicQYSpecies1[speciesForFractions.year].Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                            }
                            else
                            {
                                dicSpecies1 = new Dictionary<string, SpeciesForFractions>();
                                dicSpecies1.Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                                dicQYSpecies1.Add(speciesForFractions.year, dicSpecies1);
                            }
                            count1++;
                            break;
                        case "04":
                        case "05":
                        case "06":
                            speciesForFractions.year = strLineArray[iDate].Substring(0, 4).Replace("\"", "");
                            speciesForFractions.measured_fm = Convert.ToSingle(strLineArray[iMeasuredFM]);
                            speciesForFractions.crustal = strLineArray[iCrustal].Length == 0 && strLineArray[iCrustal] == "" || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]);
                            speciesForFractions.so4 = strLineArray[iSO4].Length == 0 && strLineArray[iSO4] == "" || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]);
                            speciesForFractions.ec = strLineArray[iEC].Length == 0 && strLineArray[iEC] == "" ? float.NaN : Convert.ToSingle(strLineArray[iEC]);
                            speciesForFractions.ocb = strLineArray[iOCB].Length == 0 && strLineArray[iOCB] == "" ? float.NaN : Convert.ToSingle(strLineArray[iOCB]);
                            speciesForFractions.no3 = strLineArray[iNO3].Length == 0 && strLineArray[iNO3] == "" || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]);
                            speciesForFractions.no3r = strLineArray[iNO3r].Length == 0 && strLineArray[iNO3r] == "" || Convert.ToSingle(strLineArray[iNO3r]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3r]);
                            speciesForFractions.nh4 = strLineArray[iNH4].Length == 0 && strLineArray[iNH4] == "" || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]);
                            speciesForFractions.salt = strLineArray[iSalt].Length == 0 && strLineArray[iSalt] == "" || Convert.ToSingle(strLineArray[iSalt]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSalt]);
                            speciesForFractions.don = strLineArray[iDON].Length == 0 && strLineArray[iDON] == "" || Convert.ToSingle(strLineArray[iDON]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iDON]);
                            if (dicQYSpecies2.ContainsKey(speciesForFractions.year))
                            {
                                dicQYSpecies2[speciesForFractions.year].Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                            }
                            else
                            {
                                dicSpecies2 = new Dictionary<string, SpeciesForFractions>();
                                dicSpecies2.Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                                dicQYSpecies2.Add(speciesForFractions.year, dicSpecies2);
                            }
                            count2++;
                            break;
                        case "07":
                        case "08":
                        case "09":
                            speciesForFractions.year = strLineArray[iDate].Substring(0, 4).Replace("\"", "");
                            speciesForFractions.measured_fm = Convert.ToSingle(strLineArray[iMeasuredFM]);
                            speciesForFractions.crustal = strLineArray[iCrustal].Length == 0 && strLineArray[iCrustal] == "" || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]);
                            speciesForFractions.so4 = strLineArray[iSO4].Length == 0 && strLineArray[iSO4] == "" || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]);
                            speciesForFractions.ec = strLineArray[iEC].Length == 0 && strLineArray[iEC] == "" ? float.NaN : Convert.ToSingle(strLineArray[iEC]);
                            speciesForFractions.ocb = strLineArray[iOCB].Length == 0 && strLineArray[iOCB] == "" ? float.NaN : Convert.ToSingle(strLineArray[iOCB]);
                            speciesForFractions.no3 = strLineArray[iNO3].Length == 0 && strLineArray[iNO3] == "" || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]);
                            speciesForFractions.no3r = strLineArray[iNO3r].Length == 0 && strLineArray[iNO3r] == "" || Convert.ToSingle(strLineArray[iNO3r]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3r]);
                            speciesForFractions.nh4 = strLineArray[iNH4].Length == 0 && strLineArray[iNH4] == "" || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]);
                            speciesForFractions.salt = strLineArray[iSalt].Length == 0 && strLineArray[iSalt] == "" || Convert.ToSingle(strLineArray[iSalt]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSalt]);
                            speciesForFractions.don = strLineArray[iDON].Length == 0 && strLineArray[iDON] == "" || Convert.ToSingle(strLineArray[iDON]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iDON]);
                            if (dicQYSpecies3.ContainsKey(speciesForFractions.year))
                            {
                                dicQYSpecies3[speciesForFractions.year].Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                            }
                            else
                            {
                                dicSpecies3 = new Dictionary<string, SpeciesForFractions>();
                                dicSpecies3.Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                                dicQYSpecies3.Add(speciesForFractions.year, dicSpecies3);
                            }
                            count3++;
                            break;
                        case "10":
                        case "11":
                        case "12":
                            speciesForFractions.year = strLineArray[iDate].Substring(0, 4).Replace("\"", "");
                            speciesForFractions.measured_fm = Convert.ToSingle(strLineArray[iMeasuredFM]);
                            speciesForFractions.crustal = strLineArray[iCrustal].Length == 0 && strLineArray[iCrustal] == "" || Convert.ToSingle(strLineArray[iCrustal]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iCrustal]);
                            speciesForFractions.so4 = strLineArray[iSO4].Length == 0 && strLineArray[iSO4] == "" || Convert.ToSingle(strLineArray[iSO4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSO4]);
                            speciesForFractions.ec = strLineArray[iEC].Length == 0 && strLineArray[iEC] == "" ? float.NaN : Convert.ToSingle(strLineArray[iEC]);
                            speciesForFractions.ocb = strLineArray[iOCB].Length == 0 && strLineArray[iOCB] == "" ? float.NaN : Convert.ToSingle(strLineArray[iOCB]);
                            speciesForFractions.no3 = strLineArray[iNO3].Length == 0 && strLineArray[iNO3] == "" || Convert.ToSingle(strLineArray[iNO3]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3]);
                            speciesForFractions.no3r = strLineArray[iNO3r].Length == 0 && strLineArray[iNO3r] == "" || Convert.ToSingle(strLineArray[iNO3r]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNO3r]);
                            speciesForFractions.nh4 = strLineArray[iNH4].Length == 0 && strLineArray[iNH4] == "" || Convert.ToSingle(strLineArray[iNH4]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iNH4]);
                            speciesForFractions.salt = strLineArray[iSalt].Length == 0 && strLineArray[iSalt] == "" || Convert.ToSingle(strLineArray[iSalt]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iSalt]);
                            speciesForFractions.don = strLineArray[iDON].Length == 0 && strLineArray[iDON] == "" || Convert.ToSingle(strLineArray[iDON]) < 0 ? float.NaN : Convert.ToSingle(strLineArray[iDON]);
                            if (dicQYSpecies4.ContainsKey(speciesForFractions.year))
                            {
                                dicQYSpecies4[speciesForFractions.year].Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                            }
                            else
                            {
                                dicSpecies4 = new Dictionary<string, SpeciesForFractions>();
                                dicSpecies4.Add(strLineArray[iDate].Replace("\"", ""), speciesForFractions);
                                dicQYSpecies4.Add(speciesForFractions.year, dicSpecies4);
                            }
                            count4++;
                            break;
                    }
                    count++;
                }
                #endregion
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool CalculateQuarterlyPeakSpeciatedMonitors(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, Monitors> dicSpeciatedMonitors, Dictionary<string, Monitors> dicSpeciesDaily, Dictionary<string, Dictionary<string, Dictionary<string, string>>> dicMinQuarters, Dictionary<string, string> dicMonitorInModelSpecies)
        {
            try
            {
                Dictionary<string, SpeciesForFractions> dicDailySpecies = new Dictionary<string, SpeciesForFractions>();
                Dictionary<string, SpeciesForFractions> dicSpeciesQuarterlyPeakValues = new Dictionary<string, SpeciesForFractions>();
                int valueGreater = -1; int count = 0;
                if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_DoUseAlldailyMonitorValuesGreaterThan)
                {
                    valueGreater = dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_UseAlldailyMonitorValuesGreaterThan;
                }
                foreach (KeyValuePair<string, Monitors> k in dicSpeciesDaily)
                {
                    if (!dicMinQuarters.ContainsKey(k.Key)) continue;
                    dicDailySpecies = new Dictionary<string, SpeciesForFractions>();
                    //针对每种不同的species需要分开计算
                    //-----------根据measured_frm进行降序排列，然后根据用户自己的设置进行计算: 1) Top X percent; 2) Top X number; 3) Value Greater Than
                    //--------对于1），总天数为30，10%，则计算前3个，但是当第四个的measured_frm与第三个的一样时，也要纳入计算
                    foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, SpeciesForFractions>>> kQ in k.Value.dicSpeciesDailyQuarterYear)
                    {
                        //根据之前得到的满足最小值要求的监测点信息进行计算
                        if (!dicMinQuarters[k.Key].ContainsKey(kQ.Key)) continue;
                        dicSpeciesQuarterlyPeakValues = new Dictionary<string, SpeciesForFractions>();
                        //先求出所有年份的第一个季度的quarterly peak，然后再跨年求quarterly peak for each species dicSpeciesDaily[k.Key].dicSpeciesDailyQuarterYear[kQ.Key]
                        foreach (KeyValuePair<string, Dictionary<string, SpeciesForFractions>> kY in kQ.Value)
                        {
                            if (kY.Value.Count < dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVE_MinDays) continue;
                            dicDailySpecies = kY.Value.OrderByDescending(p => p.Value.measured_fm).ToDictionary(p => p.Key, p => p.Value);
                            count = 0;
                            if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_DoTopXPercent)
                            {
                                count = Convert.ToInt32(Math.Round(Convert.ToDecimal(dicDailySpecies.Count) * Convert.ToDecimal(0.01) *  dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_TopXPercent, MidpointRounding.AwayFromZero));
                                if (count == 0) continue;
                                float measuredFM = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Select(p => p.Value.measured_fm).Skip(count - 1).Take(1).First();
                                dicSpeciesQuarterlyPeakValues.Add(kY.Key, new SpeciesForFractions()
                                {
                                    so4 = dicDailySpecies.Where(p => !float.IsNaN(p.Value.so4) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.so4).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.so4) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.so4).Average(),
                                    no3r = dicDailySpecies.Where(p => !float.IsNaN(p.Value.no3r) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.no3r).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.no3r) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.no3r).Average(),
                                    no3 = dicDailySpecies.Where(p => !float.IsNaN(p.Value.no3) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.no3).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.no3) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.no3).Average(),
                                    ocb = dicDailySpecies.Where(p => !float.IsNaN(p.Value.ocb) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.ocb).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.ocb) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.ocb).Average(),
                                    ec = dicDailySpecies.Where(p => !float.IsNaN(p.Value.ec) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.ec).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.ec) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.ec).Average(),
                                    crustal = dicDailySpecies.Where(p => !float.IsNaN(p.Value.crustal) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.crustal).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.crustal) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.crustal).Average(),
                                    salt = dicDailySpecies.Where(p => !float.IsNaN(p.Value.salt) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.salt).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.salt) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.salt).Average(),
                                });
                                dicSpeciesQuarterlyPeakValues[kY.Key].don = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.don) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.don).Count() > 0 ? dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.don) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.don).Average() : float.NaN;
                                dicSpeciesQuarterlyPeakValues[kY.Key].nh4 = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.nh4) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.nh4).Count() > 0 ? dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.nh4) && p.Value.measured_fm >= measuredFM).Select(p => p.Value.nh4).Average() : float.NaN;
                            }
                            else if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_DoUseAlldailyMonitorValuesGreaterThan)
                            {
                                dicSpeciesQuarterlyPeakValues.Add(kY.Key, new SpeciesForFractions()
                                {
                                    so4 = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.so4 >= valueGreater && !Double.IsNaN(p.Value.so4)).Select(p => p.Value.so4).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.so4 >= valueGreater && !Double.IsNaN(p.Value.so4)).Select(p => p.Value.so4).Average(),
                                    no3r = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.no3r >= valueGreater && !Double.IsNaN(p.Value.no3r)).Select(p => p.Value.no3r).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.no3r >= valueGreater && !Double.IsNaN(p.Value.no3r)).Select(p => p.Value.no3r).Average(),
                                    no3 = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.no3 >= valueGreater && !Double.IsNaN(p.Value.no3)).Select(p => p.Value.no3).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.no3 >= valueGreater && !Double.IsNaN(p.Value.no3)).Select(p => p.Value.no3).Average(),
                                    ocb = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.ocb >= valueGreater && !Double.IsNaN(p.Value.ocb)).Select(p => p.Value.oc).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.ocb >= valueGreater && !Double.IsNaN(p.Value.ocb)).Select(p => p.Value.oc).Average(),
                                    ec = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.ec >= valueGreater && !Double.IsNaN(p.Value.ec)).Select(p => p.Value.ec).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.ec >= valueGreater && !Double.IsNaN(p.Value.ec)).Select(p => p.Value.ec).Average(),
                                    crustal = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.crustal >= valueGreater && !Double.IsNaN(p.Value.crustal)).Select(p => p.Value.crustal).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.crustal >= valueGreater && !Double.IsNaN(p.Value.crustal)).Select(p => p.Value.crustal).Average(),
                                    salt = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.salt >= valueGreater && !Double.IsNaN(p.Value.salt)).Select(p => p.Value.salt).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.salt >= valueGreater && !Double.IsNaN(p.Value.salt)).Select(p => p.Value.salt).Average(),
                                });
                                dicSpeciesQuarterlyPeakValues[kY.Key].don = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.don >= valueGreater && !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Count() > 0 ? dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.don >= valueGreater && !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Average() : float.NaN;
                                dicSpeciesQuarterlyPeakValues[kY.Key].nh4 = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.nh4 >= valueGreater && !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Count() > 0 ? dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => p.Value.nh4 >= valueGreater && !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Average() : float.NaN;
                            }
                            else if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_DoUseTopXNumber)
                            {
                                count = dailyPMAnalysisConfiguration.speciesFractionOptionsD.IMPROVESTN_UseTopXNumber;
                                dicSpeciesQuarterlyPeakValues.Add(kY.Key, new SpeciesForFractions()
                                {
                                    so4 = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.so4)).Select(p => p.Value.so4).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.so4)).Select(p => p.Value.so4).Take(count).Average(),
                                    no3r = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.no3r)).Select(p => p.Value.no3r).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.no3r)).Select(p => p.Value.no3r).Take(count).Average(),
                                    no3 = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.no3)).Select(p => p.Value.no3).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.no3)).Select(p => p.Value.no3).Take(count).Average(),
                                    ocb = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.ocb)).Select(p => p.Value.ocb).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.ocb)).Select(p => p.Value.ocb).Take(count).Average(),
                                    ec = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.ec)).Select(p => p.Value.ec).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.ec)).Select(p => p.Value.ec).Take(count).Average(),
                                    crustal = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.crustal)).Select(p => p.Value.crustal).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.crustal)).Select(p => p.Value.crustal).Take(count).Average(),
                                    salt = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.salt)).Select(p => p.Value.salt).Count() == 0 ? float.NaN : dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.salt)).Select(p => p.Value.salt).Take(count).Average(),
                                });
                                dicSpeciesQuarterlyPeakValues[kY.Key].don = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Count() > 0 ? dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Take(count).Average() : float.NaN;
                                dicSpeciesQuarterlyPeakValues[kY.Key].nh4 = dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Count() > 0 ? dicDailySpecies.OrderByDescending(p => p.Value.measured_fm).Where(p => !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Take(count).Average() : float.NaN;
                            }
                        }
                        //calculate  each species values
                        if (dicSpeciatedMonitors.ContainsKey(k.Key))
                        {
                            if (dicSpeciatedMonitors[k.Key].dicSpeciesMonitors.ContainsKey(kQ.Key))
                            {
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].so4 = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.so4)).Select(p => p.Value.so4).Average();
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].no3r = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.no3r)).Select(p => p.Value.no3r).Average();
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].no3 = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.no3)).Select(p => p.Value.no3).Average();
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].ocb = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.ocb)).Select(p => p.Value.ocb).Average();
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].ec = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.ec)).Select(p => p.Value.ec).Average();
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].crustal = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.crustal)).Select(p => p.Value.crustal).Average();
                                //因为DON的最大值为0.375，所以当计算值大于0.375时则其值设为最大值
                                if (dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Count() > 0)
                                {
                                    dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].don = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Average() > 0.375 ? Convert.ToSingle(0.375) : dicSpeciesQuarterlyPeakValues.Select(p => p.Value.don).Average();
                                }
                                else
                                    dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].don = float.NaN;
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].nh4 = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Count() > 0 ? dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Average() : float.NaN;
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].salt = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.salt)).Select(p => p.Value.salt).Average();
                            }
                            else
                            {
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors.Add(kQ.Key, new SpeciesForFractions()
                                {
                                    so4 = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.so4)).Select(p => p.Value.so4).Average(),
                                    no3r = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.no3r)).Select(p => p.Value.no3r).Average(),
                                    no3 = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.no3)).Select(p => p.Value.no3).Average(),
                                    ocb = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.ocb)).Select(p => p.Value.ocb).Average(),
                                    ec = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.ec)).Select(p => p.Value.ec).Average(),
                                    crustal = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.crustal)).Select(p => p.Value.crustal).Average(),
                                    salt = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.salt)).Select(p => p.Value.salt).Average(),
                                });
                                if (dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Count() > 0)
                                    dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].don = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Average() > 0.375 ? Convert.ToSingle(0.375) : dicSpeciesQuarterlyPeakValues.Select(p => p.Value.don).Average();
                                else
                                    dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].don = float.NaN;
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].nh4 = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Count() > 0 ? dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Average() : float.NaN;
                            }
                        }
                        else
                        {
                            dicSpeciatedMonitors.Add(k.Key, new Monitors()
                            {
                                id = k.Value.id,
                                type = k.Value.type,
                                lat = k.Value.lat,
                                longitude = k.Value.longitude,
                                monitorGridcell = dicMonitorInModelSpecies[k.Key],
                                dicSpeciesMonitors = new Dictionary<string, SpeciesForFractions>(),
                            });
                            dicSpeciatedMonitors[k.Key].dicSpeciesMonitors.Add(kQ.Key, new SpeciesForFractions()
                            {
                                so4 = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.so4)).Select(p => p.Value.so4).Average(),
                                no3r = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.no3r)).Select(p => p.Value.no3r).Average(),
                                no3 = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.no3)).Select(p => p.Value.no3).Average(),
                                ocb = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.ocb)).Select(p => p.Value.ocb).Average(),
                                ec = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.ec)).Select(p => p.Value.ec).Average(),
                                crustal = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.crustal)).Select(p => p.Value.crustal).Average(),
                                salt = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.salt)).Select(p => p.Value.salt).Average(),
                            });
                            if (dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Count() > 0)
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].don = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.don)).Select(p => p.Value.don).Average() > 0.375 ? Convert.ToSingle(0.375) : dicSpeciesQuarterlyPeakValues.Select(p => p.Value.don).Average();
                            else
                                dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].don = float.NaN;
                            dicSpeciatedMonitors[k.Key].dicSpeciesMonitors[kQ.Key].nh4 = dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Count() > 0 ? dicSpeciesQuarterlyPeakValues.Where(p => !float.IsNaN(p.Value.nh4)).Select(p => p.Value.nh4).Average() : float.NaN;
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static string GetSpeciesFractions(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, Monitors> dicSpeciesFractions)
        {
            try
            {
                int iID = -1, iLong = -1, iLat = -1, iStateName = -1, iCountyName = -1, iDate = -1, iPM25 = -1, iSO4 = -1, iNO3 = -1, iSalt = -1, iOC = -1, iNH4 = -1, iEC = -1, iCrustal = -1;
                int iFcr = -1, iFec = -1, iFoc = -1, iFnh4 = -1, iFso4 = -1, iFno3 = -1, iFwater = -1, iFsalt = -1, iBlankMass = -1, iDon = -1,
                    iIdon = -1, iNO3r = -1;
                FileStream fs = new FileStream(dailyPMAnalysisConfiguration.dataInputD.specFracPointFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                    int i = 0;
                    #region
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Trim().ToLower())
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_state_name":
                                iStateName = i;
                                break;
                            case "_county_name":
                                iCountyName = i;
                                break;
                            case "monitor_lat":
                                iLat = i;
                                break;
                            case "monitor_long":
                                iLong = i;
                                break;
                            case "quarter":
                                iDate = i;
                                break;
                            case "pm25_mass_frac":
                                iPM25 = i;
                                break;
                            case "fcr":
                                iFcr = i;
                                break;
                            case "fec":
                                iFec = i;
                                break;
                            case "fnh4":
                                iFnh4 = i;
                                break;
                            case "focm":
                                iFoc = i;
                                break;
                            case "fso4":
                                iFso4 = i;
                                break;
                            case "fno3":
                                iFno3 = i;
                                break;
                            case "fwater":
                                iFwater = i;
                                break;
                            case "fsalt":
                                iFsalt = i;
                                break;
                            case "blank_mass":
                                iBlankMass = i;
                                break;
                            case "don":
                                iDon = i;
                                break;
                            case "i_so4":
                                iSO4 = i;
                                break;
                            case "i_no3r":
                                iNO3r = i;
                                break;
                            case "i_ocb":
                                iOC = i;
                                break;
                            case "i_ec":
                                iEC = i;
                                break;
                            case "i_crustal":
                                iCrustal = i;
                                break;
                            case "i_don":
                                iIdon = i;
                                break;
                            case "i_nh4":
                                iNH4 = i;
                                break;
                            case "i_no3":
                                iNO3 = i;
                                break;
                            case "i_salt":
                                iSalt = i;
                                break;

                        }
                        i++;
                    }
                    #endregion
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        strLineArray = strLine.Split(new char[] { ',' });
                        if (dicSpeciesFractions.ContainsKey(strLineArray[iID]))
                        {
                            dicSpeciesFractions[strLineArray[iID]].dicSpeciesFractions.Add(strLineArray[iDate], new SpecFracPM()
                            {
                                pm25MassFrac = Convert.ToDouble(strLineArray[iPM25]),
                                fCr = Convert.ToDouble(strLineArray[iFcr]),
                                fEC = Convert.ToDouble(strLineArray[iFec]),
                                fNH4 = Convert.ToDouble(strLineArray[iFnh4]),
                                fOcm = Convert.ToDouble(strLineArray[iFoc]),
                                fSO4 = Convert.ToDouble(strLineArray[iFso4]),
                                fNO3r = Convert.ToDouble(strLineArray[iFno3]),
                                fWater = Convert.ToDouble(strLineArray[iFwater]),
                                fSalt = Convert.ToDouble(strLineArray[iFsalt]),
                                blankMass = Convert.ToDouble(strLineArray[iBlankMass]),
                                don = Convert.ToDouble(strLineArray[iDon]),
                                iSO4 = Convert.ToDouble(strLineArray[iSO4]),
                                iNO3r = Convert.ToDouble(strLineArray[iNO3r]),
                                iOcb = Convert.ToDouble(strLineArray[iOC]),
                                iEC = Convert.ToDouble(strLineArray[iEC]),
                                iCrustal = Convert.ToDouble(strLineArray[iCrustal]),
                                iDON = Convert.ToDouble(strLineArray[iIdon]),
                                iNH4 = Convert.ToDouble(strLineArray[iNH4]),
                                iNO3 = Convert.ToDouble(strLineArray[iNO3]),
                                iSalt = Convert.ToDouble(strLineArray[iSalt]),
                            });
                        }
                        else
                        {
                            dicSpeciesFractions.Add(strLineArray[iID], new Monitors()
                            {
                                id = strLineArray[iID],
                                lat = Convert.ToDouble(strLineArray[iLat]),
                                longitude = Convert.ToDouble(strLineArray[iLong]),
                                stateName = strLineArray[iStateName],
                                countyName = strLineArray[iCountyName],
                                dicSpeciesFractions = new Dictionary<string, SpecFracPM>(),
                            });
                            dicSpeciesFractions[strLineArray[iID]].dicSpeciesFractions.Add(strLineArray[iDate], new SpecFracPM()
                            {
                                pm25MassFrac = Convert.ToDouble(strLineArray[iPM25]),
                                fCr = Convert.ToDouble(strLineArray[iFcr]),
                                fEC = Convert.ToDouble(strLineArray[iFec]),
                                fNH4 = Convert.ToDouble(strLineArray[iFnh4]),
                                fOcm = Convert.ToDouble(strLineArray[iFoc]),
                                fSO4 = Convert.ToDouble(strLineArray[iFso4]),
                                fNO3r = Convert.ToDouble(strLineArray[iFno3]),
                                fWater = Convert.ToDouble(strLineArray[iFwater]),
                                fSalt = Convert.ToDouble(strLineArray[iFsalt]),
                                blankMass = Convert.ToDouble(strLineArray[iBlankMass]),
                                don = Convert.ToDouble(strLineArray[iDon]),
                                iSO4 = Convert.ToDouble(strLineArray[iSO4]),
                                iNO3r = Convert.ToDouble(strLineArray[iNO3r]),
                                iOcb = Convert.ToDouble(strLineArray[iOC]),
                                iEC = Convert.ToDouble(strLineArray[iEC]),
                                iCrustal = Convert.ToDouble(strLineArray[iCrustal]),
                                iDON = Convert.ToDouble(strLineArray[iIdon]),
                                iNH4 = Convert.ToDouble(strLineArray[iNH4]),
                                iNO3 = Convert.ToDouble(strLineArray[iNO3]),
                                iSalt = Convert.ToDouble(strLineArray[iSalt]),
                            });
                        }
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                };
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        public static string GetUnofficialPM(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, Monitors> dicUnofficialPMDaily)
        {
            try
            {
                #region read csv
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iPM25 = -1, iEPA = -1, iUser = -1;
                int count = -1;
                string id = "", type = "", date = "", quarter = "";
                //string errorInfo = "";
                Dictionary<string, string> dicIdType = new Dictionary<string, string>();
                Dictionary<string, PM25Monitors> dicDaily1 = new Dictionary<string, PM25Monitors>();
                Dictionary<string, PM25Monitors> dicDaily2 = new Dictionary<string, PM25Monitors>();
                Dictionary<string, PM25Monitors> dicDaily3 = new Dictionary<string, PM25Monitors>();
                Dictionary<string, PM25Monitors> dicDaily4 = new Dictionary<string, PM25Monitors>();
                Dictionary<string, Dictionary<string, PM25Monitors>> dicQYDaily1 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                Dictionary<string, Dictionary<string, PM25Monitors>> dicQYDaily2 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                Dictionary<string, Dictionary<string, PM25Monitors>> dicQYDaily3 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                Dictionary<string, Dictionary<string, PM25Monitors>> dicQYDaily4 = new Dictionary<string, Dictionary<string, PM25Monitors>>();

                FileStream fs = new FileStream(dailyPMAnalysisConfiguration.dataInputD.unofficialMonitorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                    int i = 0;
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Replace("\"", "").Trim().ToLower())
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_type":
                                iType = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "date":
                                iDate = i;
                                break;
                            case "pm25":
                                iPM25 = i;
                                break;
                            case "epa_flag":
                                iEPA = i;
                                break;
                            case "user_flag":
                                iUser = i;
                                break;
                        }
                        i++;
                    }
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        strLineArray = strLine.Split(new char[] { ',' });
                        //记录id相同，但type不同的监测点，需将type为IMPROVE的id重新命名为id^IMPROVE
                        if (dicIdType.ContainsKey(strLineArray[iID].Replace("\"", "")) && strLineArray[iType].Replace("\"", "").ToString() == "IMPROVE")
                        {
                            if (!dicIdType.ContainsKey(strLineArray[iID].Replace("\"", "") + "^IMPROVE") && (dicIdType.ContainsKey(strLineArray[iID].Replace("\"", "")) && dicIdType[strLineArray[iID].Replace("\"", "")].ToString() == "FRM"))
                                dicIdType.Add(strLineArray[iID].Replace("\"", "") + "^IMPROVE", strLineArray[iType].Replace("\"", ""));
                        }
                        else
                            if (!dicIdType.ContainsKey(strLineArray[iID].Replace("\"", "")))
                                dicIdType.Add(strLineArray[iID].Replace("\"", ""), strLineArray[iType].Replace("\"", ""));

                        if (Convert.ToInt32(strLineArray[iDate].Substring(0, 4).ToString()) < Convert.ToInt32(dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialStartYear)
                            || Convert.ToInt32(strLineArray[iDate].Substring(0, 4).ToString()) > Convert.ToInt32(dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialEndYear)
                            || (Convert.ToDouble(strLineArray[iPM25].ToString()) < 0)) continue;
                        bool isOK = true;
                        if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialEPADeletionChoice && !dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialUserDeletionChoice)
                        {
                            if (strLineArray[iEPA].ToString().Replace("\"", "") != "0") continue;
                            if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_DoUseAlldailyMonitorValuesGreaterThan)
                                if (Convert.ToDouble(strLineArray[iPM25]) < dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_UseAlldailyMonitorValuesGreaterThan) continue;
                            isOK = ReadUnofficialMonitorsDaily(strLineArray, ref iID, ref iType, ref iLat, ref iLong, ref iDate, ref iPM25, ref iEPA, ref iUser, ref id, ref type, ref date, ref quarter, ref count, ref dicUnofficialPMDaily, ref dicIdType, ref dicDaily1, ref dicDaily2, ref dicDaily3, ref dicDaily4, ref dicQYDaily1, ref dicQYDaily2, ref dicQYDaily3, ref dicQYDaily4);
                        }
                        else if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialEPADeletionChoice && dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialUserDeletionChoice) //epa/user
                        {
                            if (strLineArray[iUser].Replace("\"", "") != "0" && strLineArray[iEPA].Replace("\"", "") != "0") continue;
                            if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_DoUseAlldailyMonitorValuesGreaterThan)
                                if (Convert.ToDouble(strLineArray[iPM25]) < dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_UseAlldailyMonitorValuesGreaterThan) continue;
                            isOK = ReadUnofficialMonitorsDaily(strLineArray, ref iID, ref iType, ref iLat, ref iLong, ref iDate, ref iPM25, ref iEPA, ref iUser, ref id, ref type, ref date, ref quarter, ref count, ref dicUnofficialPMDaily, ref dicIdType, ref dicDaily1, ref dicDaily2, ref dicDaily3, ref dicDaily4, ref dicQYDaily1, ref dicQYDaily2, ref dicQYDaily3, ref dicQYDaily4);
                        }
                        else if (!dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialEPADeletionChoice && dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialUserDeletionChoice) //user
                        {
                            if (strLineArray[iEPA].Replace("\"", "") != "0") continue;
                            if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_DoUseAlldailyMonitorValuesGreaterThan)
                                if (Convert.ToDouble(strLineArray[iPM25]) < dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_UseAlldailyMonitorValuesGreaterThan) continue;
                            isOK = ReadUnofficialMonitorsDaily(strLineArray, ref iID, ref iType, ref iLat, ref iLong, ref iDate, ref iPM25, ref iEPA, ref iUser, ref id, ref type, ref date, ref quarter, ref count, ref dicUnofficialPMDaily, ref dicIdType, ref dicDaily1, ref dicDaily2, ref dicDaily3, ref dicDaily4, ref dicQYDaily1, ref dicQYDaily2, ref dicQYDaily3, ref dicQYDaily4);
                        }
                        else if (!dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialEPADeletionChoice && !dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialUserDeletionChoice) //none
                        {
                            if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_DoUseAlldailyMonitorValuesGreaterThan)
                                if (Convert.ToDouble(strLineArray[iPM25]) < dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_UseAlldailyMonitorValuesGreaterThan) continue;
                            isOK = ReadUnofficialMonitorsDaily(strLineArray, ref iID, ref iType, ref iLat, ref iLong, ref iDate, ref iPM25, ref iEPA, ref iUser, ref id, ref type, ref date, ref quarter, ref count, ref dicUnofficialPMDaily, ref dicIdType, ref dicDaily1, ref dicDaily2, ref dicDaily3, ref dicDaily4, ref dicQYDaily1, ref dicQYDaily2, ref dicQYDaily3, ref dicQYDaily4);
                        }
                        if (!isOK)
                            return "unknow";
                    }
                    #region readToEnd
                    if (csv.EndOfStream)
                    {
                        for (int j = 1; j <= 4; j++)
                        {
                            switch (j)
                            {
                                case 1:
                                    quarter = "1";
                                    dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily1);
                                    break;
                                case 2:
                                    quarter = "2";
                                    dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily2);
                                    break;
                                case 3:
                                    quarter = "3";
                                    dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily3);
                                    break;
                                case 4:
                                    quarter = "4";
                                    dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily4);
                                    break;
                            }
                        }
                    }
                    #endregion
                    fs.Dispose();
                    csv.Dispose();
                    GC.Collect();
                }
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        public static bool ReadUnofficialMonitorsDaily(string[] strLineArray, ref int iID, ref int iType, ref int iLat, ref int iLong, ref int iDate, ref int iPM25, ref int iEPA, ref int iUser, ref string id, ref string type, ref string date, ref string quarter, ref int count, ref Dictionary<string, Monitors> dicUnofficialPMDaily,
          ref  Dictionary<string, string> dicIdType, ref Dictionary<string, PM25Monitors> dicDaily1, ref Dictionary<string, PM25Monitors> dicDaily2, ref Dictionary<string, PM25Monitors> dicDaily3, ref Dictionary<string, PM25Monitors> dicDaily4,
          ref   Dictionary<string, Dictionary<string, PM25Monitors>> dicQYDaily1, ref Dictionary<string, Dictionary<string, PM25Monitors>> dicQYDaily2, ref Dictionary<string, Dictionary<string, PM25Monitors>> dicQYDaily3, ref Dictionary<string, Dictionary<string, PM25Monitors>> dicQYDaily4)
        {
            try
            {
                if (strLineArray[iID].Replace("\"", "") == id.Replace("^IMPROVE", "").Replace("\"", "") && strLineArray[iDate].Substring(0, 4).Replace("\"", "") == date && strLineArray[iType].Replace("\"", "") == type)
                {
                    switch (strLineArray[iDate].Substring(4, 2).Replace("\"", ""))
                    {
                        case "01":
                        case "02":
                        case "03":
                            if (dicQYDaily1.ContainsKey(date))
                            {
                                dicQYDaily1[date].Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                            }
                            else
                            {
                                dicDaily1.Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                                dicQYDaily1.Add(date, dicDaily1);
                            }
                            break;
                        case "04":
                        case "05":
                        case "06":
                            if (dicQYDaily2.ContainsKey(date))
                            {
                                dicQYDaily2[date].Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                            }
                            else
                            {
                                dicDaily2.Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                                dicQYDaily2.Add(date, dicDaily2);
                            }
                            break;
                        case "07":
                        case "08":
                        case "09":
                            if (dicQYDaily3.ContainsKey(date))
                            {
                                dicQYDaily3[date].Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                            }
                            else
                            {
                                dicDaily3.Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                                dicQYDaily3.Add(date, dicDaily3);
                            }
                            break;
                        case "10":
                        case "11":
                        case "12":
                            if (dicQYDaily4.ContainsKey(date))
                            {
                                dicQYDaily4[date].Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                            }
                            else
                            {
                                dicDaily4.Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                                dicQYDaily4.Add(date, dicDaily4);
                            }
                            break;
                    }
                    count++;
                }
                else
                {
                    if (count > 0)
                    {
                        if (strLineArray[iID].Replace("\"", "") != id.Replace("^IMPROVE", "").Replace("\"", ""))
                        {
                            //为每年的四个季度添加pm25的值
                            #region
                            for (int j = 1; j <= 4; j++)
                            {
                                switch (j)
                                {
                                    case 1:
                                        quarter = "1";
                                        dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily1);
                                        break;
                                    case 2:
                                        quarter = "2";
                                        dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily2);
                                        break;
                                    case 3:
                                        quarter = "3";
                                        dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily3);
                                        break;
                                    case 4:
                                        quarter = "4";
                                        dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily4);
                                        break;
                                }
                            }
                            #endregion
                            count = 0;
                            dicDaily1 = new Dictionary<string, PM25Monitors>();
                            dicDaily3 = new Dictionary<string, PM25Monitors>();
                            dicDaily4 = new Dictionary<string, PM25Monitors>();
                            dicDaily2 = new Dictionary<string, PM25Monitors>();
                            dicQYDaily1 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                            dicQYDaily2 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                            dicQYDaily3 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                            dicQYDaily4 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                        }
                        else
                        {
                            if (id.Replace("\"", "") != strLineArray[iID].Replace("\"", "") + "^IMPROVE" && dicIdType.ContainsKey(id.Replace("\"", "") + "^IMPROVE"))
                            {
                                for (int j = 1; j <= 4; j++)
                                {
                                    switch (j)
                                    {
                                        case 1:
                                            quarter = "1";
                                            dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily1);
                                            break;
                                        case 2:
                                            quarter = "2";
                                            dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily2);
                                            break;
                                        case 3:
                                            quarter = "3";
                                            dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily3);
                                            break;
                                        case 4:
                                            quarter = "4";
                                            dicUnofficialPMDaily[id].dicUnofficialPM25Daily.Add(quarter, dicQYDaily4);
                                            break;
                                    }
                                }
                                count = 0;
                                dicDaily1 = new Dictionary<string, PM25Monitors>();
                                dicDaily3 = new Dictionary<string, PM25Monitors>();
                                dicDaily4 = new Dictionary<string, PM25Monitors>();
                                dicDaily2 = new Dictionary<string, PM25Monitors>();
                                dicQYDaily1 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                dicQYDaily2 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                dicQYDaily3 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                dicQYDaily4 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                            }
                        }
                        dicDaily1 = new Dictionary<string, PM25Monitors>();
                        dicDaily3 = new Dictionary<string, PM25Monitors>();
                        dicDaily4 = new Dictionary<string, PM25Monitors>();
                        dicDaily2 = new Dictionary<string, PM25Monitors>();
                    }

                    id = strLineArray[iID].Replace("\"", "");
                    if (strLineArray[iType].Replace("\"", "") == "IMPROVE")
                    {
                        if (dicIdType.ContainsKey(id.Replace("\"", "") + "^IMPROVE"))
                        {
                            id = id.Replace("\"", "") + "^IMPROVE";
                        }
                    }
                    type = strLineArray[iType].Replace("\"", "");
                    date = strLineArray[iDate].Substring(0, 4).ToString().Replace("\"", "");
                    if (!dicUnofficialPMDaily.ContainsKey(id))
                    {
                        dicUnofficialPMDaily.Add(id, new Monitors()
                        {
                            id = id,
                            type = strLineArray[iType].Replace("\"", ""),
                            lat = Convert.ToDouble(strLineArray[iLat]),
                            longitude = Convert.ToDouble(strLineArray[iLong]),
                            dicUnofficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                        });
                    }
                    switch (strLineArray[iDate].Substring(4, 2).Replace("\"", ""))
                    {
                        case "01":
                        case "02":
                        case "03":
                            if (dicQYDaily1.ContainsKey(date))
                            {
                                dicQYDaily1[date].Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                            }
                            else
                            {
                                dicDaily1.Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                                dicQYDaily1.Add(date, dicDaily1);
                            }
                            break;
                        case "04":
                        case "05":
                        case "06":
                            if (dicQYDaily2.ContainsKey(date))
                            {
                                dicQYDaily2[date].Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                            }
                            else
                            {
                                dicDaily2.Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                                dicQYDaily2.Add(date, dicDaily2);
                            }
                            break;
                        case "07":
                        case "08":
                        case "09":
                            if (dicQYDaily3.ContainsKey(date))
                            {
                                dicQYDaily3[date].Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                            }
                            else
                            {
                                dicDaily3.Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                                dicQYDaily3.Add(date, dicDaily3);
                            }
                            break;
                        case "10":
                        case "11":
                        case "12":
                            if (dicQYDaily4.ContainsKey(date))
                            {
                                dicQYDaily4[date].Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                            }
                            else
                            {
                                dicDaily4.Add(strLineArray[iDate].Replace("\"", ""), new PM25Monitors()
                                {
                                    year = date,
                                    bPM25 = Convert.ToSingle(strLineArray[iPM25]),
                                });
                                dicQYDaily4.Add(date, dicDaily4);
                            }
                            break;
                    }
                    count++;
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetQuarterlyPeakPmMonitors(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, Monitors> dicUnofficialPM, Dictionary<string, Monitors> dicUnofficialPMDaily, Dictionary<string, Dictionary<string, Dictionary<string, string>>> dicMinQuarters, Dictionary<string, string> dicMonitorInModelUnofficial)
        {
            try
            {
                int iCountDay = 0;
                foreach (KeyValuePair<string, Monitors> k in dicUnofficialPMDaily)
                {
                    if (!dicMinQuarters.ContainsKey(k.Key)) continue;
                    List<double> lstPM = new List<double>();
                    foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQ in k.Value.dicUnofficialPM25Daily)
                    {
                        if (!dicMinQuarters[k.Key].ContainsKey(kQ.Key)) continue;
                        //先求出每个季度的所有年份的quarterly peak，然后再跨年求quarterly peak
                        Dictionary<string, PM25Monitors> dicDailyPMUnofficial = new Dictionary<string, PM25Monitors>();
                        foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kY in kQ.Value)
                        {
                            if (kY.Value.Count < dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialMinDays) continue;
                            if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_DoTopXPercent)
                            {
                                iCountDay = Convert.ToInt32(Math.Round(kY.Value.Count * 0.01 * Convert.ToDouble(dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_TopXPercent), MidpointRounding.AwayFromZero));
                                dicDailyPMUnofficial.Add(kY.Key, new PM25Monitors()
                                {
                                    bPM25 = kY.Value.OrderByDescending(p => p.Value.bPM25).Select(p => p.Value.bPM25).Take(iCountDay).Average(),
                                });
                            }
                            else if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_DoUseAlldailyMonitorValuesGreaterThan)
                            {
                                dicDailyPMUnofficial.Add(kY.Key, new PM25Monitors()
                                {
                                    bPM25 = kY.Value.Where(p => p.Value.bPM25 >= dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_UseAlldailyMonitorValuesGreaterThan).Select(p => p.Value.bPM25).Average(),
                                });
                            }
                            else if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_DoTopXNumber)
                            {
                                dicDailyPMUnofficial.Add(kY.Key, new PM25Monitors()
                                {
                                    bPM25 = kY.Value.OrderByDescending(p => p.Value.bPM25).Take(dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialPM25_TopXNumber).Select(p => p.Value.bPM25).Average(),
                                });
                            }
                        }
                        if (dicDailyPMUnofficial.Count == 0) continue;
                        if (dicUnofficialPM.ContainsKey(k.Key))
                        {
                            dicUnofficialPM[k.Key].dicPM.Add(kQ.Key, new PM25Monitors()
                            {
                                bPM25 = dicDailyPMUnofficial.Select(p => p.Value.bPM25).Average(),
                            });
                        }
                        else
                        {
                            dicUnofficialPM.Add(k.Key, new Monitors()
                            {
                                id = k.Key,
                                type = k.Value.type,
                                lat = k.Value.lat,
                                longitude = k.Value.longitude,
                                monitorGridcell = dicMonitorInModelUnofficial[k.Key],
                                dicPM = new Dictionary<string, PM25Monitors>(),
                            });
                            dicUnofficialPM[k.Key].dicPM.Add(kQ.Key, new PM25Monitors()
                            {
                                bPM25 = dicDailyPMUnofficial.Select(p => p.Value.bPM25).Average(),
                            });
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static string GetOfficialPM(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, Monitors> dicMonitorStateCounty, ref Dictionary<string, Monitors> dicOfficialPMDaily)
        {
            try
            {
                #region official pm
                int iID = -1, iType = -1, iLat = -1, iLong = -1, iDate = -1, iPM25 = -1, i98Percentile = -1, iStateName = -1, iCountyName = -1, iRank98 = -1, iCompletionCode = -1, iEPA = -1;
                string date = "", id = "", type = "", quarter = "";
                int count = 0;
                //string errorInfo = "";
                Dictionary<string, PM25Monitors> dicPM1 = new Dictionary<string, PM25Monitors>();
                Dictionary<string, PM25Monitors> dicPM2 = new Dictionary<string, PM25Monitors>();
                Dictionary<string, PM25Monitors> dicPM3 = new Dictionary<string, PM25Monitors>();
                Dictionary<string, PM25Monitors> dicPM4 = new Dictionary<string, PM25Monitors>();
                Dictionary<string, Dictionary<string, PM25Monitors>> dicQYpm1 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                Dictionary<string, Dictionary<string, PM25Monitors>> dicQYpm2 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                Dictionary<string, Dictionary<string, PM25Monitors>> dicQYpm3 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                Dictionary<string, Dictionary<string, PM25Monitors>> dicQYpm4 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                PM25Monitors pmMonitors = new PM25Monitors();
                FileStream fs = new FileStream(dailyPMAnalysisConfiguration.dataInputD.officialMonitorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();
                    string[] strLineArray = csv.ReadLine().Split(new char[] { ',' });
                    int i = 0;
                    #region
                    while (i < strLineArray.Length)
                    {
                        string s = strLineArray[i];
                        switch (s.Replace("\"", "").Trim().ToLower())
                        {
                            case "_id":
                                iID = i;
                                break;
                            case "_type":
                                iType = i;
                                break;
                            case "lat":
                                iLat = i;
                                break;
                            case "long":
                                iLong = i;
                                break;
                            case "date":
                                iDate = i;
                                break;
                            case "pm25":
                                iPM25 = i;
                                break;
                            case "98_percentile":
                                i98Percentile = i;
                                break;
                            case "epa_flag":
                                iEPA = i;
                                break;
                            case "completion_code":
                                iCompletionCode = i;
                                break;
                            case "_state_name":
                                iStateName = i;
                                break;
                            case "_county_name":
                                iCountyName = i;
                                break;
                            case "rank98":
                                iRank98 = i;
                                break;
                        }
                        i++;
                    }
                    #endregion
                    #region read from csv
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        //try
                        //{
                            strLineArray = strLine.Split(new char[] { ',' });
                            //保存所有sites 的statename 和countyname
                            if (!dicMonitorStateCounty.ContainsKey(strLineArray[iID].Replace("\"", "")))
                            {
                                dicMonitorStateCounty.Add(strLineArray[iID].Replace("\"", ""), new Monitors()
                                {
                                    id = strLineArray[iID].Replace("\"", ""),
                                    stateName = strLineArray[iStateName].Replace("\"", ""),
                                    countyName = strLineArray[iCountyName].Replace("\"", ""),
                                });
                            }
                            //满足start/end year，epa_flag=0
                            if (dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialEPADeletionChoice && !dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialUserDeletionChoice)
                            {
                                #region epa deletion
                                if (Convert.ToInt32(strLineArray[iDate].Substring(0, 4)) >= Convert.ToInt32(dailyPMAnalysisConfiguration.pm25CalculationOptionsD.officialPM25StartYear)
                                    && Convert.ToInt32(strLineArray[iDate].Substring(0, 4)) <= Convert.ToInt32(dailyPMAnalysisConfiguration.pm25CalculationOptionsD.officialPM25EndYear)
                                    && Convert.ToInt32(strLineArray[iEPA]) == 0)
                                {
                                    quarter = "";
                                    if (strLineArray[iID].Replace("\"", "") == id && strLineArray[iDate].Substring(0, 4).Replace("\"", "") == date && strLineArray[iType].Replace("\"", "") == type)
                                    {
                                        #region
                                        pmMonitors = new PM25Monitors();
                                        switch (strLineArray[iDate].Substring(4, 2).Replace("\"", ""))
                                        {
                                            case "01":
                                            case "02":
                                            case "03":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm1.ContainsKey(date))
                                                {
                                                    dicQYpm1[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM1 = new Dictionary<string, PM25Monitors>();
                                                    dicPM1.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm1.Add(date, dicPM1);
                                                }
                                                break;
                                            case "04":
                                            case "05":
                                            case "06":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm2.ContainsKey(date))
                                                {
                                                    dicQYpm2[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM2 = new Dictionary<string, PM25Monitors>();
                                                    dicPM2.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm2.Add(date, dicPM2);
                                                }
                                                break;
                                            case "07":
                                            case "08":
                                            case "09":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm3.ContainsKey(date))
                                                {
                                                    dicQYpm3[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM3 = new Dictionary<string, PM25Monitors>();
                                                    dicPM3.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm3.Add(date, dicPM3);
                                                }
                                                break;
                                            case "10":
                                            case "11":
                                            case "12":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm4.ContainsKey(date))
                                                {
                                                    dicQYpm4[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM4 = new Dictionary<string, PM25Monitors>();
                                                    dicPM4.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm4.Add(date, dicPM4);
                                                }
                                                break;
                                        }
                                        count++;
                                        #endregion
                                    }
                                    else
                                    {
                                        if (count > 0)
                                        {
                                            #region add pm values to four quarters for each year
                                            if (strLineArray[iID].Replace("\"", "") != id)
                                            {
                                                for (int k = 1; k <= 4; k++)
                                                {
                                                    switch (k)
                                                    {
                                                        case 1:
                                                            quarter = "1";
                                                            dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm1);
                                                            break;
                                                        case 2:
                                                            quarter = "2";
                                                            dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm2);
                                                            break;
                                                        case 3:
                                                            quarter = "3";
                                                            dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm3);
                                                            break;
                                                        case 4:
                                                            quarter = "4";
                                                            dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm4);
                                                            break;
                                                    }
                                                }
                                                count = 0;
                                                dicPM1 = new Dictionary<string, PM25Monitors>();
                                                dicPM2 = new Dictionary<string, PM25Monitors>();
                                                dicPM3 = new Dictionary<string, PM25Monitors>();
                                                dicPM4 = new Dictionary<string, PM25Monitors>();
                                                dicQYpm1 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                                dicQYpm2 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                                dicQYpm3 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                                dicQYpm4 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                            }
                                            #endregion
                                        }
                                        #region
                                        id = strLineArray[iID].Replace("\"", "");
                                        type = strLineArray[iType].Replace("\"", "");
                                        date = strLineArray[iDate].Substring(0, 4).Replace("\"", "");
                                        if (!dicOfficialPMDaily.ContainsKey(id))
                                        {
                                            dicOfficialPMDaily.Add(id, new Monitors()
                                            {
                                                id = id,
                                                type = type,
                                                lat = Convert.ToDouble(strLineArray[iLat]),
                                                longitude = Convert.ToDouble(strLineArray[iLong]),
                                                stateName = strLineArray[iStateName].Replace("\"", ""),
                                                countyName = strLineArray[iCountyName].Replace("\"", ""),
                                                rank98 = Convert.ToInt32(strLineArray[iRank98]),
                                                dicOfficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                                            });
                                        }
                                        pmMonitors = new PM25Monitors();
                                        switch (strLineArray[iDate].Substring(4, 2).Replace("\"", ""))
                                        {
                                            case "01":
                                            case "02":
                                            case "03":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm1.ContainsKey(date))
                                                {
                                                    dicQYpm1[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM1 = new Dictionary<string, PM25Monitors>();
                                                    dicPM1.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm1.Add(date, dicPM1);
                                                }
                                                break;
                                            case "04":
                                            case "05":
                                            case "06":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm2.ContainsKey(date))
                                                {
                                                    dicQYpm2[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM2 = new Dictionary<string, PM25Monitors>();
                                                    dicPM2.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm2.Add(date, dicPM2);
                                                }
                                                break;
                                            case "07":
                                            case "08":
                                            case "09":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm3.ContainsKey(date))
                                                {
                                                    dicQYpm3[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM3 = new Dictionary<string, PM25Monitors>();
                                                    dicPM3.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm3.Add(date, dicPM3);
                                                }
                                                break;
                                            case "10":
                                            case "11":
                                            case "12":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm4.ContainsKey(date))
                                                {
                                                    dicQYpm4[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM4 = new Dictionary<string, PM25Monitors>();
                                                    dicPM4.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm4.Add(date, dicPM4);
                                                }
                                                break;
                                        }
                                        count++;
                                        #endregion
                                    }
                                }
                                #endregion
                            }
                            else if (!dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialEPADeletionChoice)
                            {
                                #region epa deletion
                                if (Convert.ToInt32(strLineArray[iDate].Substring(0, 4).Replace("\"", "")) >= Convert.ToInt32(dailyPMAnalysisConfiguration.pm25CalculationOptionsD.officialPM25StartYear)
                                    && Convert.ToInt32(strLineArray[iDate].Substring(0, 4).Replace("\"", "")) <= Convert.ToInt32(dailyPMAnalysisConfiguration.pm25CalculationOptionsD.officialPM25EndYear)
                                    )
                                {
                                    quarter = "";
                                    if (strLineArray[iID].Replace("\"", "") == id && strLineArray[iDate].Substring(0, 4).Replace("\"", "") == date && strLineArray[iType].Replace("\"", "") == type)
                                    {
                                        #region
                                        pmMonitors = new PM25Monitors();
                                        switch (strLineArray[iDate].Substring(4, 2).Replace("\"", ""))
                                        {
                                            case "01":
                                            case "02":
                                            case "03":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm1.ContainsKey(date))
                                                {
                                                    dicQYpm1[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM1 = new Dictionary<string, PM25Monitors>();
                                                    dicPM1.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm1.Add(date, dicPM1);
                                                }
                                                break;
                                            case "04":
                                            case "05":
                                            case "06":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm2.ContainsKey(date))
                                                {
                                                    dicQYpm2[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM2 = new Dictionary<string, PM25Monitors>();
                                                    dicPM2.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm2.Add(date, dicPM2);
                                                }
                                                break;
                                            case "07":
                                            case "08":
                                            case "09":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm3.ContainsKey(date))
                                                {
                                                    dicQYpm3[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM3 = new Dictionary<string, PM25Monitors>();
                                                    dicPM3.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm3.Add(date, dicPM3);
                                                }
                                                break;
                                            case "10":
                                            case "11":
                                            case "12":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm4.ContainsKey(date))
                                                {
                                                    dicQYpm4[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM4 = new Dictionary<string, PM25Monitors>();
                                                    dicPM4.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm4.Add(date, dicPM4);
                                                }
                                                break;
                                        }
                                        count++;
                                        #endregion
                                    }
                                    else
                                    {
                                        if (count > 0)
                                        {
                                            #region add pm values to four quarters for each year
                                            if (strLineArray[iID].Replace("\"", "") != id)
                                            {
                                                for (int k = 1; k <= 4; k++)
                                                {
                                                    switch (k)
                                                    {
                                                        case 1:
                                                            quarter = "1";
                                                            dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm1);
                                                            break;
                                                        case 2:
                                                            quarter = "2";
                                                            dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm2);
                                                            break;
                                                        case 3:
                                                            quarter = "3";
                                                            dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm3);
                                                            break;
                                                        case 4:
                                                            quarter = "4";
                                                            dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm4);
                                                            break;
                                                    }
                                                }
                                                count = 0;
                                                dicPM1 = new Dictionary<string, PM25Monitors>();
                                                dicPM2 = new Dictionary<string, PM25Monitors>();
                                                dicPM3 = new Dictionary<string, PM25Monitors>();
                                                dicPM4 = new Dictionary<string, PM25Monitors>();
                                                dicQYpm1 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                                dicQYpm2 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                                dicQYpm3 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                                dicQYpm4 = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                                            }
                                            #endregion
                                        }
                                        #region
                                        id = strLineArray[iID].Replace("\"", "");
                                        type = strLineArray[iType].Replace("\"", "");
                                        date = strLineArray[iDate].Replace("\"", "").Substring(0, 4);
                                        if (!dicOfficialPMDaily.ContainsKey(id))
                                        {
                                            dicOfficialPMDaily.Add(id, new Monitors()
                                            {
                                                id = id,
                                                type = type,
                                                lat = Convert.ToDouble(strLineArray[iLat]),
                                                longitude = Convert.ToDouble(strLineArray[iLong]),
                                                stateName = strLineArray[iStateName].Replace("\"", ""),
                                                countyName = strLineArray[iCountyName].Replace("\"", ""),
                                                rank98 = Convert.ToInt32(strLineArray[iRank98]),
                                                dicOfficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                                            });
                                        }
                                        pmMonitors = new PM25Monitors();
                                        switch (strLineArray[iDate].Substring(4, 2).Replace("\"", ""))
                                        {
                                            case "01":
                                            case "02":
                                            case "03":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm1.ContainsKey(date))
                                                {
                                                    dicQYpm1[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM1 = new Dictionary<string, PM25Monitors>();
                                                    dicPM1.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm1.Add(date, dicPM1);
                                                }
                                                break;
                                            case "04":
                                            case "05":
                                            case "06":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm2.ContainsKey(date))
                                                {
                                                    dicQYpm2[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM2 = new Dictionary<string, PM25Monitors>();
                                                    dicPM2.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm2.Add(date, dicPM2);
                                                }
                                                break;
                                            case "07":
                                            case "08":
                                            case "09":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm3.ContainsKey(date))
                                                {
                                                    dicQYpm3[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM3 = new Dictionary<string, PM25Monitors>();
                                                    dicPM3.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm3.Add(date, dicPM3);
                                                }
                                                break;
                                            case "10":
                                            case "11":
                                            case "12":
                                                pmMonitors.percentile_98 = Convert.ToInt32(strLineArray[i98Percentile]);
                                                pmMonitors.bPM25 = Convert.ToSingle(strLineArray[iPM25]);
                                                pmMonitors.epaFlag = Convert.ToInt32(strLineArray[iEPA]);
                                                pmMonitors.completionCode = Convert.ToInt32(strLineArray[iCompletionCode]);
                                                pmMonitors.rank98 = Convert.ToInt32(strLineArray[iRank98]);
                                                if (dicQYpm4.ContainsKey(date))
                                                {
                                                    dicQYpm4[date].Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                }
                                                else
                                                {
                                                    dicPM4 = new Dictionary<string, PM25Monitors>();
                                                    dicPM4.Add(strLineArray[iDate].Replace("\"", ""), pmMonitors);
                                                    dicQYpm4.Add(date, dicPM4);
                                                }
                                                break;
                                        }
                                        count++;
                                        #endregion
                                    }
                                }
                                #endregion
                            }
                        //}
                        //catch
                        //{
                        //    errorInfo = "errorRow";
                        //}
                    }
                    #region read to end
                    if (csv.EndOfStream)
                    {
                        //在daily分析中没有custom和epa deletion之分，所有的都是epa deletion，所以不需要判定季度的最小天数，直接将结果保存到dictionary中
                        for (int k = 1; k <= 4; k++)
                        {
                            switch (k)
                            {
                                case 1:
                                    quarter = "1";
                                    dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm1);
                                    break;
                                case 2:
                                    quarter = "2";
                                    dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm2);
                                    break;
                                case 3:
                                    quarter = "3";
                                    dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm3);
                                    break;
                                case 4:
                                    quarter = "4";
                                    dicOfficialPMDaily[id].dicOfficialPM25Daily.Add(quarter, dicQYpm4);
                                    break;
                            }
                        }
                    }
                    #endregion
                    #endregion
                    fs.Dispose(); csv.Dispose();
                    GC.Collect();
                }
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        public static bool GetGridCellOfficialMonitor(ref Dictionary<string, string> dicOfficialMonitorInModel, Dictionary<string, DailyModelMonitor> dicQuarterlyPeakModel, Dictionary<string, Monitors> dicOfficialPMDaily)
        {
            try
            {
                double dFirst = dicQuarterlyPeakModel.First().Value.longitude, dLen = 0, dLat = 0;
                int iFirst = Convert.ToInt32(dicQuarterlyPeakModel.First().Key);
                if (dicQuarterlyPeakModel.ContainsKey((((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()))
                {
                    dLen = Math.Abs(dicQuarterlyPeakModel[(((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()].longitude -
                            dicQuarterlyPeakModel.First().Value.longitude
                            );
                    dLat = Math.Abs(dicQuarterlyPeakModel[(((iFirst / 1000)) * 1000 + iFirst % 1000 + 1).ToString()].lat -
                        dicQuarterlyPeakModel.First().Value.lat
                        );
                    dLen *= 2; dLat *= 2;
                }

                //---------计算两个网格之内；然后属于哪个的网格
                foreach (KeyValuePair<string, Monitors> k in dicOfficialPMDaily)
                {
                    try
                    {
                        var query = dicQuarterlyPeakModel.Where(p => Math.Abs(p.Value.longitude - k.Value.longitude) < dLen && Math.Abs(p.Value.lat - k.Value.lat) < dLat).ToList();
                        string sModelIDTemp = "";
                        if (query.Count() > 0)
                        {
                            DotSpatial.Topology.Coordinate coor = new DotSpatial.Topology.Coordinate(k.Value.longitude, k.Value.lat);
                            sModelIDTemp = query.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.lat)).First().Key;
                            dicOfficialMonitorInModel.Add(k.Key, sModelIDTemp);
                        }
                        else
                        {
                            sModelIDTemp = dicQuarterlyPeakModel.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.lat)).First().Key;
                            dicOfficialMonitorInModel.Add(k.Key, sModelIDTemp);
                        }
                    }
                    catch
                    {
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetGridCellUnofficialMonitors(ref Dictionary<string, string> dicMonitorInModelUnofficial, Dictionary<string, DailyModelMonitor> dicQuarterlyPeakModel, Dictionary<string, Monitors> dicUnofficialPMDaily, ref Dictionary<string, string> dicMonitorInModelFRM)
        {
            try
            {
                double dFirst = dicQuarterlyPeakModel.First().Value.longitude, dLon = 0, dLat = 0;
                int iFirst = Convert.ToInt32(dicQuarterlyPeakModel.First().Key);
                if (dicQuarterlyPeakModel.ContainsKey((((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()))
                {
                    dLon = Math.Abs(dicQuarterlyPeakModel[(((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()].longitude -
                            dicQuarterlyPeakModel.First().Value.longitude
                            );
                    dLat = Math.Abs(dicQuarterlyPeakModel[(((iFirst / 1000)) * 1000 + iFirst % 1000 + 1).ToString()].lat -
                        dicQuarterlyPeakModel.First().Value.lat
                        );
                    dLon *= 2; dLat *= 2;
                }

                //---------计算两个网格之内；然后属于哪个的网格
                foreach (KeyValuePair<string, Monitors> k in dicUnofficialPMDaily)
                {
                    var query = dicQuarterlyPeakModel.Where(p => Math.Abs(p.Value.longitude - k.Value.longitude) < dLon && Math.Abs(p.Value.lat - k.Value.lat) < dLat).ToList();
                    string sModelIDTemp = "";
                    try
                    {
                        if (query.Count() > 0)
                        {
                            DotSpatial.Topology.Coordinate coor = new DotSpatial.Topology.Coordinate(k.Value.longitude, k.Value.lat);
                            sModelIDTemp = query.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.lat)).First().Key;
                            dicMonitorInModelUnofficial.Add(k.Key, sModelIDTemp);
                            dicMonitorInModelFRM.Add(k.Key, sModelIDTemp);
                        }
                        else
                        {
                            sModelIDTemp = dicQuarterlyPeakModel.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.lat)).First().Key;
                            dicMonitorInModelUnofficial.Add(k.Key, sModelIDTemp);
                        }
                    }
                    catch { }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetGridCellSpeciatedMonitors(ref Dictionary<string, string> dicMonitorInModelSpecies, Dictionary<string, DailyModelMonitor> dicQuarterlyPeakModel, Dictionary<string, Monitors> dicSpeciesDaily)
        {
            try
            {
                double dFirst = dicQuarterlyPeakModel.First().Value.longitude; double dLon = 0, dLat = 0;
                int iFirst = Convert.ToInt32(dicQuarterlyPeakModel.First().Key);
                if (dicQuarterlyPeakModel.ContainsKey((((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()))
                {
                    dLon = Math.Abs(dicQuarterlyPeakModel[(((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()].longitude -
                            dicQuarterlyPeakModel.First().Value.longitude
                            );
                    dLat = Math.Abs(dicQuarterlyPeakModel[(((iFirst / 1000)) * 1000 + iFirst % 1000 + 1).ToString()].lat -
                        dicQuarterlyPeakModel.First().Value.lat
                        );
                    dLon *= 2; dLat *= 2;
                }

                //---------计算两个网格之内；然后属于哪个的网格
                foreach (KeyValuePair<string, Monitors> k in dicSpeciesDaily)
                {
                    var query = dicQuarterlyPeakModel.Where(p => Math.Abs(p.Value.longitude - k.Value.longitude) < dLon && Math.Abs(p.Value.lat - k.Value.lat) < dLat).ToList();
                    string sModelIDTemp = "";
                    try
                    {
                        if (query.Count() > 0)
                        {
                            DotSpatial.Topology.Coordinate coor = new DotSpatial.Topology.Coordinate(k.Value.longitude, k.Value.lat);
                            sModelIDTemp = query.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.lat)).First().Key;
                            dicMonitorInModelSpecies.Add(k.Key, sModelIDTemp);
                        }
                        else
                        {
                            sModelIDTemp = dicQuarterlyPeakModel.OrderBy(p => CommonClass.getDistanceFrom2Point(p.Value.longitude, p.Value.lat, k.Value.longitude, k.Value.lat)).First().Key;
                            dicMonitorInModelSpecies.Add(k.Key, sModelIDTemp);
                        }
                    }
                    catch { }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetValidPeriods(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, Dictionary<string, Monitors> dicOfficialPMDaily, List<string> dicDesignValuePeriod, ref Dictionary<string, List<string>> dicValidYear, ref List<Dictionary<string, Monitors>> lstAllYearsAllDaysPeriod, ref Dictionary<string, Dictionary<string, int>> dicComCodePeriod)
        {
            try
            {
                foreach (KeyValuePair<string, Monitors> k in dicOfficialPMDaily)
                {
                    //判断3年DV是否有效：末尾年的comCode为1或2，且年份都存在,默认情况下只考虑三个dv period的情况
                    //首先获取设置的开始年和结束年，然后求出dv periods的数目
                    int dvNum = dicDesignValuePeriod.Count;
                    List<string> lstYear = new List<string>();
                    Dictionary<string, int> dicComCode = new Dictionary<string, int>();
                    int[] doDV = new int[dvNum];
                    foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQ in k.Value.dicOfficialPM25Daily)
                    {
                        foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kY in kQ.Value)
                        {
                            if (!lstYear.Contains(kY.Key))
                                lstYear.Add(kY.Key);
                            List<int> lstComCode = kY.Value.Select(p => p.Value.completionCode).Distinct().ToList();
                            if (!dicComCode.ContainsKey(kY.Key))
                                dicComCode.Add(kY.Key, lstComCode[0]);
                        }
                    }
                    //只有当用户有设定特定的dv periods时才需要此步骤，当为no selected时则不需要，只需判断是否满足最小dv periods的要求，若三个连续的年份全部不满足com_code为1或2，则在满足最小数目的情况下delete year
                    #region
                    dicComCode = dicComCode.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                    int[] delYear = new int[dicComCode.Count()];
                    Dictionary<string, int> dicPeriodComcode = new Dictionary<string, int>();
                    for (int i = 0; i < dvNum; i++)
                    {
                        string s = dicDesignValuePeriod[i];
                        List<string> lstYearPeriod = new List<string>();
                        //lstYearPeriod.Add(s.Substring(0, s.IndexOf("-")));
                        //lstYearPeriod.Add((Convert.ToInt32(s.Substring(0, s.IndexOf("-"))) + 1).ToString());
                        //lstYearPeriod.Add(s.Substring(s.IndexOf("-") + 1));
                        for (int j = Convert.ToInt16(s.Substring(0, s.IndexOf("-"))); j <= Convert.ToInt16(s.Substring(s.IndexOf("-") + 1)); j++)
                        {
                            lstYearPeriod.Add(j.ToString());
                        }
                        lstYearPeriod.Sort();
                        if (dicComCode.Where(p => lstYearPeriod.Contains(p.Key)).ToList().Count() > 0 && dicComCode.Where(p => lstYearPeriod.Contains(p.Key)).ToList().Count == lstYearPeriod.Count)//3)//20140721这里改掉是因为3年以下也需要可以，如start2010,end2011
                        {
                            if (dicComCode[lstYearPeriod[lstYearPeriod.Count - 1]] == 1 || dicComCode[lstYearPeriod[lstYearPeriod.Count - 1]] == 2)
                            {
                                doDV[i] = 1;
                                //if (dicPeriodsValue.ContainsKey(k.Key))
                                //{
                                //    dicPeriodsValue[k.Key].Add(s);
                                //}
                                //else
                                //{
                                //    dicPeriodsValue.Add(k.Key, new List<string>() { s });
                                //}
                            }
                            else
                            {
                                doDV[i] = 0;
                            }
                        }
                        else
                        {
                            doDV[i] = 0;
                        }
                        dicPeriodComcode.Add(s, doDV[i]);

                        if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                        {
                            var queryComCode = dicComCode.Where(p => lstYearPeriod.Contains(p.Key)).Select(p => p.Value).ToList();
                            if ((queryComCode.Contains(1) || queryComCode.Contains(2)) && doDV[i]==1)//---------modify by xiejp
                            {

                                lstAllYearsAllDaysPeriod[i].Add(k.Key, new Monitors()
                                {
                                    id = k.Value.id,
                                    type = k.Value.type,
                                    lat = k.Value.lat,
                                    longitude = k.Value.longitude,
                                    stateName = k.Value.stateName,
                                    countyName = k.Value.countyName,
                                    //percentile_98 = k.Value.percentile_98,
                                    //rank98 = k.Value.rank98,
                                    dicOfficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                                });
                                foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kQ in k.Value.dicOfficialPM25Daily)
                                {
                                    //if (kQ.Value.Count < 3) continue;
                                    var query = kQ.Value.Where(p => lstYearPeriod.Contains(p.Key)).ToDictionary(p => p.Key + "," + p.Value.Last().Value.rank98, p => p.Value);
                                    if (query.Count() > 0)
                                        lstAllYearsAllDaysPeriod[i][k.Key].dicOfficialPM25Daily.Add(kQ.Key, query);
                                }
                            }
                        }
                    }
                    dicComCodePeriod.Add(k.Key, dicPeriodComcode);
                    #endregion
                    //min num dv periods and required DV periods
                    #region
                    if (dvNum - doDV.Where(p => p == 0).Count() >= dailyPMAnalysisConfiguration.pm25CalculationOptionsD.minNumDVPeriodsForValidFRMMonitors)
                    {
                        //根据用户选择的dv period进行筛选
                        if (dailyPMAnalysisConfiguration.pm25CalculationOptionsD.requiredDesignValuePeriodsForValidFRMMonitors == "None selected")
                        {
                            List<int> lstComCode = dicComCode.Select(p => p.Value).ToList();
                            string[] arrayYear = dicComCode.Select(p => p.Key).ToArray();
                            for (int i = 2; i < lstComCode.Count(); i++)
                            {
                                if ((lstComCode[i - 2] != 1 && lstComCode[i - 2] != 2) && (lstComCode[i - 1] != 1 && lstComCode[i - 1] != 2) && (lstComCode[i] != 1 && lstComCode[i] != 2))
                                    delYear[i - 2] = 1;
                            }
                            List<string> lstValidYear = new List<string>();
                            for (int i = 0; i < delYear.Count(); i++)
                            {
                                if (delYear[i] == 0)
                                    lstValidYear.Add(arrayYear[i]);
                            }
                            dicValidYear.Add(k.Key, lstValidYear);

                        }
                        else
                        {
                            List<string> lstRequiredPeriods = dailyPMAnalysisConfiguration.pm25CalculationOptionsD.requiredDesignValuePeriodsForValidFRMMonitors.Split(',').ToList();
                            if (dicPeriodComcode.Where(p => lstRequiredPeriods.Contains(p.Key) && p.Value == 1).Count() == lstRequiredPeriods.Count())
                            {
                                List<int> lstComCode = dicComCode.Select(p => p.Value).ToList();
                                string[] arrayYear = dicComCode.Select(p => p.Key).ToArray();
                                for (int i = 2; i < lstComCode.Count(); i++)
                                {
                                    if ((lstComCode[i - 2] != 1 && lstComCode[i - 2] != 2) && (lstComCode[i - 1] != 1 && lstComCode[i - 1] != 2) && (lstComCode[i] != 1 && lstComCode[i] != 2))
                                        delYear[i - 2] = 1;
                                }
                                List<string> lstValidYear = new List<string>();
                                for (int i = 0; i < delYear.Count(); i++)
                                {
                                    if (delYear[i] == 0)
                                        lstValidYear.Add(lstYear[i]);
                                }
                                dicValidYear.Add(k.Key, lstValidYear);
                            }
                        }
                    }
                    #endregion
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetAllYearHighDays(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, ref Dictionary<string, Monitors> dicHighDaysDaily, Dictionary<string, Monitors> dicAllYearsAllDaysDaily)
        {
            try
            {
                foreach (KeyValuePair<string, Monitors> k in dicAllYearsAllDaysDaily)
                {
                    if (k.Value.dicPMDaily == null || k.Value.dicPMDaily.Count == 0) continue;
                    dicHighDaysDaily.Add(k.Key, new Monitors()
                    {
                        id = k.Value.id,
                        type = k.Value.type,
                        stateName = k.Value.stateName,
                        countyName = k.Value.countyName,
                        lat = k.Value.lat,
                        longitude = k.Value.longitude,
                        monitorGridcell = k.Value.monitorGridcell,
                        dicHighDays = new Dictionary<string, AllYearHighDays>(),
                    });
                    foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kYear in k.Value.dicPMDaily)
                    {
                        if (k.Value.dicOfficialPM25Daily[kYear.Key].ContainsKey("4"))
                        {
                            AllYearHighDays ayHighDays = new AllYearHighDays();
                            var query = kYear.Value.OrderByDescending(q => q.Value.bPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1))).Last();
                            //if (query.Value.percentile_98 != 1)
                            //{
                            //    if (Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1)) - 1 > 0)
                            //    {
                            //        var query2 = kYear.Value.OrderByDescending(q => q.Value.bPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1)) - 1).Last();
                            //        if (query.Value.bPM25 == query2.Value.bPM25 && query2.Value.percentile_98 == 1)
                            //        { query = query2; }
                            //    }
                            //    if (Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1)) + 1 <= 8)
                            //    {
                            //        var query3 = kYear.Value.OrderByDescending(q => q.Value.bPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1)) + 1).Last();
                            //        if (query.Value.bPM25 == query3.Value.bPM25 && query3.Value.percentile_98 == 1)
                            //        { query = query3; }
                            //    }
                            //}
                            ayHighDays.rank98 = Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1));
                            ayHighDays.date_b = query.Key;
                            switch (query.Key.Substring(4, 2))
                            {
                                case "01":
                                case "02":
                                case "03":
                                    ayHighDays.highQuarter_b = 1;
                                    break;
                                case "04":
                                case "05":
                                case "06":
                                    ayHighDays.highQuarter_b = 2;
                                    break;
                                case "07":
                                case "08":
                                case "09":
                                    ayHighDays.highQuarter_b = 3;
                                    break;
                                case "10":
                                case "11":
                                case "12":
                                    ayHighDays.highQuarter_b = 4;
                                    break;
                            }
                            ayHighDays.bPMdqCONC = query.Value.bPM25;
                            //ayHighDays.bCrustalMassq = query.Value.bCrustal;
                            ayHighDays.bCrustalMassq = query.Value.bCrustal;
                            ayHighDays.bECMassq = query.Value.bEC;
                            ayHighDays.bNH4Massq = query.Value.bNH4;
                            ayHighDays.bOcmbMassq = query.Value.bOCMmb;
                            ayHighDays.bSO4Massq = query.Value.bSO4;
                            ayHighDays.bNO3Massq = query.Value.bNO3r;
                            ayHighDays.bWaterMassq = query.Value.bWater;
                            ayHighDays.bSaltMassq = query.Value.bSalt;

                            ayHighDays.rrfCrustalq = query.Value.rrfCrustal;
                            ayHighDays.rrfECq = query.Value.rrfEC;
                            ayHighDays.rrfNH4q = query.Value.rrfNH4;
                            ayHighDays.rrfOCq = query.Value.rrfOC;
                            ayHighDays.rrfSO4q = query.Value.rrfSO4;
                            ayHighDays.rrfNO3q = query.Value.rrfNO3;
                            ayHighDays.rrfWaterq = query.Value.rrfWater;
                            ayHighDays.rrfSaltq = query.Value.rrfSalt;
                            if (k.Value.id == "371830014")
                            {
                                var temp = kYear.Value.OrderByDescending(q => q.Value.fPM25);
                            }
                            query = kYear.Value.OrderByDescending(q => q.Value.fPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1))).Last();
                            //if (query.Value.percentile_98 != 1)
                            //{
                            //    if (Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1)) - 1 > 0)
                            //    {
                            //        var query2 = kYear.Value.OrderByDescending(q => q.Value.bPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1)) - 1).Last();
                            //        if (query.Value.bPM25 == query2.Value.bPM25 && query2.Value.percentile_98 == 1)
                            //        { query = query2; }
                            //    }
                            //    if (Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1)) + 1 <= 8)
                            //    {
                            //        var query3 = kYear.Value.OrderByDescending(q => q.Value.bPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1)) + 1).Last();
                            //        if (query.Value.bPM25 == query3.Value.bPM25 && query3.Value.percentile_98 == 1)
                            //        { query = query3; }
                            //    }
                            //}
                            ayHighDays.date_f = query.Key;
                            switch (query.Key.Substring(4, 2))
                            {
                                case "01":
                                case "02":
                                case "03":
                                    ayHighDays.highQuarter_f = 1;
                                    break;
                                case "04":
                                case "05":
                                case "06":
                                    ayHighDays.highQuarter_f = 2;
                                    break;
                                case "07":
                                case "08":
                                case "09":
                                    ayHighDays.highQuarter_f = 3;
                                    break;
                                case "10":
                                case "11":
                                case "12":
                                    ayHighDays.highQuarter_f = 4;
                                    break;
                            }
                            ayHighDays.fPMdqCONC = query.Value.fPM25;
                            ayHighDays.fCrustalMassq =   query.Value.fCrustal;
                            ayHighDays.fECMassq =   query.Value.fEC;
                            ayHighDays.fNH4Massq =   query.Value.fNH4;
                            ayHighDays.fOcmbMassq =   query.Value.fOCMmb;
                            ayHighDays.fSO4Massq =   query.Value.fSO4;
                            ayHighDays.fNO3Massq =   query.Value.fNO3r;
                            ayHighDays.fWaterMassq =   query.Value.fWater;
                            ayHighDays.fSaltMassq =   query.Value.fSalt;

                            //ayHighDays.fCrustalMassq = ayHighDays.bCrustalMassq * ayHighDays.rrfCrustalq;// query.Value.fCrustal;
                            //ayHighDays.fECMassq = ayHighDays.bECMassq * ayHighDays.rrfECq;// query.Value.fEC;
                            //ayHighDays.fNH4Massq = ayHighDays.bNH4Massq * ayHighDays.rrfNH4q;// query.Value.fNH4;
                            //ayHighDays.fOcmbMassq = ayHighDays.bOcmbMassq * ayHighDays.rrfOCq;// query.Value.fOCMmb;
                            //ayHighDays.fSO4Massq = ayHighDays.bSO4Massq * ayHighDays.rrfSO4q;// query.Value.fSO4;
                            //ayHighDays.fNO3Massq = ayHighDays.bNO3Massq * ayHighDays.rrfNO3q;// query.Value.fNO3r;
                            //ayHighDays.fWaterMassq = ayHighDays.bWaterMassq * ayHighDays.rrfWaterq;// query.Value.fWater;
                            //ayHighDays.fSaltMassq = ayHighDays.bSaltMassq * ayHighDays.rrfSO4q;// query.Value.fSalt;
                            dicHighDaysDaily[k.Key].dicHighDays.Add(kYear.Key.Substring(0, kYear.Key.IndexOf(',')), ayHighDays);
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetAllYearHighDaysPeriod(ref List<Dictionary<string, Monitors>> lstHighDaysPeriod, List<Dictionary<string, Monitors>> lstDailyFilePeriod, int periodCount)
        {
            try
            {
                for (int i = 0; i < periodCount; i++)
                {
                    lstHighDaysPeriod.Add(new Dictionary<string, Monitors>());
                }
                for (int i = 0; i < lstDailyFilePeriod.Count; i++)
                {
                    foreach (KeyValuePair<string, Monitors> k in lstDailyFilePeriod[i])
                    {
                        if (k.Value.dicPMDaily == null || k.Value.dicPMDaily.Count == 0) continue;
                        lstHighDaysPeriod[i].Add(k.Key, new Monitors()
                        {
                            id = k.Value.id,
                            type = k.Value.type,
                            stateName = k.Value.stateName,
                            countyName = k.Value.countyName,
                            lat = k.Value.lat,
                            longitude = k.Value.longitude,
                            monitorGridcell = k.Value.monitorGridcell,
                            dicHighDays = new Dictionary<string, AllYearHighDays>(),
                        });
                        foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kYear in k.Value.dicPMDaily)
                        {
                            if (k.Value.dicOfficialPM25Daily[kYear.Key].ContainsKey("4"))
                            {
                                int rank = Convert.ToInt32(kYear.Value.Select(p => p.Value.rank98).First().ToString());
                                AllYearHighDays ayHighDays = new AllYearHighDays();
                                var query = kYear.Value.OrderByDescending(q => q.Value.bPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1))).Last();
                                ayHighDays.rank98 = Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1));
                                ayHighDays.date_b = query.Key;
                                switch (query.Key.Substring(4, 2))
                                {
                                    case "01":
                                    case "02":
                                    case "03":
                                        ayHighDays.highQuarter_b = 1;
                                        break;
                                    case "04":
                                    case "05":
                                    case "06":
                                        ayHighDays.highQuarter_b = 2;
                                        break;
                                    case "07":
                                    case "08":
                                    case "09":
                                        ayHighDays.highQuarter_b = 3;
                                        break;
                                    case "10":
                                    case "11":
                                    case "12":
                                        ayHighDays.highQuarter_b = 4;
                                        break;
                                }
                                ayHighDays.bPMdqCONC = query.Value.bPM25;
                               // query = kYear.Value.OrderByDescending(q => q.Value.fPM25).Take(rank).Last();
                                query = kYear.Value.OrderByDescending(q => q.Value.fPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1))).Last();
                                ayHighDays.date_f = query.Key;
                                switch (query.Key.Substring(4, 2))
                                {
                                    case "01":
                                    case "02":
                                    case "03":
                                        ayHighDays.highQuarter_f = 1;
                                        break;
                                    case "04":
                                    case "05":
                                    case "06":
                                        ayHighDays.highQuarter_f = 2;
                                        break;
                                    case "07":
                                    case "08":
                                    case "09":
                                        ayHighDays.highQuarter_f = 3;
                                        break;
                                    case "10":
                                    case "11":
                                    case "12":
                                        ayHighDays.highQuarter_f = 4;
                                        break;
                                }
                                ayHighDays.fPMdqCONC = query.Value.fPM25;
                                ayHighDays.bCrustalMassq = query.Value.bCrustal;
                                ayHighDays.bECMassq = query.Value.bEC;
                                ayHighDays.bNH4Massq = query.Value.bNH4;
                                ayHighDays.bOcmbMassq = query.Value.bOCMmb;
                                ayHighDays.bSO4Massq = query.Value.bSO4;
                                ayHighDays.bNO3Massq = query.Value.bNO3r;
                                ayHighDays.bWaterMassq = query.Value.bWater;
                                ayHighDays.bSaltMassq = query.Value.bSalt;
                                ayHighDays.fCrustalMassq = query.Value.fCrustal;
                                ayHighDays.fECMassq = query.Value.fEC;
                                ayHighDays.fNH4Massq = query.Value.fNH4;
                                ayHighDays.fOcmbMassq = query.Value.fOCMmb;
                                ayHighDays.fSO4Massq = query.Value.fSO4;
                                ayHighDays.fNO3Massq = query.Value.fNO3r;
                                ayHighDays.fWaterMassq = query.Value.fWater;
                                ayHighDays.fSaltMassq = query.Value.fSalt;
                                //ayHighDays.rrfCrustalq = query.Value.fCrustal / ayHighDays.bCrustalMassq;
                                //ayHighDays.rrfECq = query.Value.fEC / ayHighDays.bECMassq;
                                //ayHighDays.rrfNH4q = query.Value.fNH4 / ayHighDays.bNH4Massq;
                                //ayHighDays.rrfOCq = query.Value.fOCMmb / ayHighDays.bOcmbMassq;
                                //ayHighDays.rrfSO4q = query.Value.fSO4 / ayHighDays.bSO4Massq;
                                //ayHighDays.rrfNO3q = query.Value.fNO3r / ayHighDays.bNO3Massq;
                                //ayHighDays.rrfWaterq = query.Value.fWater / ayHighDays.bWaterMassq;
                                //ayHighDays.rrfSaltq = query.Value.fSalt / ayHighDays.bSaltMassq;
                                ayHighDays.rrfCrustalq = query.Value.rrfCrustal;
                                ayHighDays.rrfECq = query.Value.rrfEC;
                                ayHighDays.rrfNH4q = query.Value.rrfNH4;
                                ayHighDays.rrfOCq = query.Value.rrfOC;
                                ayHighDays.rrfSO4q = query.Value.rrfSO4;
                                ayHighDays.rrfNO3q = query.Value.rrfNO3;
                                ayHighDays.rrfWaterq = query.Value.rrfWater;
                                ayHighDays.rrfSaltq = query.Value.rrfSalt;
                                lstHighDaysPeriod[i][k.Key].dicHighDays.Add(kYear.Key.Substring(0, kYear.Key.IndexOf(',')), ayHighDays);
                            }
                        }
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool GetDailyPointFutureVlues(DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration, Dictionary<string, Monitors> dicHighDaysDaily, List<string> dicDesignValuePeriod, Dictionary<string, Dictionary<string, int>> dicComCodePeriod, ref Dictionary<string, PMPoint> dicDailyPoint, ref List<Dictionary<string, PMPoint>> lstDailyPointPeriod)
        {
            try
            {
                List<string> lstYear = new List<string>();
                foreach (KeyValuePair<string, Monitors> k in dicHighDaysDaily)
                {
                    if (k.Value.dicDailyPointValues == null)
                        k.Value.dicDailyPointValues = new Dictionary<string, PM25Monitors>();
                    Dictionary<string, PM25Monitors> dic = new Dictionary<string, PM25Monitors>();
                    //跨年求均值为3年一组
                    for (int i = 0; i < dicDesignValuePeriod.Count; i++)
                    {
                        string s = dicDesignValuePeriod[i];
                        lstYear = new List<string>();
                        //lstYear = s.Split('-').ToList();
                        //lstYear.Insert(1, (Convert.ToInt32((lstYear[0])) + 1).ToString());
                        for (int j = Convert.ToInt16(s.Split('-')[0]); j <= Convert.ToInt16(s.Split('-')[1]); j++)
                        {
                            lstYear.Add(j.ToString());
                        }
                        lstYear.Sort();
                        var query = k.Value.dicHighDays.Where(p => lstYear.Contains(p.Key));
                        if (dicComCodePeriod[k.Key][s] != 1) continue;
                        dic.Add(s, new PM25Monitors()
                        {
                            bPM25 = query.Count() < lstYear.Count ? -9 : query.Select(p => p.Value.bPMdqCONC).Average(),//3 ? -9 : query.Select(p => p.Value.bPMdqCONC).Average(),
                            fPM25 = query.Count() < lstYear.Count ? -9 : query.Select(p => p.Value.fPMdqCONC).Average(),//3 ? -9 : query.Select(p => p.Value.fPMdqCONC).Average(),
                            bCrustal = Convert.ToSingle(query.Select(p => p.Value.bCrustalMassq).Average()),
                            bEC = Convert.ToSingle(query.Select(p => p.Value.bECMassq).Average()),
                            bNH4 = Convert.ToSingle(query.Select(p => p.Value.bNH4Massq).Average()),
                            bOCMmb = Convert.ToSingle(query.Select(p => p.Value.bOcmbMassq).Average()),
                            bSO4 = Convert.ToSingle(query.Select(p => p.Value.bSO4Massq).Average()),
                            bNO3r = Convert.ToSingle(query.Select(p => p.Value.bNO3Massq).Average()),
                            bWater = Convert.ToSingle(query.Select(p => p.Value.bWaterMassq).Average()),
                            bSalt = Convert.ToSingle(query.Select(p => p.Value.bSaltMassq).Average()),

                            fCrustal = query.Select(p => p.Value.fCrustalMassq).Average(),
                            fEC = query.Select(p => p.Value.fECMassq).Average(),
                            fNH4 = query.Select(p => p.Value.fNH4Massq).Average(),
                            fOCMmb = query.Select(p => p.Value.fOcmbMassq).Average(),
                            fSO4 = query.Select(p => p.Value.fSO4Massq).Average(),
                            fNO3r = query.Select(p => p.Value.fNO3Massq).Average(),
                            fWater = query.Select(p => p.Value.fWaterMassq).Average(),
                            fSalt = query.Select(p => p.Value.fSaltMassq).Average(),
                        });

                        if (dailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                        {
                            if (dicComCodePeriod.ContainsKey(k.Key) && dicComCodePeriod[k.Key][s] == 1)
                            {
                                lstDailyPointPeriod[i].Add(k.Key, new PMPoint()
                                {
                                    id = k.Value.id,
                                    type = k.Value.type,
                                    stateName = k.Value.stateName,
                                    countyName = k.Value.countyName,
                                    monitorLat = k.Value.lat,
                                    monitorLong = k.Value.longitude,
                                    monitorGridcell = k.Value.monitorGridcell,
                                    bPMDV = dic[s].bPM25,
                                    fPMDV = dic[s].fPM25,
                                    bCrustalMass = dic[s].bCrustal,
                                    bECMass = dic[s].bEC,
                                    bNH4Mass = dic[s].bNH4,
                                    bOcmbMass = dic[s].bOCMmb,
                                    bSO4Mass = dic[s].bSO4,
                                    bNO3Mass = dic[s].bNO3r,
                                    bWaterMass = dic[s].bWater,
                                    bSaltMass = dic[s].bSalt,
                                    fCrustalMass = dic[s].fCrustal,
                                    fECMass = dic[s].fEC,
                                    fNH4Mass = dic[s].fNH4,
                                    fOcmbMass = dic[s].fOCMmb,
                                    fSO4Mass = dic[s].fSO4,
                                    fNO3Mass = dic[s].fNO3r,
                                    fWaterMass = dic[s].fWater,
                                    fSaltMass = dic[s].fSalt,
                                });
                            }
                        }
                    }
                    if (dailyPMAnalysisConfiguration.pm25CalculationOptionsD.requiredDesignValuePeriodsForValidFRMMonitors == "None selected")
                    {
                        dicDailyPoint.Add(k.Key, new PMPoint()
                        {
                            id = k.Value.id,
                            type = k.Value.type,
                            stateName = k.Value.stateName,
                            countyName = k.Value.countyName,
                            monitorLat = k.Value.lat,
                            monitorLong = k.Value.longitude,
                            monitorGridcell = k.Value.monitorGridcell,
                            bPMDV = dic.Select(p => p.Value.bPM25).Average(),
                            fPMDV = dic.Select(p => p.Value.fPM25).Average(),
                            bCrustalMass = dic.Select(p => p.Value.bCrustal).Average(),
                            bECMass = dic.Select(p => p.Value.bEC).Average(),
                            bNH4Mass = dic.Select(p => p.Value.bNH4).Average(),
                            bOcmbMass = dic.Select(p => p.Value.bOCMmb).Average(),
                            bSO4Mass = dic.Select(p => p.Value.bSO4).Average(),
                            bNO3Mass = dic.Select(p => p.Value.bNO3r).Average(),
                            bWaterMass = dic.Select(p => p.Value.bWater).Average(),
                            bSaltMass = dic.Select(p => p.Value.bSalt).Average(),
                            fCrustalMass = dic.Select(p => p.Value.fCrustal).Average(),
                            fECMass = dic.Select(p => p.Value.fEC).Average(),
                            fNH4Mass = dic.Select(p => p.Value.fNH4).Average(),
                            fOcmbMass = dic.Select(p => p.Value.fOCMmb).Average(),
                            fSO4Mass = dic.Select(p => p.Value.fSO4).Average(),
                            fNO3Mass = dic.Select(p => p.Value.fNO3r).Average(),
                            fWaterMass = dic.Select(p => p.Value.fWater).Average(),
                            fSaltMass = dic.Select(p => p.Value.fSalt).Average(),
                        });
                    }
                    else
                    {
                        List<string> lstPeriod = dailyPMAnalysisConfiguration.pm25CalculationOptionsD.requiredDesignValuePeriodsForValidFRMMonitors.Split(',').ToList();
                        dicDailyPoint.Add(k.Key, new PMPoint()
                        {
                            id = k.Value.id,
                            type = k.Value.type,
                            stateName = k.Value.stateName,
                            countyName = k.Value.countyName,
                            monitorLat = k.Value.lat,
                            monitorLong = k.Value.longitude,
                            monitorGridcell = k.Value.monitorGridcell,
                            bPMDV = dic.Where(p => lstPeriod.Contains(p.Key)).Select(p => p.Value.bPM25).Average(),
                            //bPMDV = dic .Select(p => p.Value.bPM25).Average(),
                            fPMDV = dic.Where(p => lstPeriod.Contains(p.Key)).Select(p => p.Value.fPM25).Average(),
                            bCrustalMass = dic.Select(p => p.Value.bCrustal).Average(),
                            bECMass = dic.Select(p => p.Value.bEC).Average(),
                            bNH4Mass = dic.Select(p => p.Value.bNH4).Average(),
                            bOcmbMass = dic.Select(p => p.Value.bOCMmb).Average(),
                            bSO4Mass = dic.Select(p => p.Value.bSO4).Average(),
                            bNO3Mass = dic.Select(p => p.Value.bNO3r).Average(),
                            bWaterMass = dic.Select(p => p.Value.bWater).Average(),
                            bSaltMass = dic.Select(p => p.Value.bSalt).Average(),
                            fCrustalMass = dic.Select(p => p.Value.fCrustal).Average(),
                            fECMass = dic.Select(p => p.Value.fEC).Average(),
                            fNH4Mass = dic.Select(p => p.Value.fNH4).Average(),
                            fOcmbMass = dic.Select(p => p.Value.fOCMmb).Average(),
                            fSO4Mass = dic.Select(p => p.Value.fSO4).Average(),
                            fNO3Mass = dic.Select(p => p.Value.fNO3r).Average(),
                            fWaterMass = dic.Select(p => p.Value.fWater).Average(),
                            fSaltMass = dic.Select(p => p.Value.fSalt).Average(),
                        });
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        #endregion
        #region save files
        #region save quarterly peak baseline/future model data
        public static bool SaveQuarterlyPeakModelDataCopyDirectly(BaseScenario baseScenario,Dictionary<string,DailyModelMonitor> dicQuarterlyModel,bool isSalt)
        {
            try
            {
                if (!(baseScenario.configuration is DailyPMAnalysisConfiguration))
                {
                    return false;
                }
                DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = (baseScenario.configuration) as DailyPMAnalysisConfiguration;
                File.Copy(dailyPMAnalysisConfiguration.dataInputD.baselineModelFile, _resultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Baseline Quarterly Peak Model Data.csv", true);
                string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Baseline Quarterly Peak Model Data.csv";
                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);

                File.Copy(dailyPMAnalysisConfiguration.dataInputD.forecastModelFile, _resultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Future Quarterly Peak Model Data.csv", true);
                strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Future Quarterly Peak Model Data.csv";
                baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);

                //added by Yangwenwei 20131220
                DataTable dtDeltaModelData = new DataTable();
                //Construct the DataTable "dtDeltaModelData". added by Yangwenwei 20131219
                dtDeltaModelData.Columns.Add("_id");
                dtDeltaModelData.Columns.Add("_type");
                dtDeltaModelData.Columns.Add("lat");
                dtDeltaModelData.Columns.Add("long");
                dtDeltaModelData.Columns.Add("date");
                dtDeltaModelData.Columns.Add("DeltaC(crustal)");
                dtDeltaModelData.Columns.Add("DeltaC(nh4)");
                dtDeltaModelData.Columns.Add("DeltaC(so4)");
                dtDeltaModelData.Columns.Add("DeltaC(ec)");
                dtDeltaModelData.Columns.Add("DeltaC(no3)");
                dtDeltaModelData.Columns.Add("DeltaC(oc)");
                dtDeltaModelData.Columns.Add("DeltaC(pm25)");
                dtDeltaModelData.Columns.Add("DeltaC(cm)");
                if (isSalt == true) dtDeltaModelData.Columns.Add("DeltaC(salt)");//end

                //read data in dicQuarterlyModel and write Delta data
                dicQuarterlyModel = dicQuarterlyModel.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                foreach (KeyValuePair<string, DailyModelMonitor> k in dicQuarterlyModel)
                {
                    foreach (KeyValuePair<string, ModelDataSpecies> kFuture in dicQuarterlyModel[k.Key].dicFutureSpecies)
                    {
                        DataRow drDelta = dtDeltaModelData.NewRow();
                        drDelta[0] = k.Key;
                        drDelta[1] = k.Value.type;
                        drDelta[2] = Math.Round(k.Value.lat,6);
                        drDelta[3] = Math.Round(k.Value.longitude,6);
                        switch(kFuture.Key)
                        {
                            case "1":
                                drDelta[4]="01";
                                break;
                            case"2":
                                drDelta[4]="04";
                                break;
                            case "3":
                                drDelta[4]="07";
                                break;
                            case "4":
                                drDelta[4]="10";
                                break;
                        }
                        drDelta[5] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].crustal - kFuture.Value.crustal, 8);
                        drDelta[6] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].nh4 - kFuture.Value.nh4, 8);
                        drDelta[7] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].so4 - kFuture.Value.so4, 8);
                        drDelta[8] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].ec - kFuture.Value.ec, 8);
                        drDelta[9] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].no3 - kFuture.Value.no3, 8);
                        drDelta[10] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].oc - kFuture.Value.oc, 8);
                        drDelta[11] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].pm25 - kFuture.Value.pm25, 8);
                        drDelta[12] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].cm - kFuture.Value.cm, 8);
                        if (isSalt == true) drDelta[13] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].salt - kFuture.Value.salt, 8);
                        dtDeltaModelData.Rows.Add(drDelta);
                    }                    
                }

                //create Delta CSV added by Yangwenwei 20131219
                strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Delta Quarterly Peak Model Data.csv";
                baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtDeltaModelData, _resultFilePath + @"\" + strFile, "Quarter");
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                dtDeltaModelData.Dispose();//end
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool SaveQuarterlyPeakModelData(BaseScenario baseScenario, Dictionary<string, DailyModelMonitor> dicDailyModel, bool isSalt, string baseYear, string futureYear)
        {
            try
            {
                if (!(baseScenario.configuration is DailyPMAnalysisConfiguration))
                {
                    return false;
                }
                else
                {
                    DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = (baseScenario.configuration) as DailyPMAnalysisConfiguration;
                    DataTable dtBaselineModelData = new DataTable();
                    DataTable dtFutureModelData = new DataTable();
                    DataTable dtDeltaModelData = new DataTable();// added by Yangwenwei 20131219

                    dtBaselineModelData.Columns.Add("_id");
                    dtBaselineModelData.Columns.Add("_type");
                    dtBaselineModelData.Columns.Add("lat");
                    dtBaselineModelData.Columns.Add("long");
                    dtBaselineModelData.Columns.Add("date");
                    dtBaselineModelData.Columns.Add("crustal");
                    dtBaselineModelData.Columns.Add("nh4");
                    dtBaselineModelData.Columns.Add("so4");
                    dtBaselineModelData.Columns.Add("ec");
                    dtBaselineModelData.Columns.Add("no3");
                    dtBaselineModelData.Columns.Add("oc");
                    dtBaselineModelData.Columns.Add("pm25");
                    dtBaselineModelData.Columns.Add("cm");
                    if (isSalt == true) dtBaselineModelData.Columns.Add("salt");

                    dtFutureModelData.Columns.Add("_id");
                    dtFutureModelData.Columns.Add("_type");
                    dtFutureModelData.Columns.Add("lat");
                    dtFutureModelData.Columns.Add("long");
                    dtFutureModelData.Columns.Add("date");
                    dtFutureModelData.Columns.Add("crustal");
                    dtFutureModelData.Columns.Add("nh4");
                    dtFutureModelData.Columns.Add("so4");
                    dtFutureModelData.Columns.Add("ec");
                    dtFutureModelData.Columns.Add("no3");
                    dtFutureModelData.Columns.Add("oc");
                    dtFutureModelData.Columns.Add("pm25");
                    dtFutureModelData.Columns.Add("cm");
                    if (isSalt == true) dtFutureModelData.Columns.Add("salt");
                    
                    //Construct the DataTable "dtDeltaModelData". added by Yangwenwei 20131219
                    dtDeltaModelData.Columns.Add("_id");
                    dtDeltaModelData.Columns.Add("_type");
                    dtDeltaModelData.Columns.Add("lat");
                    dtDeltaModelData.Columns.Add("long");
                    dtDeltaModelData.Columns.Add("date");
                    dtDeltaModelData.Columns.Add("DeltaC(crustal)");
                    dtDeltaModelData.Columns.Add("DeltaC(nh4)");
                    dtDeltaModelData.Columns.Add("DeltaC(so4)");
                    dtDeltaModelData.Columns.Add("DeltaC(ec)");
                    dtDeltaModelData.Columns.Add("DeltaC(no3)");
                    dtDeltaModelData.Columns.Add("DeltaC(oc)");
                    dtDeltaModelData.Columns.Add("DeltaC(pm25)");
                    dtDeltaModelData.Columns.Add("DeltaC(cm)");
                    if (isSalt == true) dtDeltaModelData.Columns.Add("DeltaC(salt)");//end

                    dicDailyModel = dicDailyModel.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicDailyModel)
                    {                        
                        foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicDailyModel[k.Key].dicBaseSpecies)
                        {
                            DataRow drBase = dtBaselineModelData.NewRow();
                            drBase[0] = k.Key;
                            drBase[1] = k.Value.type;
                            drBase[2] = Math.Round(k.Value.lat, 6);
                            drBase[3] = Math.Round(k.Value.longitude, 6);
                            switch (kBase.Key)
                            {
                                case "1":
                                    drBase[4] = baseYear + "01";
                                    break;
                                case "2":
                                    drBase[4] = baseYear + "04";
                                    break;
                                case "3":
                                    drBase[4] = baseYear + "07";
                                    break;
                                case "4":
                                    drBase[4] = baseYear + "10";
                                    break;
                            }
                            drBase[5] = Math.Round(kBase.Value.crustal, 8);
                            drBase[6] = Math.Round(kBase.Value.nh4, 8);
                            drBase[7] = Math.Round(kBase.Value.so4, 8);
                            drBase[8] = Math.Round(kBase.Value.ec, 8);
                            drBase[9] = Math.Round(kBase.Value.no3, 8);
                            drBase[10] = Math.Round(kBase.Value.oc, 8);
                            drBase[11] = Math.Round(kBase.Value.pm25, 8);
                            drBase[12] = Math.Round(kBase.Value.cm, 8);
                            if (isSalt == true) drBase[13] = Math.Round(kBase.Value.salt, 8);
                            dtBaselineModelData.Rows.Add(drBase);
                        }

                        foreach (KeyValuePair<string, ModelDataSpecies> kFuture in dicDailyModel[k.Key].dicFutureSpecies)
                        {
                            DataRow drFuture = dtFutureModelData.NewRow();
                            DataRow drDelta = dtDeltaModelData.NewRow();//added by Yangwenwei
                            drFuture[0] = k.Key;
                            drFuture[1] = k.Value.type;
                            drFuture[2] = Math.Round(k.Value.lat, 6);
                            drFuture[3] = Math.Round(k.Value.longitude, 6);
                            switch (kFuture.Key)
                            {
                                case "1":
                                    drFuture[4] = futureYear + "01";
                                    drDelta[4] = "01";
                                    break;
                                case "2":
                                    drFuture[4] = futureYear + "04";
                                    drDelta[4] = "04";
                                    break;
                                case "3":
                                    drFuture[4] = futureYear + "07";
                                    drDelta[4] = "07";
                                    break;
                                case "4":
                                    drFuture[4] = futureYear + "10";
                                    drDelta[4] = "10";
                                    break;
                            }
                            drFuture[5] = Math.Round(kFuture.Value.crustal, 8);
                            drFuture[6] = Math.Round(kFuture.Value.nh4, 8);
                            drFuture[7] = Math.Round(kFuture.Value.so4, 8);
                            drFuture[8] = Math.Round(kFuture.Value.ec, 8);
                            drFuture[9] = Math.Round(kFuture.Value.no3, 8);
                            drFuture[10] = Math.Round(kFuture.Value.oc, 8);
                            drFuture[11] = Math.Round(kFuture.Value.pm25, 8);
                            drFuture[12] = Math.Round(kFuture.Value.cm, 8);
                            if (isSalt == true) drFuture[13] = Math.Round(kFuture.Value.salt, 8);
                            dtFutureModelData.Rows.Add(drFuture);

                            //write Delta Data in "dtDeltaModelData".added by Yangwenwei 20131219                           
                            drDelta[0] = k.Key;
                            drDelta[1] = k.Value.type;
                            drDelta[2] = Math.Round(k.Value.lat, 6);
                            drDelta[3] = Math.Round(k.Value.longitude, 6);
                            drDelta[5] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].crustal - kFuture.Value.crustal,8);
                            drDelta[6] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].nh4 - kFuture.Value.nh4, 8);
                            drDelta[7] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].so4 - kFuture.Value.so4, 8);
                            drDelta[8] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].ec - kFuture.Value.ec, 8);
                            drDelta[9] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].no3 - kFuture.Value.no3, 8);
                            drDelta[10] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].oc - kFuture.Value.oc, 8);
                            drDelta[11] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].pm25 - kFuture.Value.pm25, 8);
                            drDelta[12] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].cm - kFuture.Value.cm, 8);
                            if (isSalt == true) drDelta[13] = Math.Round(k.Value.dicBaseSpecies[kFuture.Key].salt - kFuture.Value.salt, 8);
                            dtDeltaModelData.Rows.Add(drDelta);//end
                        }
                    }

                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doAutomaticallyExtract)
                    {
                        //if (!Directory.Exists(System.Windows.Forms.Application.StartupPath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName))
                        //    System.IO.Directory.CreateDirectory(System.Windows.Forms.Application.StartupPath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName);
                        if (!CommonClass.IsBatch)
                        {
                            if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                                _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                        }
                        else
                        {
                            if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                                _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                        }
                        if (!Directory.Exists(_resultFilePath))
                            System.IO.Directory.CreateDirectory(_resultFilePath);
                    }
                    string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Baseline Quarterly Peak Model Data.csv";
                    CommonClass.SaveCSV(dtBaselineModelData, _resultFilePath + @"\" + strFile, "Quarter");
                    BaseOutput baseOutput = new BaseOutput();
                    baseOutput.outputName = strFile.Replace(".csv", "");
                    baseOutput.outputType = "Monitor Network";
                    baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                    if (File.Exists(_resultFilePath + @"\" + strFile))
                    {
                        FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                        baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                    }
                    else
                    {
                        baseOutput.outputSize = 0;
                    }
                    CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                    dtBaselineModelData.Dispose();

                    strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Future Quarterly Peak Model Data.csv";
                    baseOutput = new BaseOutput();
                    CommonClass.SaveCSV(dtFutureModelData, _resultFilePath + @"\" + strFile, "Quarter");
                    baseOutput.outputName = strFile.Replace(".csv", "");
                    baseOutput.outputType = "Monitor Network";
                    baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                    if (File.Exists(_resultFilePath + @"\" + strFile))
                    {
                        FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                        baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                    }
                    else
                    {
                        baseOutput.outputSize = 0;
                    }
                    CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                    dtFutureModelData.Dispose();

                    //create Delta CSV added by Yangwenwei 20131219
                    strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Delta Quarterly Peak Model Data.csv";
                    baseOutput = new BaseOutput();
                    CommonClass.SaveCSV(dtDeltaModelData, _resultFilePath + @"\" + strFile, "Quarter");
                    baseOutput.outputName = strFile.Replace(".csv", "");
                    baseOutput.outputType = "Monitor Network";
                    baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                    if (File.Exists(_resultFilePath + @"\" + strFile))
                    {
                        FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                        baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                    }
                    else
                    {
                        baseOutput.outputSize = 0;
                    }
                    CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                    dtDeltaModelData.Dispose();//end

                    GC.Collect();
                    return true;
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        #endregion

        #region save used model data
        public static bool SaveUsedModelData(BaseScenario baseScenario, List<string> lst, Dictionary<string, DailyModelMonitor> dicModel, bool isSalt, string baseYear, string futureYear)
        {
            try
            {
                if (!(baseScenario.configuration is DailyPMAnalysisConfiguration))
                {
                    return false;
                }
                else
                {
                    DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = baseScenario.configuration as DailyPMAnalysisConfiguration;
                    DataTable dtBaselineModelDataUsed = new DataTable();
                    DataTable dtFutureModelDataUsed = new DataTable();
                    DataTable dtDeltaModelDataUsed = new DataTable();// added by Yangwenwei 20131219

                    dtBaselineModelDataUsed.Columns.Add("_id");
                    dtBaselineModelDataUsed.Columns.Add("_type");
                    dtBaselineModelDataUsed.Columns.Add("lat");
                    dtBaselineModelDataUsed.Columns.Add("long");
                    dtBaselineModelDataUsed.Columns.Add("date");
                    dtBaselineModelDataUsed.Columns.Add("crustal");
                    dtBaselineModelDataUsed.Columns.Add("nh4");
                    dtBaselineModelDataUsed.Columns.Add("so4");
                    dtBaselineModelDataUsed.Columns.Add("ec");
                    dtBaselineModelDataUsed.Columns.Add("no3");
                    dtBaselineModelDataUsed.Columns.Add("oc");
                    dtBaselineModelDataUsed.Columns.Add("pm25");
                    dtBaselineModelDataUsed.Columns.Add("cm");
                    if (isSalt == true) dtBaselineModelDataUsed.Columns.Add("salt");

                    dtFutureModelDataUsed.Columns.Add("_id");
                    dtFutureModelDataUsed.Columns.Add("_type");
                    dtFutureModelDataUsed.Columns.Add("lat");
                    dtFutureModelDataUsed.Columns.Add("long");
                    dtFutureModelDataUsed.Columns.Add("date");
                    dtFutureModelDataUsed.Columns.Add("crustal");
                    dtFutureModelDataUsed.Columns.Add("nh4");
                    dtFutureModelDataUsed.Columns.Add("so4");
                    dtFutureModelDataUsed.Columns.Add("ec");
                    dtFutureModelDataUsed.Columns.Add("no3");
                    dtFutureModelDataUsed.Columns.Add("oc");
                    dtFutureModelDataUsed.Columns.Add("pm25");
                    dtFutureModelDataUsed.Columns.Add("cm");
                    if (isSalt == true) dtBaselineModelDataUsed.Columns.Add("salt");

                    //Construct the DataTable "dtDeltaModelData". added by Yangwenwei 20131219
                    dtDeltaModelDataUsed.Columns.Add("_id");
                    dtDeltaModelDataUsed.Columns.Add("_type");
                    dtDeltaModelDataUsed.Columns.Add("lat");
                    dtDeltaModelDataUsed.Columns.Add("long");
                    dtDeltaModelDataUsed.Columns.Add("date");
                    dtDeltaModelDataUsed.Columns.Add("DeltaC(crustal)");
                    dtDeltaModelDataUsed.Columns.Add("DeltaC(nh4)");
                    dtDeltaModelDataUsed.Columns.Add("DeltaC(so4)");
                    dtDeltaModelDataUsed.Columns.Add("DeltaC(ec)");
                    dtDeltaModelDataUsed.Columns.Add("DeltaC(no3)");
                    dtDeltaModelDataUsed.Columns.Add("DeltaC(oc)");
                    dtDeltaModelDataUsed.Columns.Add("DeltaC(pm25)");
                    dtDeltaModelDataUsed.Columns.Add("DeltaC(cm)");
                    if (isSalt == true) dtDeltaModelDataUsed.Columns.Add("DeltaC(salt)");//end
                   
                    for (int i = 0; i < lst.Count; i++)
                    {
                        //used base model data
                        foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicModel[lst[i]].dicBaseSpecies)
                        {
                            DataRow drBase = dtBaselineModelDataUsed.NewRow();
                            drBase[0] = lst[i];
                            drBase[1] = dicModel[lst[i]].type;
                            drBase[2] = Math.Round(dicModel[lst[i]].lat, 6);
                            drBase[3] = Math.Round(dicModel[lst[i]].longitude, 6);
                            switch (kBase.Key)
                            {
                                case "1":
                                    drBase[4] = baseYear + "01";
                                    break;
                                case "2":
                                    drBase[4] = baseYear + "04";
                                    break;
                                case "3":
                                    drBase[4] = baseYear + "07";
                                    break;
                                case "4":
                                    drBase[4] = baseYear + "10";
                                    break;
                            }
                            drBase[5] = Math.Round(kBase.Value.crustal, 8);
                            drBase[6] = Math.Round(kBase.Value.nh4, 8);
                            drBase[7] = Math.Round(kBase.Value.so4, 8);
                            drBase[8] = Math.Round(kBase.Value.ec, 8);
                            drBase[9] = Math.Round(kBase.Value.no3, 8);
                            drBase[10] = Math.Round(kBase.Value.oc, 8);
                            drBase[11] = Math.Round(kBase.Value.pm25, 8);
                            drBase[12] = Math.Round(kBase.Value.cm, 8);
                            if (isSalt == true) drBase[13] = Math.Round(kBase.Value.salt, 8);
                            dtBaselineModelDataUsed.Rows.Add(drBase);
                        }

                        //used future model data
                        foreach (KeyValuePair<string, ModelDataSpecies> kFuture in dicModel[lst[i]].dicFutureSpecies)
                        {
                            DataRow drFuture = dtFutureModelDataUsed.NewRow();
                            DataRow drDelta = dtDeltaModelDataUsed.NewRow();//added by Yangwenwei
                            drFuture[0] = lst[i];
                            drFuture[1] = dicModel[lst[i]].type;
                            drFuture[2] = Math.Round(dicModel[lst[i]].lat, 6);
                            drFuture[3] = Math.Round(dicModel[lst[i]].longitude, 6);
                            switch (kFuture.Key)
                            {
                                case "1":
                                    drFuture[4] = futureYear + "01";
                                    drDelta[4] = "01";
                                    break;
                                case "2":
                                    drFuture[4] = futureYear + "04";
                                    drDelta[4] = "04";
                                    break;
                                case "3":
                                    drFuture[4] = futureYear + "07";
                                    drDelta[4] = "07";
                                    break;
                                case "4":
                                    drFuture[4] = futureYear + "10";
                                    drDelta[4] = "10";
                                    break;
                            }
                            drFuture[5] = Math.Round(kFuture.Value.crustal, 8);
                            drFuture[6] = Math.Round(kFuture.Value.nh4, 8);
                            drFuture[7] = Math.Round(kFuture.Value.so4, 8);
                            drFuture[8] = Math.Round(kFuture.Value.ec, 8);
                            drFuture[9] = Math.Round(kFuture.Value.no3, 8);
                            drFuture[10] = Math.Round(kFuture.Value.oc, 8);
                            drFuture[11] = Math.Round(kFuture.Value.pm25, 8);
                            drFuture[12] = Math.Round(kFuture.Value.cm, 8);
                            if (isSalt == true) drFuture[13] = Math.Round(kFuture.Value.salt, 8);
                            dtFutureModelDataUsed.Rows.Add(drFuture);

                            //write Delta Data in "dtDeltaModelData".added by Yangwenwei 20131219
                           
                            drDelta[0] = lst[i];
                            drDelta[1] = dicModel[lst[i]].type;
                            drDelta[2] = Math.Round(dicModel[lst[i]].lat, 6);
                            drDelta[3] = Math.Round(dicModel[lst[i]].longitude, 6);
                            drDelta[5] = Math.Round(dicModel[lst[i]].dicBaseSpecies[kFuture.Key].crustal - kFuture.Value.crustal, 8);
                            drDelta[6] = Math.Round(dicModel[lst[i]].dicBaseSpecies[kFuture.Key].nh4 - kFuture.Value.nh4, 8);
                            drDelta[7] = Math.Round(dicModel[lst[i]].dicBaseSpecies[kFuture.Key].so4 - kFuture.Value.so4, 8);
                            drDelta[8] = Math.Round(dicModel[lst[i]].dicBaseSpecies[kFuture.Key].ec - kFuture.Value.ec, 8);
                            drDelta[9] = Math.Round(dicModel[lst[i]].dicBaseSpecies[kFuture.Key].no3 - kFuture.Value.no3, 8);
                            drDelta[10] = Math.Round(dicModel[lst[i]].dicBaseSpecies[kFuture.Key].oc - kFuture.Value.oc, 8);
                            drDelta[11] = Math.Round(dicModel[lst[i]].dicBaseSpecies[kFuture.Key].pm25 - kFuture.Value.pm25, 8);
                            drDelta[12] = Math.Round(dicModel[lst[i]].dicBaseSpecies[kFuture.Key].cm - kFuture.Value.cm, 8);
                            if (isSalt == true) drDelta[13] = Math.Round(dicModel[lst[i]].dicBaseSpecies[kFuture.Key].salt - kFuture.Value.salt, 8);
                            dtDeltaModelDataUsed.Rows.Add(drDelta);//end
                        }
                    }
                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doAutomaticallyExtract)
                    {
                        //if (!Directory.Exists(System.Windows.Forms.Application.StartupPath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName))
                        //    System.IO.Directory.CreateDirectory(System.Windows.Forms.Application.StartupPath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName);
                        if (!CommonClass.IsBatch)
                        {
                            if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                                _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                        }
                        else
                        {
                            if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                                _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                        }
                        if (!Directory.Exists(_resultFilePath))
                            System.IO.Directory.CreateDirectory(_resultFilePath);
                    }
                    string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Used Baseline Quarterly Peak Model Data.csv";
                    CommonClass.SaveCSV(dtBaselineModelDataUsed, _resultFilePath + @"\" + strFile, "Quarter");
                    BaseOutput baseOutput = new BaseOutput();
                    baseOutput.outputName = strFile.Replace(".csv", "");
                    baseOutput.outputType = "Monitor Network";
                    baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                    if (File.Exists(_resultFilePath + @"\" + strFile))
                    {
                        FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                        baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                    }
                    else
                    {
                        baseOutput.outputSize = 0;
                    }
                    CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);

                    strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Used Future Quarterly Peak Model Data.csv";
                    CommonClass.SaveCSV(dtFutureModelDataUsed, _resultFilePath + @"\" + strFile, "Quarter");
                    baseOutput = new BaseOutput();
                    baseOutput.outputName = strFile.Replace(".csv", "");
                    baseOutput.outputType = "Monitor Network";
                    baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                    if (File.Exists(_resultFilePath + @"\" + strFile))
                    {
                        FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                        baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                    }
                    else
                    {
                        baseOutput.outputSize = 0;
                    }
                    CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);

                    //create Delta CSV. added by Yangwenwei
                    strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Used Delta Quarterly Peak Model Data.csv";
                    baseOutput = new BaseOutput();
                    CommonClass.SaveCSV(dtDeltaModelDataUsed, _resultFilePath + @"\" + strFile, "Quarter");
                    baseOutput.outputName = strFile.Replace(".csv", "");
                    baseOutput.outputType = "Monitor Network";
                    baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                    if (File.Exists(_resultFilePath + @"\" + strFile))
                    {
                        FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                        baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                    }
                    else
                    {
                        baseOutput.outputSize = 0;
                    }
                    CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                    dtDeltaModelDataUsed.Dispose();//end
                    dtBaselineModelDataUsed.Dispose();
                    dtFutureModelDataUsed.Dispose();
                    GC.Collect();
                    return true;
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        #endregion

        #region save high county sites
        public static bool SaveHighCountySites(BaseScenario baseScenario, Dictionary<string, PMPoint> dicDailyPMPoint, string period)
        {
            try
            {
                if (!(baseScenario.configuration is DailyPMAnalysisConfiguration))
                {
                    return false;
                }
                else
                {
                    DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = baseScenario.configuration as DailyPMAnalysisConfiguration;
                    DataTable dt = new DataTable();
                    dt.Columns.Add("_id");
                    dt.Columns.Add("_type");
                    dt.Columns.Add("_state_name");
                    dt.Columns.Add("_county_name");
                    dt.Columns.Add("monitor_lat");
                    dt.Columns.Add("monitor_long");
                    dt.Columns.Add("monitor_gridcell");
                    dt.Columns.Add("b_pm25_d_DV");
                    dt.Columns.Add("f_pm25_d_DV");
                    dt.Columns.Add("b_blank_mass");
                    dt.Columns.Add("b_crustal_mass");
                    dt.Columns.Add("b_EC_mass");
                    dt.Columns.Add("b_NH4_mass");
                    dt.Columns.Add("b_Ocmb_mass");
                    dt.Columns.Add("b_SO4_mass");
                    dt.Columns.Add("b_NO3_mass");
                    dt.Columns.Add("b_water_mass");
                    dt.Columns.Add("b_salt_mass");
                    dt.Columns.Add("f_blank_mass");
                    dt.Columns.Add("f_crustal_mass");
                    dt.Columns.Add("f_EC_mass");
                    dt.Columns.Add("f_NH4_mass");
                    dt.Columns.Add("f_Ocmb_mass");
                    dt.Columns.Add("f_SO4_mass");
                    dt.Columns.Add("f_NO3_mass");
                    dt.Columns.Add("f_water_mass");
                    dt.Columns.Add("f_salt_mass");
                    dt.Columns.Add("rrf_crustal");
                    dt.Columns.Add("rrf_ec");
                    dt.Columns.Add("rrf_nh4");
                    dt.Columns.Add("rrf_oc");
                    dt.Columns.Add("rrf_so4");
                    dt.Columns.Add("rrf_no3");
                    dt.Columns.Add("rrf_water");
                    dt.Columns.Add("rrf_salt");
                    dicDailyPMPoint = dicDailyPMPoint.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                    Dictionary<string, List<string>> dicStateCounty = new Dictionary<string, List<string>>();
                    foreach (KeyValuePair<string, PMPoint> k in dicDailyPMPoint)
                    {
                        if (dicStateCounty.ContainsKey(k.Value.stateName))
                        {
                            if (!dicStateCounty[k.Value.stateName].Contains(k.Value.countyName))
                            {
                                dicStateCounty[k.Value.stateName].Add(k.Value.countyName);
                            }
                        }
                        else
                        {
                            dicStateCounty.Add(k.Value.stateName, new List<string>() { k.Value.countyName });
                        }
                    }
                    List<string> lstCountyName = dicDailyPMPoint.Select(p => p.Value.countyName).Distinct().ToList();
                    foreach (KeyValuePair<string, List<string>> kState in dicStateCounty)
                    {
                        foreach (string s in kState.Value)
                        {
                            var query = dicDailyPMPoint.Where(p => p.Value.stateName == kState.Key && p.Value.countyName == s).OrderByDescending(p => p.Value.fPMDV).First();
                            DataRow dr = dt.NewRow();
                            dr[0] = query.Value.id;
                            dr[1] = query.Value.type;
                            dr[2] = query.Value.stateName;
                            dr[3] = query.Value.countyName;
                            dr[4] = Math.Round(query.Value.monitorLat, 6);
                            dr[5] = Math.Round(query.Value.monitorLong, 6);
                            dr[6] = query.Value.monitorGridcell;
                            dr[7] = Math.Round(query.Value.bPMDV, 8);
                            dr[8] = Math.Round(query.Value.fPMDV, 8);
                            dr[9] = Math.Round(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass, 8);
                            dr[10] = Math.Round(query.Value.bCrustalMass, 8);
                            dr[11] = Math.Round(query.Value.bECMass, 8);
                            dr[12] = Math.Round(query.Value.bNH4Mass, 8);
                            dr[13] = Math.Round(query.Value.bOcmbMass, 8);
                            dr[14] = Math.Round(query.Value.bSO4Mass, 8);
                            dr[15] = Math.Round(query.Value.bNO3Mass, 8);
                            dr[16] = Math.Round(query.Value.bWaterMass, 8);
                            dr[17] = Math.Round(query.Value.bSaltMass, 8);
                            dr[18] = Math.Round(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass, 8);
                            dr[19] = Math.Round(query.Value.fCrustalMass, 8);
                            dr[20] = Math.Round(query.Value.fECMass, 8);
                            dr[21] = Math.Round(query.Value.fNH4Mass, 8);
                            dr[22] = Math.Round(query.Value.fOcmbMass, 8);
                            dr[23] = Math.Round(query.Value.fSO4Mass, 8);
                            dr[24] = Math.Round(query.Value.fNO3Mass, 8);
                            dr[25] = Math.Round(query.Value.fWaterMass, 8);
                            dr[26] = Math.Round(query.Value.fSaltMass, 8);
                            dr[27] = Double.IsNaN(query.Value.fCrustalMass / query.Value.bCrustalMass) || Double.IsInfinity(query.Value.fCrustalMass / query.Value.bCrustalMass) ? -9 : Math.Round(query.Value.fCrustalMass / query.Value.bCrustalMass, 8);
                            dr[28] = Double.IsNaN(query.Value.fECMass / query.Value.bECMass) || Double.IsInfinity(query.Value.fECMass / query.Value.bECMass) ? -9 : Math.Round(query.Value.fECMass / query.Value.bECMass, 8);
                            dr[29] = Double.IsNaN(query.Value.fNH4Mass / query.Value.bNH4Mass) || Double.IsInfinity(query.Value.fNH4Mass / query.Value.bNH4Mass) ? -9 : Math.Round(query.Value.fNH4Mass / query.Value.bNH4Mass, 8);
                            dr[30] = Double.IsNaN(query.Value.fOcmbMass / query.Value.bOcmbMass) || Double.IsInfinity(query.Value.fOcmbMass / query.Value.bOcmbMass) ? -9 : Math.Round(query.Value.fOcmbMass / query.Value.bOcmbMass, 8);
                            dr[31] = Double.IsNaN(query.Value.fSO4Mass / query.Value.bSO4Mass) || Double.IsInfinity(query.Value.fSO4Mass / query.Value.bSO4Mass) ? -9 : Math.Round(query.Value.fSO4Mass / query.Value.bSO4Mass, 8);
                            dr[32] = Double.IsNaN(query.Value.fNO3Mass / query.Value.bNO3Mass) || Double.IsInfinity(query.Value.fNO3Mass / query.Value.bNO3Mass) ? -9 : Math.Round(query.Value.fNO3Mass / query.Value.bNO3Mass, 8);
                            dr[33] = Double.IsNaN(query.Value.fWaterMass / query.Value.bWaterMass) || Double.IsInfinity(query.Value.fWaterMass / query.Value.bWaterMass) ? -9 : Math.Round(query.Value.fWaterMass / query.Value.bWaterMass, 8);
                            dr[34] = Double.IsNaN(query.Value.fSaltMass / query.Value.bSaltMass) || Double.IsInfinity(query.Value.fSaltMass / query.Value.bSaltMass) ? -9 : Math.Round(query.Value.fSaltMass / query.Value.bSaltMass, 8);
                            dt.Rows.Add(dr);
                        }
                    }
                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doAutomaticallyExtract)
                    {
                        if (!CommonClass.IsBatch)
                        {
                            if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                                _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                        }
                        else
                        {
                            if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                                _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                        }
                        if (!Directory.Exists(_resultFilePath))
                            System.IO.Directory.CreateDirectory(_resultFilePath);
                    }
                    string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " High County Sites" + period + ".csv";
                    BaseOutput baseOutput = new BaseOutput();
                    CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                    baseOutput.outputName = strFile.Replace(".csv", "");
                    baseOutput.outputType = "Monitor Network";
                    baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                    if (File.Exists(_resultFilePath + @"\" + strFile))
                    {
                        FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                        baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                    }
                    else
                    {
                        baseOutput.outputSize = 0;
                    }
                    CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                    dt.Dispose();
                    GC.Collect();
                    return true;
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        #endregion

        #region save daily pm25 point
        public static bool SaveDailyPmPoint(BaseScenario baseScenario, Dictionary<string, PMPoint> dicDailyPMPoint, string period)
        {
            try
            {
                if (!(baseScenario.configuration is DailyPMAnalysisConfiguration))
                { return false; }
                else
                {
                    DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = baseScenario.configuration as DailyPMAnalysisConfiguration;
                    DataTable dt = new DataTable();
                    dt.Columns.Add("_id");
                    dt.Columns.Add("_type");
                    dt.Columns.Add("_state_name");
                    dt.Columns.Add("_county_name");
                    dt.Columns.Add("monitor_lat");
                    dt.Columns.Add("monitor_long");
                    dt.Columns.Add("monitor_gridcell");
                    dt.Columns.Add("b_pm25_d_DV");
                    dt.Columns.Add("f_pm25_d_DV");
                    dt.Columns.Add("b_blank_mass");
                    dt.Columns.Add("b_crustal_mass");
                    dt.Columns.Add("b_EC_mass");
                    dt.Columns.Add("b_NH4_mass");
                    dt.Columns.Add("b_Ocmb_mass");
                    dt.Columns.Add("b_SO4_mass");
                    dt.Columns.Add("b_NO3_mass");
                    dt.Columns.Add("b_water_mass");
                    dt.Columns.Add("b_salt_mass");
                    dt.Columns.Add("f_blank_mass");
                    dt.Columns.Add("f_crustal_mass");
                    dt.Columns.Add("f_EC_mass");
                    dt.Columns.Add("f_NH4_mass");
                    dt.Columns.Add("f_Ocmb_mass");
                    dt.Columns.Add("f_SO4_mass");
                    dt.Columns.Add("f_NO3_mass");
                    dt.Columns.Add("f_water_mass");
                    dt.Columns.Add("f_salt_mass");
                    dt.Columns.Add("rrf_crustal");
                    dt.Columns.Add("rrf_ec");
                    dt.Columns.Add("rrf_nh4");
                    dt.Columns.Add("rrf_oc");
                    dt.Columns.Add("rrf_so4");
                    dt.Columns.Add("rrf_no3");
                    dt.Columns.Add("rrf_water");
                    dt.Columns.Add("rrf_salt");

                    foreach (KeyValuePair<string, PMPoint> k in dicDailyPMPoint)
                    {
                        DataRow dr = dt.NewRow();
                        dr[0] = k.Value.id;
                        dr[1] = k.Value.type;
                        dr[2] = k.Value.stateName;
                        dr[3] = k.Value.countyName;
                        dr[4] = Math.Round(k.Value.monitorLat, 6);
                        dr[5] = Math.Round(k.Value.monitorLong, 6);
                        dr[6] = k.Value.monitorGridcell;
                        dr[7] = CommonClass.ToFixed(k.Value.bPMDV, CommonClass.Pm_daily_base_output_precision);
                        dr[8] = CommonClass.ToFixed(k.Value.fPMDV, CommonClass.Pm_daily_output_precisionfuture_final);
                        dr[9] = Math.Round(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass, 8);
                        dr[10] = Math.Round(k.Value.bCrustalMass, 8);
                        dr[11] = Math.Round(k.Value.bECMass, 8);
                        dr[12] = Math.Round(k.Value.bNH4Mass, 8);
                        dr[13] = Math.Round(k.Value.bOcmbMass, 8);
                        dr[14] = Math.Round(k.Value.bSO4Mass, 8);
                        dr[15] = Math.Round(k.Value.bNO3Mass, 8);
                        dr[16] = Math.Round(k.Value.bWaterMass, 8);
                        dr[17] = Math.Round(k.Value.bSaltMass, 8);
                        dr[18] = dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass;
                        dr[19] = Math.Round(k.Value.fCrustalMass, 8);
                        dr[20] = Math.Round(k.Value.fECMass, 8);
                        dr[21] = Math.Round(k.Value.fNH4Mass, 8);
                        dr[22] = Math.Round(k.Value.fOcmbMass, 8);
                        dr[23] = Math.Round(k.Value.fSO4Mass, 8);
                        dr[24] = Math.Round(k.Value.fNO3Mass, 8);
                        dr[25] = Math.Round(k.Value.fWaterMass, 8);
                        dr[26] = Math.Round(k.Value.fSaltMass, 8);
                        dr[27] = Double.IsNaN(Math.Round(k.Value.fCrustalMass, 8) / Math.Round(k.Value.bCrustalMass, 8)) || Double.IsInfinity(Math.Round(k.Value.fCrustalMass, 8) / Math.Round(k.Value.bCrustalMass, 8)) ? -9 : Math.Round(k.Value.fCrustalMass / k.Value.bCrustalMass, 8);
                        dr[28] = Double.IsNaN(Math.Round(k.Value.fECMass, 8) / Math.Round(k.Value.bECMass, 8)) || Double.IsInfinity(Math.Round(k.Value.fECMass, 8) / Math.Round(k.Value.bECMass, 8)) ? -9 : Math.Round(k.Value.fECMass / k.Value.bECMass, 8);
                        dr[29] = Double.IsNaN(Math.Round(k.Value.fNH4Mass, 8) / Math.Round(k.Value.bNH4Mass, 8)) || Double.IsInfinity(Math.Round(k.Value.fNH4Mass, 8) / Math.Round(k.Value.bNH4Mass, 8)) ? -9 : Math.Round(k.Value.fNH4Mass / k.Value.bNH4Mass, 8);
                        dr[30] = Double.IsNaN(Math.Round(k.Value.fOcmbMass, 8) / Math.Round(k.Value.bOcmbMass, 8)) || Double.IsInfinity(Math.Round(k.Value.fOcmbMass, 8) / Math.Round(k.Value.bOcmbMass, 8)) ? -9 : Math.Round(k.Value.fOcmbMass / k.Value.bOcmbMass, 8);
                        dr[31] = Double.IsNaN(Math.Round(k.Value.fSO4Mass, 8) / Math.Round(k.Value.bSO4Mass, 8)) || Double.IsInfinity(Math.Round(k.Value.fSO4Mass, 8) / Math.Round(k.Value.bSO4Mass, 8)) ? -9 : Math.Round(k.Value.fSO4Mass / k.Value.bSO4Mass, 8);
                        dr[32] = Double.IsNaN(Math.Round(k.Value.fNO3Mass, 8) / Math.Round(k.Value.bNO3Mass, 8)) || Double.IsInfinity(Math.Round(k.Value.fNO3Mass, 8) / Math.Round(k.Value.bNO3Mass, 8)) ? -9 : Math.Round(k.Value.fNO3Mass / k.Value.bNO3Mass, 8);
                        dr[33] = Double.IsNaN(Math.Round(k.Value.fWaterMass, 8) / Math.Round(k.Value.bWaterMass, 8)) || Double.IsInfinity(Math.Round(k.Value.fWaterMass, 8) / Math.Round(k.Value.bWaterMass, 8)) ? -9 : Math.Round(k.Value.fWaterMass / k.Value.bWaterMass, 8);
                        dr[34] = Double.IsNaN(Math.Round(k.Value.fSaltMass, 8) / Math.Round(k.Value.bSaltMass, 8)) || Double.IsInfinity(Math.Round(k.Value.fSaltMass, 8) / Math.Round(k.Value.bSaltMass, 8)) ? -9 : Math.Round(k.Value.fSaltMass / k.Value.bSaltMass, 8);
                        dt.Rows.Add(dr);
                    }

                    if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doAutomaticallyExtract)
                    {
                        if (!CommonClass.IsBatch)
                        {
                            if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                                _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                        }
                        else
                        {
                            if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                                _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                        }
                        if (!Directory.Exists(_resultFilePath))
                            System.IO.Directory.CreateDirectory(_resultFilePath);
                    }
                    string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Daily PM25 Point" + period + ".csv";
                    BaseOutput baseOutput = new BaseOutput();
                    CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Year");
                    baseOutput.outputName = strFile.Replace(".csv", "");
                    baseOutput.outputType = "Monitor Network";
                    baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                    if (File.Exists(_resultFilePath + @"\" + strFile))
                    {
                        FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                        baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                    }
                    else
                    {
                        baseOutput.outputSize = 0;
                    }
                    CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                    dt.Dispose();
                    GC.Collect();
                    return true;
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        #endregion

        #region save quarterly peak PM monitors
        public static bool SaveQuarterlyPeakPMMonitors(BaseScenario baseScenario, Dictionary<string, Monitors> dicPMUnofficial)
        {
            try
            {
                DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = (baseScenario.configuration) as DailyPMAnalysisConfiguration;
                DataTable dt = new DataTable();
                dt.Columns.Add("_id");
                dt.Columns.Add("_type");
                dt.Columns.Add("monitor_lat");
                dt.Columns.Add("monitor_long");
                dt.Columns.Add("monitor_gridcell");
                dt.Columns.Add("quarter");
                dt.Columns.Add("b_pm25_mass");

                foreach (KeyValuePair<string, Monitors> k in dicPMUnofficial)
                {
                    foreach (KeyValuePair<string, PM25Monitors> kin in dicPMUnofficial[k.Key].dicPM)
                    {
                        DataRow dr = dt.NewRow();
                        dr[0] = k.Key;
                        dr[1] = k.Value.type;
                        dr[2] = Math.Round(k.Value.lat, 6);
                        dr[3] = Math.Round(k.Value.longitude, 6);
                        dr[4] = k.Value.monitorGridcell;
                        dr[5] = kin.Key;
                        dr[6] = Math.Round(kin.Value.bPM25, 8);
                        dt.Rows.Add(dr);
                    }
                }
                if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doAutomaticallyExtract)
                {
                    if (!CommonClass.IsBatch)
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    else
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    if (!Directory.Exists(_resultFilePath))
                        System.IO.Directory.CreateDirectory(_resultFilePath);
                }
                string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Quarterly Peak PM2.5 Monitors.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Quarter");
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        #endregion

        #region save quarterly peak species fractions point
        public static bool SaveSpeciesFractions(BaseScenario baseScenario, Dictionary<string, Monitors> dicSpeciesFractions, string period)
        {
            try
            {
                DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = (baseScenario.configuration) as DailyPMAnalysisConfiguration;
                DataTable dtSpeciesFractions = new DataTable();
                dtSpeciesFractions.Columns.Add("_id");
                dtSpeciesFractions.Columns.Add("_STATE_NAME");
                dtSpeciesFractions.Columns.Add("_COUNTY_NAME");
                dtSpeciesFractions.Columns.Add("monitor_lat");
                dtSpeciesFractions.Columns.Add("monitor_long");
                dtSpeciesFractions.Columns.Add("quarter");
                dtSpeciesFractions.Columns.Add("pm25_mass_frac");
                dtSpeciesFractions.Columns.Add("fcr");
                dtSpeciesFractions.Columns.Add("fec");
                dtSpeciesFractions.Columns.Add("fnh4");
                dtSpeciesFractions.Columns.Add("focm");
                dtSpeciesFractions.Columns.Add("fso4");
                dtSpeciesFractions.Columns.Add("fno3");
                dtSpeciesFractions.Columns.Add("fwater");
                dtSpeciesFractions.Columns.Add("fsalt");
                dtSpeciesFractions.Columns.Add("blank_mass");
                dtSpeciesFractions.Columns.Add("don");
                dtSpeciesFractions.Columns.Add("i_so4");
                dtSpeciesFractions.Columns.Add("i_no3r");
                dtSpeciesFractions.Columns.Add("i_ocb");
                dtSpeciesFractions.Columns.Add("i_ec");
                dtSpeciesFractions.Columns.Add("i_crustal");
                dtSpeciesFractions.Columns.Add("i_don");
                dtSpeciesFractions.Columns.Add("i_nh4");
                dtSpeciesFractions.Columns.Add("i_no3");
                dtSpeciesFractions.Columns.Add("i_salt");
                foreach (KeyValuePair<string, Monitors> k in dicSpeciesFractions)
                {
                    foreach (KeyValuePair<string, SpecFracPM> kin in dicSpeciesFractions[k.Key].dicSpeciesFractions)
                    {
                        DataRow dr = dtSpeciesFractions.NewRow();
                        dr[0] = k.Key;
                        dr[1] = k.Value.stateName;
                        dr[2] = k.Value.countyName;
                        dr[3] = Math.Round(k.Value.lat, 6);
                        dr[4] = Math.Round(k.Value.longitude, 6);
                        dr[5] = kin.Key;
                        dr[6] = Math.Round(kin.Value.pm25MassFrac, 8);
                        dr[7] = Math.Round(kin.Value.fCr, 8);
                        dr[8] = Math.Round(kin.Value.fEC, 8);
                        dr[9] = Math.Round(kin.Value.fNH4, 8);
                        dr[10] = Math.Round(kin.Value.fOcm, 8);
                        dr[11] = Math.Round(kin.Value.fSO4, 8);
                        dr[12] = Math.Round(kin.Value.fNO3r, 8);
                        dr[13] = Math.Round(kin.Value.fWater, 8);
                        dr[14] = Math.Round(kin.Value.fSalt, 8);
                        dr[15] = Math.Round(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass, 8);
                        dr[16] = Math.Round(kin.Value.don, 8);
                        dr[17] = Math.Round(kin.Value.iSO4, 8);
                        dr[18] = Math.Round(kin.Value.iNO3r, 8);
                        dr[19] = Math.Round(kin.Value.iOcb, 8);
                        dr[20] = Math.Round(kin.Value.iEC, 8);
                        dr[21] = Math.Round(kin.Value.iCrustal, 8);
                        dr[22] = Math.Round(kin.Value.iDON, 8);
                        dr[23] = Math.Round(kin.Value.iNH4, 8);
                        dr[24] = Math.Round(kin.Value.iNO3, 8);
                        dr[25] = Math.Round(kin.Value.iSalt, 8);
                        dtSpeciesFractions.Rows.Add(dr);
                    }
                }

                if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doAutomaticallyExtract)
                {
                    if (!CommonClass.IsBatch)
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    else
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    if (!Directory.Exists(_resultFilePath))
                        System.IO.Directory.CreateDirectory(_resultFilePath);
                }
                string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Quarterly Peak Spec Frac Point" + period + ".csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtSpeciesFractions, _resultFilePath + @"\" + strFile, "Quarter");
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                dtSpeciesFractions.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        #endregion

        public static bool SaveSpeciesFractionCopyDirectly(BaseScenario baseScenario)
        {
            try
            {
                DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = (baseScenario.configuration) as DailyPMAnalysisConfiguration;
                File.Copy(dailyPMAnalysisConfiguration.dataInputD.specFracPointFile, Application.StartupPath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Quarterly Peak Spec Frac Point.csv", true);
                string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Quarterly Peak Spec Frac Point.csv";
                BaseOutput baseOutput = new BaseOutput();
                //CommonClass.SaveCSV(dtSpeciesFractions, _resultFilePath + @"\" + strFile, "Quarter");
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                //dtSpeciesFractions.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        #region save quarterly peak speciated monitors
        public static bool SaveQuarterlyPeakSpeciatedMonitors(BaseScenario baseScenario, Dictionary<string, Monitors> dicSpeciatedMonitors)
        {
            try
            {
                DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = (baseScenario.configuration) as DailyPMAnalysisConfiguration;
                DataTable dtSpeciatedMonitors = new DataTable();
                DataRow drSpeciatedMonitors = null;
                dtSpeciatedMonitors.Columns.Add("_id");
                dtSpeciatedMonitors.Columns.Add("_type");
                dtSpeciatedMonitors.Columns.Add("monitor_lat");
                dtSpeciatedMonitors.Columns.Add("monitor_long");
                dtSpeciatedMonitors.Columns.Add("monitor_gridcell");
                dtSpeciatedMonitors.Columns.Add("quarter");
                dtSpeciatedMonitors.Columns.Add("b_crustal_mass");
                dtSpeciatedMonitors.Columns.Add("b_EC_mass");
                dtSpeciatedMonitors.Columns.Add("b_OCB_mass");
                dtSpeciatedMonitors.Columns.Add("b_SO4_mass");
                dtSpeciatedMonitors.Columns.Add("b_NO3_mass");
                dtSpeciatedMonitors.Columns.Add("b_no3r_mass");
                dtSpeciatedMonitors.Columns.Add("b_salt_mass");

                DataTable dtNH4_DON = new DataTable();
                DataRow drNH4_DON = null;
                dtNH4_DON.Columns.Add("_id");
                dtNH4_DON.Columns.Add("_type");
                dtNH4_DON.Columns.Add("monitor_lat");
                dtNH4_DON.Columns.Add("monitor_long");
                dtNH4_DON.Columns.Add("monitor_gridcell");
                dtNH4_DON.Columns.Add("quarter");
                dtNH4_DON.Columns.Add("b_nh4_mass");
                dtNH4_DON.Columns.Add("b_don");

                dicSpeciatedMonitors = dicSpeciatedMonitors.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                foreach (KeyValuePair<string, Monitors> k in dicSpeciatedMonitors)
                {
                    foreach (KeyValuePair<string, SpeciesForFractions> kin in dicSpeciatedMonitors[k.Key].dicSpeciesMonitors)
                    {
                        drSpeciatedMonitors = dtSpeciatedMonitors.NewRow();
                        drSpeciatedMonitors[0] = k.Key;
                        drSpeciatedMonitors[1] = k.Value.type;
                        drSpeciatedMonitors[2] = Math.Round(k.Value.lat, 6);
                        drSpeciatedMonitors[3] = Math.Round(k.Value.longitude, 6);
                        drSpeciatedMonitors[4] = k.Value.monitorGridcell;
                        drSpeciatedMonitors[5] = kin.Key;
                        drSpeciatedMonitors[6] = Math.Round(kin.Value.crustal, 8);
                        drSpeciatedMonitors[7] = Math.Round(kin.Value.ec, 8);
                        drSpeciatedMonitors[8] = Math.Round(kin.Value.ocb, 8);
                        drSpeciatedMonitors[9] = Math.Round(kin.Value.so4, 8);
                        drSpeciatedMonitors[10] = Math.Round(kin.Value.no3, 8);
                        drSpeciatedMonitors[11] = Math.Round(kin.Value.no3r, 8);
                        drSpeciatedMonitors[12] = Math.Round(kin.Value.salt, 8);
                        dtSpeciatedMonitors.Rows.Add(drSpeciatedMonitors);
                        if (!Double.IsNaN(kin.Value.don))
                        {
                            drNH4_DON = dtNH4_DON.NewRow();
                            drNH4_DON[0] = k.Key;
                            drNH4_DON[1] = k.Value.type;
                            drNH4_DON[2] = Math.Round(k.Value.lat, 6);
                            drNH4_DON[3] = Math.Round(k.Value.longitude, 6);
                            drNH4_DON[4] = k.Value.monitorGridcell;
                            drNH4_DON[5] = kin.Key;
                            drNH4_DON[6] = Math.Round(kin.Value.nh4, 8);
                            drNH4_DON[7] = Math.Round(kin.Value.don, 8);
                            dtNH4_DON.Rows.Add(drNH4_DON);
                        }
                    }
                }
                if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doAutomaticallyExtract)
                {
                    if (!CommonClass.IsBatch)
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    else
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    if (!Directory.Exists(_resultFilePath))
                        System.IO.Directory.CreateDirectory(_resultFilePath);
                }
                string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Quarterly Peak Speciated Monitors.csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtSpeciatedMonitors, _resultFilePath + @"\" + strFile, "Quarter");
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                dtNH4_DON.Dispose();
                GC.Collect();

                strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Quarterly Peak NH4_DON Monitors.csv";
                baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtNH4_DON, _resultFilePath + @"\" + strFile, "Quarter");
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                dtSpeciatedMonitors.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }

        }
        #endregion

        #region save daily all years all days pm25 point
        public static bool SaveDailyFiles(BaseScenario baseScenario, Dictionary<string, Monitors> dicDailyPM, string period)
        {
            try
            {
                DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = baseScenario.configuration as DailyPMAnalysisConfiguration;
                #region daily all years all days pm25 point
                DataTable dt = new DataTable();
                dt.Columns.Add("_id");
                dt.Columns.Add("_type");
                dt.Columns.Add("_state_name");
                dt.Columns.Add("_county_name");
                dt.Columns.Add("monitor_lat");
                dt.Columns.Add("monitor_long");
                dt.Columns.Add("monitor_gridcell");
                dt.Columns.Add("day");
                dt.Columns.Add("year");
                dt.Columns.Add("quarter");
                dt.Columns.Add("b_pm25_d_conc");
                dt.Columns.Add("f_pm25_d_conc");
                dt.Columns.Add("b_blank_mass");
                dt.Columns.Add("b_crustal_mass");
                dt.Columns.Add("b_EC_mass");
                dt.Columns.Add("b_NH4_mass");
                dt.Columns.Add("b_Ocmb_mass");
                dt.Columns.Add("b_SO4_mass");
                dt.Columns.Add("b_NO3_mass");
                dt.Columns.Add("b_water_mass");
                dt.Columns.Add("b_salt_mass");
                dt.Columns.Add("f_blank_mass");
                dt.Columns.Add("f_crustal_mass");
                dt.Columns.Add("f_EC_mass");
                dt.Columns.Add("f_NH4_mass");
                dt.Columns.Add("f_Ocmb_mass");
                dt.Columns.Add("f_SO4_mass");
                dt.Columns.Add("f_NO3_mass");
                dt.Columns.Add("f_water_mass");
                dt.Columns.Add("f_salt_mass");
                dt.Columns.Add("rrf_crustal_q");
                dt.Columns.Add("rrf_ec_q");
                dt.Columns.Add("rrf_nh4_q");
                dt.Columns.Add("rrf_oc_q");
                dt.Columns.Add("rrf_so4_q");
                dt.Columns.Add("rrf_no3_q");
                dt.Columns.Add("rrf_water_q");
                dt.Columns.Add("rrf_salt_q");
                #endregion
                #region daily all years high days pm25 point
                //对于得到的所有年份的所有天数的值之后，分别对baseline pm和future pm降序排列，再根据rank98确定baseline和future pm25，
                //注意baseline和future pm25的日期是有可能不一样的。再获取相应的baseline/future species values
                //DataTable dtHighDays = new DataTable();
                //dtHighDays.Columns.Add("_id");
                //dtHighDays.Columns.Add("_type");
                //dtHighDays.Columns.Add("_state_name");
                //dtHighDays.Columns.Add("_county_name");
                //dtHighDays.Columns.Add("monitor_lat");
                //dtHighDays.Columns.Add("monitor_long");
                //dtHighDays.Columns.Add("monitor_gridcell");
                //dtHighDays.Columns.Add("98th_percent_rank");
                //dtHighDays.Columns.Add("year");
                //dtHighDays.Columns.Add("date_b");
                //dtHighDays.Columns.Add("b_high_quarter");
                //dtHighDays.Columns.Add("b_pm25_d_conc");
                //dtHighDays.Columns.Add("date_f");
                //dtHighDays.Columns.Add("f_high_quarter");
                //dtHighDays.Columns.Add("f_pm25_d_conc");
                //dtHighDays.Columns.Add("f_blank_mass");
                //dtHighDays.Columns.Add("f_crustal_mass");
                //dtHighDays.Columns.Add("f_EC_mass");
                //dtHighDays.Columns.Add("f_NH4_mass");
                //dtHighDays.Columns.Add("f_Ocmb_mass");
                //dtHighDays.Columns.Add("f_SO4_mass");
                //dtHighDays.Columns.Add("f_NO3_mass");
                //dtHighDays.Columns.Add("f_water_mass");
                //dtHighDays.Columns.Add("f_salt_mass");
                //dtHighDays.Columns.Add("rrf_crustal_q");
                //dtHighDays.Columns.Add("rrf_ec_q");
                //dtHighDays.Columns.Add("rrf_nh4_q");
                //dtHighDays.Columns.Add("rrf_oc_q");
                //dtHighDays.Columns.Add("rrf_so4_q");
                //dtHighDays.Columns.Add("rrf_no3_q");
                //dtHighDays.Columns.Add("rrf_water_q");
                //dtHighDays.Columns.Add("rrf_salt_q");
                #endregion
                DataRow dr = null;
                //int iQuarterCount = dailyPMAnalysisConfiguration.speciesFractionOptionsD.unofficialMinQuartersPoint;
                foreach (KeyValuePair<string, Monitors> k in dicDailyPM)
                {
                    if (k.Value.dicPMDaily == null || k.Value.dicPMDaily.Count == 0) continue;
                    foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> kYear in k.Value.dicPMDaily)
                    {
                        #region all years high days
                        //if (k.Value.dicOfficialPM25Daily[kYear.Key].ContainsKey("4"))
                        //{
                        //    dr = dtHighDays.NewRow();
                        //    dr[0] = k.Value.id;
                        //    dr[1] = k.Value.type;
                        //    dr[2] = k.Value.stateName;
                        //    dr[3] = k.Value.countyName;
                        //    dr[4] = Math.Round(k.Value.lat, 6);
                        //    dr[5] = Math.Round(k.Value.longitude, 6);
                        //    dr[6] = k.Value.monitorGridcell;
                        //    dr[7] = kYear.Key.Substring(kYear.Key.IndexOf(',') + 1);
                        //    dr[8] = kYear.Key.Substring(0, kYear.Key.IndexOf(','));
                        //    var query = kYear.Value.OrderByDescending(q => q.Value.bPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1))).Last();
                        //    //int rank = Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1));
                        //    ////float pm=kYear.Value.OrderByDescending(q => q.Value.bPM25).Take(rank).Last().Value.bPM25;
                        //    //var query = kYear.Value.OrderByDescending(p => p.Value.bPM25).Where(p => p.Value.bPM25 >= kYear.Value.OrderByDescending(q => q.Value.bPM25).Take(rank).Last().Value.bPM25).Last();
                        //    ////var query=kYear.Value.OrderByDescending(p => p.Value.bPM25).Where(p=>p.Value.bPM25>=pm).ToList();
                        //    //int iCountTotal = kYear.Value.OrderByDescending(p => p.Value.bPM25).Where(p => p.Value.bPM25 >= query.Value.bPM25).Count();
                        //    //int iCount = -1;
                        //    //if (iCountTotal > rank)
                        //    //{
                        //    //    dr[9] = query.Key;
                        //    //    //query = query.Last();
                        //    //}
                        //    //else
                        //    //{
                        //    //    iCount = kYear.Value.OrderByDescending(p => p.Value.bPM25).Where(p => p.Value.bPM25 == query.Value.bPM25).Count();
                        //    //    if (iCount > 1)
                        //    //    {
                        //    //        query = kYear.Value.OrderByDescending(p => p.Value.bPM25).Where(p => p.Value.bPM25 >= query.Value.bPM25).Take(iCountTotal - iCount + 1).Last();
                        //    //        dr[9] = query.Key;
                        //    //        //dr[9] = query.Take(query.Count() - query.Where(p => p.Value.bPM25 == pm).Count() + 1).Last().Key;
                        //    //    }
                        //    //    else
                        //    //    {
                        //    //        dr[9] = query.Key;
                        //    //    }
                        //    //}

                        //    dr[9] = query.Key;
                        //    switch (query.Key.Substring(4, 2))
                        //    {
                        //        case "01":
                        //        case "02":
                        //        case "03":
                        //            dr[10] = 1;
                        //            break;
                        //        case "04":
                        //        case "05":
                        //        case "06":
                        //            dr[10] = 2;
                        //            break;
                        //        case "07":
                        //        case "08":
                        //        case "09":
                        //            dr[10] = 3;
                        //            break;
                        //        case "10":
                        //        case "11":
                        //        case "12":
                        //            dr[10] = 4;
                        //            break;
                        //    }
                        //    dr[11] = Math.Round(query.Value.bPM25, 1);
                        //    query = kYear.Value.OrderByDescending(q => q.Value.fPM25).Take(Convert.ToInt32(kYear.Key.Substring(kYear.Key.IndexOf(',') + 1))).Last();
                        //    ////pm = kYear.Value.OrderByDescending(q => q.Value.fPM25).Take(rank).Last().Value.fPM25;
                        //    //query = kYear.Value.OrderByDescending(p => p.Value.fPM25).Where(p => p.Value.fPM25 >= kYear.Value.OrderByDescending(q => q.Value.fPM25).Take(rank).Last().Value.fPM25).Last();
                        //    ////query = kYear.Value.OrderByDescending(p => p.Value.fPM25).Where(p => p.Value.fPM25 >= pm).ToList();
                        //    ////query = kYear.Value.OrderByDescending(p => p.Value.fPM25).Take(rank).Last();
                        //    //iCountTotal = kYear.Value.OrderByDescending(p => p.Value.fPM25).Where(p => p.Value.fPM25 >= query.Value.fPM25).Count();
                        //    //if (iCountTotal > rank)
                        //    //{
                        //    //    dr[12] = query.Key;
                        //    //    //query = query.Last();
                        //    //}
                        //    //else
                        //    //{
                        //    //    iCount = kYear.Value.OrderByDescending(p => p.Value.fPM25).Where(p => p.Value.fPM25 == query.Value.fPM25).Count();
                        //    //    if (iCount > 1)
                        //    //    {
                        //    //        query = kYear.Value.OrderByDescending(p => p.Value.fPM25).Where(p => p.Value.fPM25 >= query.Value.fPM25).Take(iCountTotal - iCount + 1).Last();
                        //    //        dr[12] = query.Key;
                        //    //    }
                        //    //    else
                        //    //    {
                        //    //        dr[12] = query.Key;
                        //    //    }
                        //    //}
                        //    dr[12] = query.Key;
                        //    switch (query.Key.Substring(4, 2))
                        //    {
                        //        case "01":
                        //        case "02":
                        //        case "03":
                        //            dr[13] = 1;
                        //            break;
                        //        case "04":
                        //        case "05":
                        //        case "06":
                        //            dr[13] = 2;
                        //            break;
                        //        case "07":
                        //        case "08":
                        //        case "09":
                        //            dr[13] = 3;
                        //            break;
                        //        case "10":
                        //        case "11":
                        //        case "12":
                        //            dr[13] = 4;
                        //            break;
                        //    }
                        //    dr[14] = Math.Round(query.Value.fPM25, 4);
                        //    dr[15] = dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass;
                        //    dr[16] = Math.Round(query.Value.fCrustal, 7);
                        //    dr[17] = Math.Round(query.Value.fEC, 7);
                        //    dr[18] = Math.Round(query.Value.fNH4, 7);
                        //    dr[19] = Math.Round(query.Value.fOCMmb, 7);
                        //    dr[20] = Math.Round(query.Value.fSO4, 7);
                        //    dr[21] = Math.Round(query.Value.fNO3r, 7);
                        //    dr[22] = Math.Round(query.Value.fWater, 7);
                        //    dr[23] = Math.Round(query.Value.fSalt, 7);
                        //    dr[24] = Math.Round(query.Value.rrfCrustal, 4);
                        //    dr[25] = Math.Round(query.Value.rrfEC, 7);
                        //    dr[26] = Math.Round(query.Value.rrfNH4, 7);
                        //    dr[27] = Math.Round(query.Value.rrfOC, 7);
                        //    dr[28] = Math.Round(query.Value.rrfSO4, 7);
                        //    dr[29] = Math.Round(query.Value.rrfNO3, 7);
                        //    dr[30] = Math.Round(query.Value.rrfWater, 7);
                        //    dr[31] = Math.Round(query.Value.rrfSalt, 7);
                        //    dtHighDays.Rows.Add(dr);
                        //}
                        #endregion

                        foreach (KeyValuePair<string, PM25Monitors> kDay in kYear.Value.OrderByDescending(p => p.Value.fPM25))
                        {
                            dr = dt.NewRow();
                            dr[0] = k.Value.id;
                            dr[1] = k.Value.type;
                            dr[2] = k.Value.stateName;
                            dr[3] = k.Value.countyName;
                            dr[4] = Math.Round(k.Value.lat, 6);
                            dr[5] = Math.Round(k.Value.longitude, 6);
                            dr[6] = k.Value.monitorGridcell;
                            dr[7] = kDay.Key;
                            if (kYear.Key.Length > 4)
                                dr[8] = kYear.Key.Substring(0, kYear.Key.IndexOf(','));
                            else
                                dr[8] = kYear.Key;
                            switch (kDay.Key.Substring(4, 2))
                            {
                                case "01":
                                case "02":
                                case "03":
                                    dr[9] = 1;
                                    break;
                                case "04":
                                case "05":
                                case "06":
                                    dr[9] = 2;
                                    break;
                                case "07":
                                case "08":
                                case "09":
                                    dr[9] = 3;
                                    break;
                                case "10":
                                case "11":
                                case "12":
                                    dr[9] = 4;
                                    break;
                            }
                            dr[10] = Double.IsNaN(kDay.Value.bPM25) ? -9 : Math.Round(kDay.Value.bPM25, 8);
                            dr[11] = Double.IsNaN(kDay.Value.fPM25) ? -9 : Math.Round(kDay.Value.fPM25, 8);
                            dr[12] = Math.Round(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass, 8);
                            dr[13] = Double.IsNaN(kDay.Value.bCrustal) ? -9 : Math.Round(kDay.Value.bCrustal, 8);
                            dr[14] = Double.IsNaN(kDay.Value.bEC) ? -9 : Math.Round(kDay.Value.bEC, 8);
                            dr[15] = Double.IsNaN(kDay.Value.bNH4) ? -9 : Math.Round(kDay.Value.bNH4, 8);
                            dr[16] = Double.IsNaN(kDay.Value.bOCMmb) ? -9 : Math.Round(kDay.Value.bOCMmb, 8);
                            dr[17] = Double.IsNaN(kDay.Value.bSO4) ? -9 : Math.Round(kDay.Value.bSO4, 8);
                            dr[18] = Double.IsNaN(kDay.Value.bNO3r) ? -9 : Math.Round(kDay.Value.bNO3r, 8);
                            dr[19] = Double.IsNaN(kDay.Value.bWater) ? -9 : Math.Round(kDay.Value.bWater, 8);
                            dr[20] = Double.IsNaN(kDay.Value.bSalt) ? -9 : Math.Round(kDay.Value.bSalt, 8);
                            dr[21] = Math.Round(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass, 8);
                            dr[22] = Double.IsNaN(kDay.Value.fCrustal) ? -9 : Math.Round(kDay.Value.fCrustal, 8);
                            dr[23] = Double.IsNaN(kDay.Value.fEC) ? -9 : Math.Round(kDay.Value.fEC, 8);
                            dr[24] = Double.IsNaN(kDay.Value.fNH4) ? -9 : Math.Round(kDay.Value.fNH4, 8);
                            dr[25] = Double.IsNaN(kDay.Value.fOCMmb) ? -9 : Math.Round(kDay.Value.fOCMmb, 8);
                            dr[26] = Double.IsNaN(kDay.Value.fSO4) ? -9 : Math.Round(kDay.Value.fSO4, 8);
                            dr[27] = Double.IsNaN(kDay.Value.fNO3r) ? -9 : Math.Round(kDay.Value.fNO3r, 8);
                            dr[28] = Double.IsNaN(kDay.Value.fWater) ? -9 : Math.Round(kDay.Value.fWater, 8);
                            dr[29] = Double.IsNaN(kDay.Value.fSalt) ? -9 : Math.Round(kDay.Value.fSalt, 8);
                            dr[30] = Double.IsNaN(kDay.Value.rrfCrustal) ? -9 : Math.Round(kDay.Value.rrfCrustal, 8);
                            dr[31] = Double.IsNaN(kDay.Value.rrfEC) ? -9 : Math.Round(kDay.Value.rrfEC, 8);
                            dr[32] = Double.IsNaN(kDay.Value.rrfNH4) ? -9 : Math.Round(kDay.Value.rrfNH4, 8);
                            dr[33] = Double.IsNaN(kDay.Value.rrfOC) ? -9 : Math.Round(kDay.Value.rrfOC, 8);
                            dr[34] = Double.IsNaN(kDay.Value.rrfSO4) ? -9 : Math.Round(kDay.Value.rrfSO4, 8);
                            dr[35] = Double.IsNaN(kDay.Value.rrfNO3) ? -9 : Math.Round(kDay.Value.rrfNO3, 8);
                            dr[36] = Double.IsNaN(kDay.Value.rrfWater) ? -9 : Math.Round(kDay.Value.rrfWater, 8);
                            dr[37] = Double.IsNaN(kDay.Value.rrfSalt) ? -9 : Math.Round(kDay.Value.rrfSalt, 8);
                            dt.Rows.Add(dr);
                        }
                    }
                }

                if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doAutomaticallyExtract)
                {
                    if (!CommonClass.IsBatch)
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    else
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    if (!Directory.Exists(_resultFilePath))
                        System.IO.Directory.CreateDirectory(_resultFilePath);
                }
                string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Daily All Years All Days PM25 Point" + period + ".csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Quarter");
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                dt.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        #endregion

        public static bool SaveAllYearHighDays(BaseScenario baseScenario, Dictionary<string, Monitors> dicHighDays, string period)
        {
            try
            {
                DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = baseScenario.configuration as DailyPMAnalysisConfiguration;
                #region
                DataTable dtHighDays = new DataTable();
                dtHighDays.Columns.Add("_id");
                dtHighDays.Columns.Add("_type");
                dtHighDays.Columns.Add("_state_name");
                dtHighDays.Columns.Add("_county_name");
                dtHighDays.Columns.Add("monitor_lat");
                dtHighDays.Columns.Add("monitor_long");
                dtHighDays.Columns.Add("monitor_gridcell");
                dtHighDays.Columns.Add("98th_percent_rank");
                dtHighDays.Columns.Add("year");
                dtHighDays.Columns.Add("date_b");
                dtHighDays.Columns.Add("b_high_quarter");
                dtHighDays.Columns.Add("b_pm25_d_conc");
                dtHighDays.Columns.Add("date_f");
                dtHighDays.Columns.Add("f_high_quarter");
                dtHighDays.Columns.Add("f_pm25_d_conc");
                dtHighDays.Columns.Add("f_blank_mass");
                dtHighDays.Columns.Add("f_crustal_mass");
                dtHighDays.Columns.Add("f_EC_mass");
                dtHighDays.Columns.Add("f_NH4_mass");
                dtHighDays.Columns.Add("f_Ocmb_mass");
                dtHighDays.Columns.Add("f_SO4_mass");
                dtHighDays.Columns.Add("f_NO3_mass");
                dtHighDays.Columns.Add("f_water_mass");
                dtHighDays.Columns.Add("f_salt_mass");
                dtHighDays.Columns.Add("rrf_crustal_q");
                dtHighDays.Columns.Add("rrf_ec_q");
                dtHighDays.Columns.Add("rrf_nh4_q");
                dtHighDays.Columns.Add("rrf_oc_q");
                dtHighDays.Columns.Add("rrf_so4_q");
                dtHighDays.Columns.Add("rrf_no3_q");
                dtHighDays.Columns.Add("rrf_water_q");
                dtHighDays.Columns.Add("rrf_salt_q");
                #endregion
                DataRow dr = null;
                foreach (KeyValuePair<string, Monitors> k in dicHighDays)
                {
                    foreach (KeyValuePair<string, AllYearHighDays> kYear in k.Value.dicHighDays)
                    {
                        dr = dtHighDays.NewRow();
                        dr[0] = k.Key;
                        dr[1] = k.Value.type;
                        dr[2] = k.Value.stateName;
                        dr[3] = k.Value.countyName;
                        dr[4] = k.Value.lat;
                        dr[5] = k.Value.longitude;
                        dr[6] = k.Value.monitorGridcell;
                        dr[7] = kYear.Value.rank98;
                        dr[8] = kYear.Key;
                        dr[9] = kYear.Value.date_b;
                        dr[10] = kYear.Value.highQuarter_b;
                        dr[11] = CommonClass.ToFixed(kYear.Value.bPMdqCONC, CommonClass.Pm_daily_base_output_precision);
                        dr[12] = kYear.Value.date_f;
                        dr[13] = kYear.Value.highQuarter_f;
                        dr[14] = CommonClass.ToFixed(kYear.Value.fPMdqCONC, CommonClass.Pm_daily_future_output_precision);
                        dr[15] = Math.Round(dailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass, 8);
                        dr[16] = Math.Round(kYear.Value.fCrustalMassq, 8);
                        dr[17] = Math.Round(kYear.Value.fECMassq, 8);
                        dr[18] = Math.Round(kYear.Value.fNH4Massq, 8);
                        dr[19] = Math.Round(kYear.Value.fOcmbMassq, 8);
                        dr[20] = Math.Round(kYear.Value.fSO4Massq, 8);
                        dr[21] = Math.Round(kYear.Value.fNO3Massq, 8);
                        dr[22] = Math.Round(kYear.Value.fWaterMassq, 8);
                        dr[23] = Math.Round(kYear.Value.fSaltMassq, 8);
                        dr[24] = Math.Round(kYear.Value.rrfCrustalq, 8);
                        dr[25] = Math.Round(kYear.Value.rrfECq, 8);
                        dr[26] = Math.Round(kYear.Value.rrfNH4q, 8);
                        dr[27] = Math.Round(kYear.Value.rrfOCq, 8);
                        dr[28] = Math.Round(kYear.Value.rrfSO4q, 8);
                        dr[29] =kYear.Value.rrfNO3q==double.NaN?-9: Math.Round(kYear.Value.rrfNO3q, 8);
                        dr[30] = Math.Round(kYear.Value.rrfWaterq, 8);
                        dr[31] = Math.Round(kYear.Value.rrfSaltq, 8);
                        dtHighDays.Rows.Add(dr);
                    }
                }
                string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Daily All Years High Days PM25 Point" + period + ".csv";
                BaseOutput baseOutput = new BaseOutput();
                CommonClass.SaveCSV(dtHighDays, _resultFilePath + @"\" + strFile, "Year");
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                dtHighDays.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        #region save neighbor file point
        public static bool SaveNeighborFilePoint(BaseScenario baseScenario, Dictionary<string, Monitors> dicNeighborFilePoint, string period)
        {
            try
            {
                DailyPMAnalysisConfiguration dailyPMAnalysisConfiguration = baseScenario.configuration as DailyPMAnalysisConfiguration;
                if (dailyPMAnalysisConfiguration.chooseDesiredOutputD.doAutomaticallyExtract)
                {
                    if (!CommonClass.IsBatch)
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    else
                    {
                        if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName)
                            _resultFilePath = CommonClass.ResultFilePath + @"\" + dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName;
                    }
                    if (!Directory.Exists(_resultFilePath))
                        System.IO.Directory.CreateDirectory(_resultFilePath);
                }
                string strFile = dailyPMAnalysisConfiguration.chooseDesiredOutputD.scenarioName + " Neighbor File Point" + period + ".csv";
                FileStream fs = new FileStream(_resultFilePath + @"\" + strFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                StreamWriter sw = new StreamWriter(fs, Encoding.Default);
                sw.WriteLine("Quarter");
                string data = "";
                data += "_id";
                data += ",";
                data += "_state_name";
                data += ",";
                data += "_county_name";
                data += ",";
                data += "monitor_lat";
                data += ",";
                data += "monitor_long";
                data += ",";
                data += "monitor_gridcell";
                data += ",";
                data += "quarter";
                data += ",";
                data += "neighbor";
                data += ",";
                data += "neighbor_gridcell";
                data += ",";
                data += "distance";
                data += ",";
                data += "weightdistance";
                data += ",";
                data += "weightdistancesquared";
                data += ",";
                data += "pollutant";
                sw.WriteLine(data);
                double distanceSum = 0, distanceSquaredSum = 0;
                foreach (KeyValuePair<string, Monitors> k in dicNeighborFilePoint)
                {
                    if (k.Key.Replace("\"", "") == "40038001" || k.Key.Replace("\"", "") == "040038001")
                    {
                    }
                    foreach (KeyValuePair<string, Dictionary<string, NeighborInfoDaily>> kQ in k.Value.dicNeighborInfo)
                    {
                        distanceSum = distanceSquaredSum = 0;
                        distanceSum = kQ.Value.Select(p => p.Value.distance == 0 ? 0 : 1.0000 / p.Value.distance).Sum();
                        distanceSquaredSum = kQ.Value.Select(p => p.Value.distance == 0 ? 0 : 1.0000 / Math.Pow(p.Value.distance, 2)).Sum();
                        foreach (KeyValuePair<string, NeighborInfoDaily> kNeighbor in kQ.Value)
                        {
                            foreach (string sPollutant in kNeighbor.Value.lstPollutants)
                            {
                                data = "";
                                data += k.Value.id;
                                data += ",";
                                data += k.Value.stateName;
                                data += ",";
                                data += k.Value.countyName;
                                data += ",";
                                data += k.Value.lat;
                                data += ",";
                                data += k.Value.longitude;
                                data += ",";
                                data += k.Value.monitorGridcell;
                                data += ",";
                                data += kQ.Key;
                                data += ",";
                                data += kNeighbor.Key.Substring(0, kNeighbor.Key.IndexOf(","));
                                data += ",";
                                data += kNeighbor.Key.Substring(kNeighbor.Key.IndexOf(",") + 1);
                                data += ",";
                                data += Math.Round(kNeighbor.Value.distance, 8);
                                data += ",";
                                data += distanceSum == 0 || kNeighbor.Value.distance == 0 ? 1 : Math.Round(1.0000 / kNeighbor.Value.distance / distanceSum, 8);
                                data += ",";
                                data += distanceSquaredSum == 0 || kNeighbor.Value.distance == 0 ? 1 : Math.Round(1.0000 / Math.Pow(kNeighbor.Value.distance, 2) / distanceSquaredSum, 8);
                                data += ",";
                                data += sPollutant;
                                sw.WriteLine(data);
                            }
                        }
                    }
                }
                sw.Close();
                fs.Close();
                GC.Collect();

                BaseOutput baseOutput = new BaseOutput();
                baseOutput.outputName = strFile.Replace(".csv", "");
                baseOutput.outputType = "Monitor Network";
                baseOutput.outputFilePath = _resultFilePath + @"\" + strFile;
                if (File.Exists(_resultFilePath + @"\" + strFile))
                {
                    FileInfo fileInfo = new FileInfo(_resultFilePath + @"\" + strFile);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                CommonClass.CurrentBaseScenario.lstOutput.Add(baseOutput);
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        #endregion
        #endregion
    }
}
