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 SSIADailyPMCommonClass
    {
        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 DailyAnalysis(BaseScenario baseScenario, SMAT_CE mats)
        {
            if (!(baseScenario.configuration is SSIADailyPMAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                Dictionary<string, Dictionary<int,ModelDataSpecies>> dicMaxDeltaGrid = new Dictionary<string,Dictionary<int,ModelDataSpecies>>();
                Dictionary<string, Dictionary<int, ModelDataSpecies>> dicMaxDeltaDispersion = new Dictionary<string, Dictionary<int,ModelDataSpecies>>();
                _beginTime = DateTime.Now;
                SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration = (baseScenario.configuration) as SSIADailyPMAnalysisConfiguration;
                Dictionary<string, DailyModelMonitor> dicGridModel = new Dictionary<string, DailyModelMonitor>();                      
                Dictionary<string, DailyModelMonitor> dicDispersionModel = new Dictionary<string, DailyModelMonitor>();

                Dictionary<string, double> dicDistance = new Dictionary<string, double>();
                string baseYear = "", futureYear = "";
                bool isSalt = false;
                //-----保存文件前先生成相应的文件夹---------------
                #region 生成相应的文件夹
                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);
                #endregion

                #region quarterly peak model data
                //---quarterly
                string isOK = "";
                CommonClass.CurrentBaseScenario.dicLatLongLambert = new Dictionary<string, string>();
                CommonClass.CurrentBaseScenario.dicLambertLatLong = new Dictionary<string, string>();

                if (!SSIAdailyPMAnalysisConfiguration.analysisOptionD.useDispersionOnly)
                {
                    CommonClass.CurrentLog = "Read model data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.modelInputD.baselineModelDataFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    if (SSIAdailyPMAnalysisConfiguration.modelInputD.QuarterlyModelDataInput)
                    { 
                        #region read quarterly baseline/future model data from csv
                        baseYear = ""; futureYear = "";
                        isOK = GetModelDataQuarterly(SSIAdailyPMAnalysisConfiguration, ref dicGridModel, ref isSalt, ref baseYear, ref futureYear);
                        switch (isOK)//error message when loading file
                        {
                            case "wrongBaseline":
                                CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.modelInputD.baselineModelDataFile) + "\".";
                                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                                return false;
                            case "wrongFuture":
                                CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.modelInputD.alternativeScenarioFile) + "\".";
                                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;
                        }
                        #endregion
                    }                    
                    else if (SSIAdailyPMAnalysisConfiguration.modelInputD.DailyModelDataInput)
                    {
                        #region read daily baseline/future model data from csv
                        baseYear = ""; futureYear = "";
                        //------------读取文件----------baseline/forecast model data 
                        Dictionary<string, List<string>> dicBaseDays = new Dictionary<string, List<string>>();//记录date
                        isOK = GetModelDataDailyBaseline(SSIAdailyPMAnalysisConfiguration, ref dicGridModel, ref isSalt, ref baseYear, ref dicBaseDays);
                        if (!string.IsNullOrEmpty(isOK))//error message when loading file
                        {
                            CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.modelInputD.baselineModelDataFile) + "\".";
                            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(SSIAdailyPMAnalysisConfiguration.modelInputD.alternativeScenarioFile) + "\".";
                        CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);
                        
                        isOK = GetModelDataDailyFuture(SSIAdailyPMAnalysisConfiguration, ref dicGridModel, ref isSalt, ref futureYear, dicBaseDays,ref dicMaxDeltaGrid);
                        if (!string.IsNullOrEmpty(isOK))//error message when loading file
                        {
                            CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.modelInputD.alternativeScenarioFile) + "\".";
                            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);

                        dicBaseDays.Clear();
                        GC.Collect();
                        #endregion
                    }

                    #region //change project - write in dictionary (lat,long to lambert) - for draw map
                    double[] dConvertArray = null;
                    List<double> lstConvertArray = new List<double>();
                    List<string> lstKey = dicGridModel.Keys.ToList();
                    for (int iLstKey = 0; iLstKey < dicGridModel.Keys.Count; iLstKey++)
                    {
                        lstConvertArray.Add(dicGridModel[lstKey[iLstKey]].longitude);
                        lstConvertArray.Add(dicGridModel[lstKey[iLstKey]].lat);
                    }
                    dConvertArray = lstConvertArray.ToArray();
                    DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArray, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984, DotSpatial.Projections.ProjectionInfo.FromProj4String(CommonClass.projUSACMAQ), 0, dConvertArray.Length / 2);
                    for (int iLstKey = 0; iLstKey < dicGridModel.Keys.Count; iLstKey++)
                    {
                        dicGridModel[lstKey[iLstKey]].longitudeLamber = dConvertArray[2 * iLstKey] / 100.0;
                        dicGridModel[lstKey[iLstKey]].latitudeLamber = dConvertArray[2 * iLstKey + 1] / 100.0;
                        string data = dConvertArray[2 * iLstKey] + "," + dConvertArray[2 * iLstKey + 1];
                        //if (annualPMSSIAAnalysisConfiguration.analysisOptionA.useGridOnly)
                        if (!CommonClass.CurrentBaseScenario.dicLatLongLambert.ContainsKey(dicGridModel[lstKey[iLstKey]].lat + "," + dicGridModel[lstKey[iLstKey]].longitude))
                        {
                            CommonClass.CurrentBaseScenario.dicLatLongLambert.Add(dicGridModel[lstKey[iLstKey]].lat + "," + dicGridModel[lstKey[iLstKey]].longitude, data);
                            if (!CommonClass.CurrentBaseScenario.dicLambertLatLong.ContainsKey(data))
                            {
                                CommonClass.CurrentBaseScenario.dicLambertLatLong.Add(data, dicGridModel[lstKey[iLstKey]].id + "," + dicGridModel[lstKey[iLstKey]].lat + "," + dicGridModel[lstKey[iLstKey]].longitude);
                            }
                        }
                    }
                    #endregion

                    //SaveSSIADailyPMData(baseScenario, dicGridModel, null);
                    //SaveSSIAQuarterlyPMData(baseScenario, dicGridModel, null);
                }
                if (!SSIAdailyPMAnalysisConfiguration.analysisOptionD.useGridOnly)
                {
                    #region read dispersion
                    _beginTime = DateTime.Now;
                    CommonClass.CurrentLog = "Read model data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.modelInputD.dispersionFile) + "\".";
                    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                    isOK = GetDispersionModelData(SSIAdailyPMAnalysisConfiguration, ref dicDispersionModel, dicGridModel, ref dicMaxDeltaDispersion);
                    if (!string.IsNullOrEmpty(isOK))//error message when loading file
                    {
                        CommonClass.CurrentLog = "Fail to read model data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.modelInputD.dispersionFile) + "\".";
                        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);
                    #endregion

                    #region change projection and Save Data File
                    //change proj to wgs1984 from utm
                    double[] dConvertArray = null;
                    List<double> lstConvertArray = new List<double>();
                    List<string> lstKey = dicDispersionModel.Keys.ToList();
                    for (int iLstKey = 0; iLstKey < dicDispersionModel.Keys.Count; iLstKey++)
                    {
                        lstConvertArray.Add(dicDispersionModel[lstKey[iLstKey]].longitudeUTM * 100.0 + 738547);
                        lstConvertArray.Add(dicDispersionModel[lstKey[iLstKey]].latitudeUTM * 100.0 + 3724842);
                    }
                    dConvertArray = lstConvertArray.ToArray();
                    DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArray, null, DotSpatial.Projections.ProjectionInfo.FromProj4String(CommonClass.projUSAAERMOD), DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984, 0, dConvertArray.Length / 2);
                    
                    if (SSIAdailyPMAnalysisConfiguration.analysisOptionD.useDispersionOnly)
                    {
                        CommonClass.CurrentBaseScenario.dicLatLongLambert = new Dictionary<string, string>();
                        CommonClass.CurrentBaseScenario.dicLambertLatLong = new Dictionary<string, string>();
                        for (int iLstKey = 0; iLstKey < dicDispersionModel.Keys.Count; iLstKey++)
                        {
                            dicDispersionModel[lstKey[iLstKey]].longitude = Math.Round(dConvertArray[2 * iLstKey], 6);
                            dicDispersionModel[lstKey[iLstKey]].lat = Math.Round(dConvertArray[2 * iLstKey + 1], 6);
                            string data = (dicDispersionModel[lstKey[iLstKey]].longitudeUTM * 100.0 + 738547) + "," + (dicDispersionModel[lstKey[iLstKey]].latitudeUTM * 100.0 + 3724842);
                            if (!CommonClass.CurrentBaseScenario.dicLatLongLambert.ContainsKey("utm," + dicDispersionModel[lstKey[iLstKey]].lat + "," + dicDispersionModel[lstKey[iLstKey]].longitude))
                            {
                                CommonClass.CurrentBaseScenario.dicLatLongLambert.Add("utm," + dicDispersionModel[lstKey[iLstKey]].lat + "," + dicDispersionModel[lstKey[iLstKey]].longitude, data);
                                if (!CommonClass.CurrentBaseScenario.dicLambertLatLong.ContainsKey(data))
                                {
                                    CommonClass.CurrentBaseScenario.dicLambertLatLong.Add(data, dicDispersionModel[lstKey[iLstKey]].id + "," + dicDispersionModel[lstKey[iLstKey]].lat + "," + dicDispersionModel[lstKey[iLstKey]].longitude);
                                }
                            }
                        }
                        //SaveSSIAQuarterlyPMData(baseScenario, null, dicDispersionModel);
                        //SaveSSIADailyPMData(baseScenario, null, dicDispersionModel);
                    }
                    else
                    {
                        for (int iLstKey = 0; iLstKey < dicDispersionModel.Keys.Count; iLstKey++)
                        {
                            dicDispersionModel[lstKey[iLstKey]].longitude = Math.Round(dConvertArray[2 * iLstKey], 6);
                            dicDispersionModel[lstKey[iLstKey]].lat = Math.Round(dConvertArray[2 * iLstKey + 1], 6);
                            string data = (dicDispersionModel[lstKey[iLstKey]].longitudeUTM * 100.0 + 738547) + "," + (dicDispersionModel[lstKey[iLstKey]].latitudeUTM * 100.0 + 3724842);
                            if (!CommonClass.CurrentBaseScenario.dicLatLongLambert.ContainsKey("utm," + dicDispersionModel[lstKey[iLstKey]].lat + "," + dicDispersionModel[lstKey[iLstKey]].longitude))
                            {
                                CommonClass.CurrentBaseScenario.dicLatLongLambert.Add("utm," + dicDispersionModel[lstKey[iLstKey]].lat + "," + dicDispersionModel[lstKey[iLstKey]].longitude, data);
                                if (!CommonClass.CurrentBaseScenario.dicLambertLatLong.ContainsKey(data))
                                {
                                    CommonClass.CurrentBaseScenario.dicLambertLatLong.Add(data, dicDispersionModel[lstKey[iLstKey]].id + "," + dicDispersionModel[lstKey[iLstKey]].lat + "," + dicDispersionModel[lstKey[iLstKey]].longitude);
                                }
                            }
                        }

                        //change proj to lcc from wgs1984
                        DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArray, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984, DotSpatial.Projections.ProjectionInfo.FromProj4String(CommonClass.projUSACMAQ), 0, dConvertArray.Length / 2);
                        for (int iLstKey = 0; iLstKey < dicDispersionModel.Keys.Count; iLstKey++)
                        {
                            dicDispersionModel[lstKey[iLstKey]].longitudeLamber = dConvertArray[2 * iLstKey] / 100.0;
                            dicDispersionModel[lstKey[iLstKey]].latitudeLamber = dConvertArray[2 * iLstKey + 1] / 100.0;
                            string data = dConvertArray[2 * iLstKey] + "," + dConvertArray[2 * iLstKey + 1];
                            if (!CommonClass.CurrentBaseScenario.dicLatLongLambert.ContainsKey(dicDispersionModel[lstKey[iLstKey]].lat + "," + dicDispersionModel[lstKey[iLstKey]].longitude))
                            {
                                CommonClass.CurrentBaseScenario.dicLatLongLambert.Add(dicDispersionModel[lstKey[iLstKey]].lat + "," + dicDispersionModel[lstKey[iLstKey]].longitude, "d," + data);
                                if (!CommonClass.CurrentBaseScenario.dicLambertLatLong.ContainsKey(data))
                                {
                                    CommonClass.CurrentBaseScenario.dicLambertLatLong.Add(data, dicDispersionModel[lstKey[iLstKey]].id + "," + dicDispersionModel[lstKey[iLstKey]].lat + "," + dicDispersionModel[lstKey[iLstKey]].longitude);
                                }
                            }
                        }

                        #region //aremod point in cmaq grid
                        double dLon = 0, dLat = 0;
                        int iFirst = Convert.ToInt32(dicGridModel.First().Key);
                        if (dicGridModel.ContainsKey((((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()))
                        {
                            dLon = Math.Abs(dicGridModel[(((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()].longitudeLamber -
                                dicGridModel.First().Value.longitudeLamber);
                            dLon = dLon / 2;
                            dLat = Math.Abs(dicGridModel[(((iFirst / 1000)) * 1000 + iFirst % 1000 + 1).ToString()].latitudeLamber -
                                dicGridModel.First().Value.latitudeLamber);
                            dLat = dLat / 2;
                        }
                        foreach (var k in dicDispersionModel)
                        {
                            try
                            {
                                double latitudeLamber = k.Value.latitudeLamber;//dicWGS1989toLCC[k.Key][1];
                                double longitudeLamber = k.Value.longitudeLamber;//dicWGS1989toLCC[k.Key][0];
                                var query = dicGridModel.Where(p => Math.Abs(p.Value.longitudeLamber - longitudeLamber) < dLon && Math.Abs(p.Value.latitudeLamber - latitudeLamber) < dLat).ToList();
                                string sModelIDTemp = "";
                                if (query.Count() > 0)
                                {
                                    DotSpatial.Topology.Coordinate coor = new DotSpatial.Topology.Coordinate(longitudeLamber, latitudeLamber);
                                    sModelIDTemp = query.OrderBy(p => Math.Pow(p.Value.longitudeLamber - longitudeLamber, 2) + Math.Pow(p.Value.latitudeLamber - latitudeLamber, 2)).First().Key;
                                    for (int i = 0; i < 5; i++)
                                    {
                                        k.Value.dicBaseSpecies[i.ToString()].pm25 = dicGridModel[sModelIDTemp].dicBaseSpecies[i.ToString()].pm25 + 0;
                                        k.Value.dicBaseSpecies[i.ToString()].pm25sec = dicGridModel[sModelIDTemp].dicBaseSpecies[i.ToString()].pm25sec + 0; 
                                        k.Value.dicBaseSpecies[i.ToString()].pm25prim = dicGridModel[sModelIDTemp].dicBaseSpecies[i.ToString()].pm25 - dicGridModel[sModelIDTemp].dicBaseSpecies[i.ToString()].pm25sec;
                                        k.Value.dicFutureSpecies[i.ToString()].pm25prim += k.Value.dicBaseSpecies[i.ToString()].pm25prim;
                                        k.Value.dicFutureSpecies[i.ToString()].pm25sec = dicGridModel[sModelIDTemp].dicFutureSpecies[i.ToString()].pm25sec;
                                        k.Value.dicFutureSpecies[i.ToString()].pm25 = k.Value.dicFutureSpecies[i.ToString()].pm25prim + k.Value.dicFutureSpecies[i.ToString()].pm25sec;
                                    }
                                 }
                            }
                            catch
                            { }
                        }  
                        #endregion

                        //SaveSSIADailyPMData(baseScenario, null, dicDispersionModel);
                        //SaveSSIAQuarterlyPMData(baseScenario, null, dicDispersionModel);
                        //SaveSSIADailyPMData(baseScenario, dicGridModel, dicDispersionModel);
                        //SaveSSIAQuarterlyPMData(baseScenario, dicGridModel, dicDispersionModel);
                    }
                    #endregion
                }

                #region Calculate cell center distance from source
                Dictionary<string, double[]> dicCells = new Dictionary<string, double[]>();
                if (!SSIAdailyPMAnalysisConfiguration.analysisOptionD.useGridOnly)
                {
                    foreach (var item in dicDispersionModel)
                    {
                        double[] v = new double[3] { item.Value.lat, item.Value.longitude, 0 };
                        dicCells.Add(item.Value.id, v);
                    }
                }
                if (!SSIAdailyPMAnalysisConfiguration.analysisOptionD.useDispersionOnly)
                {
                    foreach (var item in dicGridModel)
                    {
                        double[] v = new double[3] { item.Value.lat, item.Value.longitude, 0 };
                        dicCells.Add(item.Value.id, v);
                    }
                }              
              

                #region Read Source File
                Dictionary<string, double[]> dicSource = new Dictionary<string, double[]>();
                FileStream fs = new FileStream(SSIAdailyPMAnalysisConfiguration.modelInputD.SourceCoordinateFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (StreamReader csv = new StreamReader(fs, System.Text.Encoding.UTF8))
                {
                    string strLine = csv.ReadLine();//header
                    strLine = csv.ReadLine();
                    string[] strLineArray ;
                    while (strLine != null)
                    {
                        strLineArray = strLine.Split(new char[] { ',' });
                        double[] v = new double[2] { Convert.ToDouble(strLineArray[1]), Convert.ToDouble(strLineArray[2]) };
                        dicSource.Add(strLineArray[0], v);
                        strLine = csv.ReadLine();
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                #endregion

                #region Output Source Location file
                string filename = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA Source Location.csv";
                BaseOutput baseOutput = new BaseOutput();
                File.Copy(SSIAdailyPMAnalysisConfiguration.modelInputD.SourceCoordinateFile, _resultFilePath+"\\" + filename,true);
                baseOutput.outputName = filename.Replace(".csv", "");
                baseOutput.outputType = "Source Location";
                baseOutput.outputFilePath = _resultFilePath+"\\" + filename;
                if (File.Exists(baseOutput.outputFilePath))
                {
                    FileInfo fileInfo = new FileInfo(baseOutput.outputFilePath);
                    baseOutput.outputSize = Convert.ToInt32(fileInfo.Length / 1024);
                }
                else
                {
                    baseOutput.outputSize = 0;
                }
                baseScenario.lstOutput.Add(baseOutput);

                CalculateDistance(ref dicCells, dicSource);

                #endregion
                #endregion


                if (!SSIAdailyPMAnalysisConfiguration.analysisOptionD.useModelFRMData)
                {
                    if (SSIAdailyPMAnalysisConfiguration.analysisOptionD.useGridOnly)
                    {
                        SaveSSIADailyPMData(baseScenario, dicGridModel, null,dicMaxDeltaGrid,dicMaxDeltaDispersion,dicCells);
                        SaveSSIAQuarterlyPMData(baseScenario, dicGridModel, null, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                    }
                    else if (SSIAdailyPMAnalysisConfiguration.analysisOptionD.useDispersionOnly)
                    {
                        SaveSSIADailyPMData(baseScenario, null, dicDispersionModel, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                        SaveSSIAQuarterlyPMData(baseScenario, null, dicDispersionModel, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                    }
                    else
                    {
                        SaveSSIADailyPMData(baseScenario, dicGridModel, dicDispersionModel, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                        SaveSSIAQuarterlyPMData(baseScenario, dicGridModel, dicDispersionModel, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                    }

                    #region 调整lstoutput顺序
                    List<BaseOutput> lstNew2 = new List<BaseOutput>();
                    List<BaseOutput> bo2 = new List<BaseOutput>();
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Combined Daily PM Receptor")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Combined Daily PM Point")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Combined Quarterly PM Receptor")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Combined Quarterly PM Point")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Dispersion Daily PM Receptor")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Dispersion Daily PM Point")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Dispersion Quarterly PM Receptor")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Dispersion Quarterly PM Point")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Grid Daily PM Data")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Grid Daily PM Point")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Grid Quarterly PM Data")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Grid Quarterly PM Point")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    bo2 = baseScenario.lstOutput.Where(q => q.outputName.Replace(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName, "").Contains("SSIA Source Location")).ToList();
                    if (bo2.Count > 0) lstNew2.Add(bo2.First());
                    baseScenario.lstOutput = lstNew2;
                    #endregion
                    return true;
                }

                #endregion

                #region standard analysis

                #region step1: official FRM monitor data

                List<string> dicDesignValuePeriod = new List<string>();
                int startYearPM = Convert.ToInt32(SSIAdailyPMAnalysisConfiguration.monitorInputD.monitorDataStartYear);
                int endYearPM = Convert.ToInt32(SSIAdailyPMAnalysisConfiguration.monitorInputD.monitorDataEndYear);
                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, Dictionary<string, int>> dicComCodePeriod = new Dictionary<string, Dictionary<string, int>>();
                _beginTime = DateTime.Now;
                CommonClass.CurrentLog = "Read official PM data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.monitorInputD.officialMonitorDataFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                Dictionary<string, Monitors> dicMonitorsDaily = new Dictionary<string, Monitors>();
                isOK = GetOfficialPM(SSIAdailyPMAnalysisConfiguration, ref dicMonitorsDaily);
                if (dicMonitorsDaily.Count <= 0 || isOK == "unknow")//error message when loading file
                {
                    CommonClass.CurrentLog = "Fail to read official PM data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.monitorInputD.officialMonitorDataFile) + "\".";
                    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 official PM data: " + CommonClass.TotalTime + " s.";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

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

                #region get monitor in model
                                
                Dictionary<string, string> dicModelGridOfMonitors = new Dictionary<string, string>();

                if (SSIAdailyPMAnalysisConfiguration.analysisOptionD.useGridAndDispersion)
                {
                    double[] dConvertArraySpatial = null;
                    List<double> lstConvertArraySpatial = new List<double>();
                    List<string> lstKeySpatial = dicMonitorsDaily.Keys.ToList();
                    for (int iLstKey = 0; iLstKey < dicMonitorsDaily.Keys.Count; iLstKey++)
                    {
                        lstConvertArraySpatial.Add(dicMonitorsDaily[lstKeySpatial[iLstKey]].longitude);
                        lstConvertArraySpatial.Add(dicMonitorsDaily[lstKeySpatial[iLstKey]].lat);
                    }
                    dConvertArraySpatial = lstConvertArraySpatial.ToArray();
                    DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArraySpatial, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984,
       DotSpatial.Projections.ProjectionInfo.FromProj4String(CommonClass.projUSACMAQ), 0, dConvertArraySpatial.Length / 2);
                    for (int iLstKey = 0; iLstKey < dicMonitorsDaily.Keys.Count; iLstKey++)
                    {
                        dicMonitorsDaily[lstKeySpatial[iLstKey]].longitudeLamber = dConvertArraySpatial[2 * iLstKey] / 100.00;
                        dicMonitorsDaily[lstKeySpatial[iLstKey]].latitudeLamber = dConvertArraySpatial[2 * iLstKey + 1] / 100.00;
                    }
                    GetGridCellOfficialMonitor(ref dicModelGridOfMonitors, dicGridModel, dicDispersionModel, ref dicMonitorsDaily);
                }
                else if (SSIAdailyPMAnalysisConfiguration.analysisOptionD.useGridOnly)
                {
                    double[] dConvertArraySpatial = null;
                    List<double> lstConvertArraySpatial = new List<double>();
                    List<string> lstKeySpatial = dicMonitorsDaily.Keys.ToList();
                    for (int iLstKey = 0; iLstKey < dicMonitorsDaily.Keys.Count; iLstKey++)
                    {
                        lstConvertArraySpatial.Add(dicMonitorsDaily[lstKeySpatial[iLstKey]].longitude);
                        lstConvertArraySpatial.Add(dicMonitorsDaily[lstKeySpatial[iLstKey]].lat);
                    }
                    dConvertArraySpatial = lstConvertArraySpatial.ToArray();
                    DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArraySpatial, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984,
       DotSpatial.Projections.ProjectionInfo.FromProj4String(CommonClass.projUSACMAQ), 0, dConvertArraySpatial.Length / 2);
                    for (int iLstKey = 0; iLstKey < dicMonitorsDaily.Keys.Count; iLstKey++)
                    {
                        dicMonitorsDaily[lstKeySpatial[iLstKey]].longitudeLamber = dConvertArraySpatial[2 * iLstKey] / 100.00;
                        dicMonitorsDaily[lstKeySpatial[iLstKey]].latitudeLamber = dConvertArraySpatial[2 * iLstKey + 1] / 100.00;
                    }
                    GetGridCellOfficialMonitor(ref dicModelGridOfMonitors, dicGridModel, null, ref dicMonitorsDaily);
                }
                else if (SSIAdailyPMAnalysisConfiguration.analysisOptionD.useDispersionOnly)
                {
                    double[] dConvertArraySpatial = null;
                    List<double> lstConvertArraySpatial = new List<double>();
                    List<string> lstKeySpatial = dicMonitorsDaily.Keys.ToList();
                    for (int iLstKey = 0; iLstKey < dicMonitorsDaily.Keys.Count; iLstKey++)
                    {
                        lstConvertArraySpatial.Add(dicMonitorsDaily[lstKeySpatial[iLstKey]].longitude);
                        lstConvertArraySpatial.Add(dicMonitorsDaily[lstKeySpatial[iLstKey]].lat);
                    }
                    dConvertArraySpatial = lstConvertArraySpatial.ToArray();
                    DotSpatial.Projections.Reproject.ReprojectPoints(dConvertArraySpatial, null, DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984,
       DotSpatial.Projections.ProjectionInfo.FromProj4String(CommonClass.projUSAAERMOD), 0, dConvertArraySpatial.Length / 2);
                    for (int iLstKey = 0; iLstKey < dicMonitorsDaily.Keys.Count; iLstKey++)
                    {
                        dicMonitorsDaily[lstKeySpatial[iLstKey]].longitudeUTM = (dConvertArraySpatial[2 * iLstKey] - 738547) / 100.00;
                        dicMonitorsDaily[lstKeySpatial[iLstKey]].latitudeUTM = (dConvertArraySpatial[2 * iLstKey + 1] - 3724842) / 100.00;
                    }
                    GetGridCellOfficialMonitor(ref dicModelGridOfMonitors, null, dicDispersionModel, ref dicMonitorsDaily);
                }
                GetGridCellOfficialMonitor(ref dicModelGridOfMonitors, dicGridModel, dicDispersionModel, ref dicMonitorsDaily);
                #endregion

                #region select top 8 values according to pm25(descending order) for each year each quarter
                Dictionary<string, Monitors> dicAllMonitors = new Dictionary<string, Monitors>();
                dicAllMonitors = new Dictionary<string, Monitors>();
                
                foreach (KeyValuePair<string, Monitors> k in dicMonitorsDaily)
                {
                    //if (!dicOfficialMonitorInModel.Keys.Contains(k.Key)) continue;
                    if (!dicValidYear.ContainsKey(k.Key)) continue;
                    dicAllMonitors.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,
                        latitudeLamber = k.Value.latitudeLamber,
                        longitudeLamber = k.Value.longitudeLamber,
                        latitudeUTM = k.Value.latitudeUTM,
                        longitudeUTM = k.Value.longitudeUTM,
                        countyName = k.Value.countyName,
                        //percentile_98 = k.Value.percentile_98,
                        //rank98 = k.Value.rank98,
                        monitorGridcell = k.Value.monitorGridcell,
                        dicOfficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                    });
                    foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, PM25Monitors>>> kin in dicMonitorsDaily[k.Key].dicOfficialPM25Daily)
                    {
                        dicAllMonitors[k.Key].dicOfficialPM25Daily.Add(kin.Key, new Dictionary<string, Dictionary<string, PM25Monitors>>());
                        foreach (KeyValuePair<string, Dictionary<string, PM25Monitors>> item in dicMonitorsDaily[k.Key].dicOfficialPM25Daily[kin.Key])
                        {
                            if (!dicValidYear[k.Key].Contains(item.Key)) continue;
                            dicAllMonitors[k.Key].dicOfficialPM25Daily[kin.Key].Add(item.Key, item.Value.OrderByDescending(p => p.Value.bPM25).Take(8).ToDictionary(p => p.Key, p => p.Value));
                        }
                    }
                }
                dicMonitorsDaily.Clear();

                Dictionary<string, Monitors> dicMonitorsInModelDomain = new Dictionary<string, Monitors>();
                dicMonitorsInModelDomain = dicAllMonitors.Where(p => dicModelGridOfMonitors.ContainsKey(p.Key)).ToDictionary(p=>p.Key,p=>p.Value);


                GC.Collect();
                #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(SSIAdailyPMAnalysisConfiguration.dataInputD.unofficialMonitorFile) + "\".";
                ////CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                ////isOK = GetUnofficialPM(SSIAdailyPMAnalysisConfiguration, 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(SSIAdailyPMAnalysisConfiguration.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 >= SSIAdailyPMAnalysisConfiguration.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 >= SSIAdailyPMAnalysisConfiguration.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() >= SSIAdailyPMAnalysisConfiguration.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(SSIAdailyPMAnalysisConfiguration, 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.KnownCoordinateSystems.Projected.NorthAmerica.USAContiguousLambertConformalConic, 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 (SSIAdailyPMAnalysisConfiguration.outputChoiceAdvancedD.doQuarterlyPeakSpeciatedMonitors)
                //{
                //    SaveQuarterlyPeakPMMonitors(CommonClass.CurrentBaseScenario, dicUnofficialPM);
                //}
                //#endregion

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

                //    isOK = GetSpeciesMonitors(SSIAdailyPMAnalysisConfiguration, ref dicSpeciesDaily);
                //    if (dicSpeciesDaily.Count <= 0 || isOK == "unknow")//error message when loading file
                //    {
                //        CommonClass.CurrentLog = "Fail to read species monitor data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.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 >= SSIAdailyPMAnalysisConfiguration.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 >= SSIAdailyPMAnalysisConfiguration.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() >= SSIAdailyPMAnalysisConfiguration.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(SSIAdailyPMAnalysisConfiguration, 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.KnownCoordinateSystems.Projected.NorthAmerica.USAContiguousLambertConformalConic, 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 (SSIAdailyPMAnalysisConfiguration.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", SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaCrustal, fsoutString, dicSpeciatedMonitors);
                //            DailyVNA(ref dicNeighborInfo, kQ.Key, "DON", SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaDON, fsoutStringNH4DON, dicSpeciatedMonitors);
                //            DailyVNA(ref dicNeighborInfo, kQ.Key, "EC", SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaEC, fsoutString, dicSpeciatedMonitors);
                //            DailyVNA(ref dicNeighborInfo, kQ.Key, "NH4", SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaNH4, fsoutStringNH4DON, dicSpeciatedMonitors);
                //            DailyVNA(ref dicNeighborInfo, kQ.Key, "NO3", SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaNO3, fsoutString, dicSpeciatedMonitors);
                //            DailyVNA(ref dicNeighborInfo, kQ.Key, "NO3r", SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaNO3r, fsoutString, dicSpeciatedMonitors);
                //            DailyVNA(ref dicNeighborInfo, kQ.Key, "OCb", SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaOC, fsoutString, dicSpeciatedMonitors);
                //            DailyVNA(ref dicNeighborInfo, kQ.Key, "SALT", SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.distanceCrustal, ref vnaSalt, fsoutString, dicSpeciatedMonitors);
                //            DailyVNA(ref dicNeighborInfo, kQ.Key, "SO4", SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.interpolationMethodCrustal, SSIAdailyPMAnalysisConfiguration.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 (SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.doUseDonValues)
                //            {
                //                vnaNH4 = vnaDON * vnaSO4 + 0.29 * vnaNO3r;
                //            }
                //            else if (SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.doUseMeasuredAmmonium)
                //            {
                //                double nh4_adj = vnaNH4 - (SSIAdailyPMAnalysisConfiguration.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(SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.defaultBlankMass);
                //            oc = nonBlankMass - (vnaCrustal + vnaSO4 + vnaNO3r + vnaNH4 + vnaPBW + vnaSalt + vnaEC);
                //            oc_floor = Convert.ToDouble(SSIAdailyPMAnalysisConfiguration.speciesFractionOptionsD.floorOCMMB) * vnaOC;
                //            oc_max = Math.Max(oc, oc_floor);
                //            oc_ceiling = Convert.ToDouble(SSIAdailyPMAnalysisConfiguration.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 (SSIAdailyPMAnalysisConfiguration.chooseDesiredOutputD.doSpeciesFraction)
                //    {
                //        SaveSpeciesFractions(CommonClass.CurrentBaseScenario, dicSpeciesFractions, "");
                //        if (SSIAdailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                //        {
                //            for (int i = 0; i < dicDesignValuePeriod.Count; i++)
                //            {
                //                SaveSpeciesFractions(CommonClass.CurrentBaseScenario, dicSpeciesFractions, " Period " + (i + 1).ToString());
                //            }
                //        }
                //    }

                //    if (SSIAdailyPMAnalysisConfiguration.outputChoiceAdvancedD.doNeighborFilePoint)
                //    {
                //        SaveNeighborFilePoint(CommonClass.CurrentBaseScenario, dicNeighborFilePoint, "");
                //        if (SSIAdailyPMAnalysisConfiguration.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 (SSIAdailyPMAnalysisConfiguration.dataInputD.doSpeciesFractionFile)
                //{
                //    _beginTime = DateTime.Now;
                //    CommonClass.CurrentLog = "Read species fraction data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.dataInputD.specFracPointFile) + "\".";
                //    CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                //    isOK = GetSpeciesFractions(SSIAdailyPMAnalysisConfiguration, ref dicSpeciesFractions);
                //    if (!string.IsNullOrEmpty(isOK))//error message when loading file
                //    {
                //        CommonClass.CurrentLog = "Fail to read species fraction data \"" + Path.GetFileName(SSIAdailyPMAnalysisConfiguration.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 (SSIAdailyPMAnalysisConfiguration.chooseDesiredOutputD.doSpeciesFraction)
                //    {
                //        SaveSpeciesFractionCopyDirectly(CommonClass.CurrentBaseScenario);
                //    }
                //}
                #endregion

                _beginTime = DateTime.Now;
                #region use species fractions to calculate baseline top32 species values
                Dictionary<string, Monitors> dicPMMonitors = new Dictionary<string, Monitors>();
                foreach (KeyValuePair<string, Monitors> k in dicMonitorsInModelDomain)
                {
                    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>>>(),
                    });
                    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;
                                dic.Add(kD.Key, pM25Monitors);
                            }
                            dicYear.Add(kY.Key + "," + rank, dic);
                        }
                        dicPMMonitors[k.Key].dicOfficialPM25Daily.Add(kQ.Key, dicYear);
                    }
                }
                #endregion

                #region step3: calculate ，future species values and pm25

                Dictionary<string, DailyModelMonitor> dicModelDataPeriod = new Dictionary<string, DailyModelMonitor>();
                foreach (KeyValuePair<string, Monitors> k in dicMonitorsInModelDomain)
                {
                    //if (!dicGridModel.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>();
                    #region 首先根据gridtype获取周围的网格数
                    switch ("1x1")//SSIAdailyPMAnalysisConfiguration.modelInputD.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

                    //然后根据选择的统计方法求所有网格的baseline和control的值：mean、max
                    List<KeyValuePair<string,DailyModelMonitor>> query = dicGridModel.Where(p => lstArround.Contains(p.Key)).ToList();
                    List<KeyValuePair<string, DailyModelMonitor>> queryDispersion = dicDispersionModel.Where(p => lstArround.Contains(p.Key)).ToList();
                    query.AddRange(queryDispersion); queryDispersion.Clear();
                    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>();
                        //--------MaxDelta
                        Dictionary<string, ModelDataSpecies> dicDmMaxDelta = new Dictionary<string, ModelDataSpecies>();
                        for (int i = 0; i < iQueryCount; i++)
                        {
                            KeyValuePair<string, DailyModelMonitor> kin = query.ToArray()[i];
                            if(dicMaxDeltaGrid.ContainsKey(kin.Key))
                            {
                                if (dicDmMaxDelta.ContainsKey(kin.Key))
                                {
                                    if (dicDmMaxDelta[kin.Key].pm25 < dicMaxDeltaGrid[kin.Key][9].pm25)
                                        dicDmMaxDelta[kin.Key].pm25 = dicMaxDeltaGrid[kin.Key][9].pm25;
                                    if (dicDmMaxDelta[kin.Key].pm25sec < dicMaxDeltaGrid[kin.Key][9].pm25sec)
                                        dicDmMaxDelta[kin.Key].pm25sec = dicMaxDeltaGrid[kin.Key][9].pm25sec;
                                    if (dicDmMaxDelta[kin.Key].pm25prim < dicMaxDeltaGrid[kin.Key][9].pm25prim)
                                        dicDmMaxDelta[kin.Key].pm25prim = dicMaxDeltaGrid[kin.Key][9].pm25prim;

                                }
                                else
                                {
                                    dicDmMaxDelta.Add(kin.Key, dicMaxDeltaGrid[kin.Key][9]);
                                }
                            }
                            else if (dicMaxDeltaDispersion.ContainsKey(kin.Key))
                            {
                                if (dicDmMaxDelta.ContainsKey(kin.Key))
                                {
                                    if (dicDmMaxDelta[kin.Key].pm25 < dicMaxDeltaDispersion[kin.Key][9].pm25)
                                        dicDmMaxDelta[kin.Key].pm25 = dicMaxDeltaDispersion[kin.Key][9].pm25;
                                    if (dicDmMaxDelta[kin.Key].pm25sec < dicMaxDeltaDispersion[kin.Key][9].pm25sec)
                                        dicDmMaxDelta[kin.Key].pm25sec = dicMaxDeltaDispersion[kin.Key][9].pm25sec;
                                    if (dicDmMaxDelta[kin.Key].pm25prim < dicMaxDeltaDispersion[kin.Key][9].pm25prim)
                                        dicDmMaxDelta[kin.Key].pm25prim = dicMaxDeltaDispersion[kin.Key][9].pm25prim;
                                }
                                else
                                {
                                    dicDmMaxDelta.Add(kin.Key, dicMaxDeltaDispersion[kin.Key][9]);
                                }
                            }
                        }
                        dicModelDataPeriod[k.Key].dicMaxDeltaSpecies = dicDmMaxDelta;
                        //根据选项求结果:mean/max
                        #region
                        switch ("Mean")//SSIAdailyPMAnalysisConfiguration.modelInputD.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].pm25 += kBase.Value.pm25;
                                        }
                                        else
                                        {
                                            dicDmBaseline.Add(kBase.Key, new ModelDataSpecies()
                                            {
                                                crustal = 0,
                                                nh4 = 0,
                                                so4 = 0,
                                                ec = 0,
                                                no3 = 0,
                                                oc = 0,
                                                cm = 0,
                                                salt = 0,
                                                pm25 = kBase.Value.pm25,
                                            });
                                        }
                                    }
                                    foreach (KeyValuePair<string, ModelDataSpecies> kControl in kin.Value.dicFutureSpecies)
                                    {
                                        if (dicDmFuture.ContainsKey(kControl.Key))
                                        {
                                            dicDmFuture[kControl.Key].pm25 += kControl.Value.pm25;
                                        }
                                        else
                                        {
                                            dicDmFuture.Add(kControl.Key, new ModelDataSpecies()
                                            {
                                                crustal = 0,
                                                nh4 = 0,
                                                so4 = 0,
                                                ec = 0,
                                                no3 = 0,
                                                oc = 0,
                                                cm = 0,
                                                salt = 0,
                                                pm25 = kControl.Value.pm25
                                            });
                                        }
                                    }
                                }
                                //------------calculate mean--------------
                                foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicDmBaseline)
                                {
                                    dicDmBaseline[kBase.Key].pm25 = dicDmBaseline[kBase.Key].pm25 / iQueryCount;
                                }
                                foreach (KeyValuePair<string, ModelDataSpecies> kControl in dicDmFuture)
                                {
                                    dicDmFuture[kControl.Key].pm25 = dicDmFuture[kControl.Key].pm25 / 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()
                                            {
                                                pm25 = kBase.Value.pm25,
                                            });
                                        }
                                        else
                                        {
                                            if (dicDmBaseline[kBase.Key].pm25 < kBase.Value.pm25)
                                                dicDmBaseline[kBase.Key].pm25 = kBase.Value.pm25;
                                        }
                                    }
                                    foreach (KeyValuePair<string, ModelDataSpecies> kControl in kin.Value.dicFutureSpecies)
                                    {
                                        if (!dicDmFuture.ContainsKey(kControl.Key))
                                        {
                                            dicDmFuture.Add(kControl.Key, new ModelDataSpecies()
                                            {
                                                pm25 = kControl.Value.pm25,
                                            });
                                        }
                                        else
                                        {
                                            if (dicDmFuture[kControl.Key].pm25 < kControl.Value.pm25)
                                                dicDmFuture[kControl.Key].pm25 = kControl.Value.pm25;
                                        }
                                    }
                                }
                                foreach (KeyValuePair<string, ModelDataSpecies> kBase in dicDmBaseline)
                                {
                                    dicDmBaseline[kBase.Key].pm25 = dicDmBaseline[kBase.Key].pm25 / iQueryCount;
                                }
                                foreach (KeyValuePair<string, ModelDataSpecies> kControl in dicDmFuture)
                                {
                                    dicDmFuture[kControl.Key].pm25 = dicDmFuture[kControl.Key].pm25 / 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;
                                            }
                                        }
                                    }
                                }
                                dicModelDataPeriod[k.Key].dicBaseSpecies = dicDmBaseline;
                                dicModelDataPeriod[k.Key].dicFutureSpecies = dicDmFuture;
                                break;
                        }
                        #endregion
                        #region
                        foreach (KeyValuePair<string, ModelDataSpecies> kSpecies in dicDmBaseline)
                        {
                            if (kSpecies.Value.pm25 < CommonClass.RrfLimit) kSpecies.Value.pm25 = Convert.ToSingle(CommonClass.RrfLimit);
                        }
                        foreach (KeyValuePair<string, ModelDataSpecies> kSpecies in dicDmFuture)
                        {
                            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)
                                {
                                    if (!dicDmFuture.ContainsKey(ipmQuarter.Key)) continue;
                                    //ipmDay.Value.fPM25 = ipmDay.Value.bPM25 * (dicDmFuture[ipmQuarter.Key].pm25 < CommonClass.RrfLimit ? CommonClass.RrfLimit : dicDmFuture[ipmQuarter.Key].pm25) / (dicDmBaseline[ipmQuarter.Key].pm25 < CommonClass.RrfLimit ? CommonClass.RrfLimit : dicDmBaseline[ipmQuarter.Key].pm25);
                                    if (ipmDay.Value.bPM25 < 0)
                                        ipmDay.Value.fPM25 = -9;
                                    else
                                        ipmDay.Value.fPM25 = ipmDay.Value.bPM25 + dicDmFuture[ipmQuarter.Key].pm25 - dicDmBaseline[ipmQuarter.Key].pm25;
                                }
                            }
                        }
                        #endregion

                    }
                }
                #region dv period
                //if (SSIAdailyPMAnalysisConfiguration.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 (SSIAdailyPMAnalysisConfiguration.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 (SSIAdailyPMAnalysisConfiguration.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 (SSIAdailyPMAnalysisConfiguration.pm25CalculationOptionsD.doCalcNH4fromDON)
                //                        {
                //                            kD.Value.fNH4 = kD.Value.bDON * kD.Value.fSO4 + 0.29 * kD.Value.fNO3r;
                //                        }
                //                        else if (SSIAdailyPMAnalysisConfiguration.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(SSIAdailyPMAnalysisConfiguration.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 (var k in dicPMMonitors)
                {
                    foreach (var kQuarter in dicPMMonitors[k.Key].dicOfficialPM25Daily)
                    {
                        foreach (var 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
                #endregion
                dicMonitorsInModelDomain.Clear();
                GC.Collect();
                #endregion

                #region ---------get All Years High Days--------------
                Dictionary<string, Monitors> dicHighDaysDaily = new Dictionary<string, Monitors>();
                GetAllYearHighDays(SSIAdailyPMAnalysisConfiguration, ref dicHighDaysDaily, dicAllYearsAllDaysDaily);
                #endregion

                #region get forecasted pm25 value for each year according to rank98
                List<Dictionary<string, PMPoint>> lstDailyPointPeriod = new List<Dictionary<string, PMPoint>>();
                Dictionary<string, PMPoint> dicDailyPoint = new Dictionary<string, PMPoint>();
                GetQuarterlyPointFutureValue(SSIAdailyPMAnalysisConfiguration, ref dicHighDaysDaily, dicDesignValuePeriod, dicComCodePeriod);
                GetDailyPointFutureVlues(SSIAdailyPMAnalysisConfiguration, dicHighDaysDaily, dicDesignValuePeriod, dicComCodePeriod, ref dicDailyPoint, ref lstDailyPointPeriod,dicModelDataPeriod);

                dicAllYearsAllDaysDaily.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.";
                

                if (SSIAdailyPMAnalysisConfiguration.analysisOptionD.useDispersionOnly)
                {
                    SaveDailyPmPoint(CommonClass.CurrentBaseScenario, dicDailyPoint, "Dispersion");
                    SaveQuarterPMPoint(CommonClass.CurrentBaseScenario, dicHighDaysDaily, "Dispersion");

                    #region spatial field
                    sp(ref dicAllMonitors, dicDesignValuePeriod, dicComCodePeriod);                    
                    _beginTime = DateTime.Now;

                    DotSpatial.Topology.Polygon pUSA = CommonClass.generatePolygonWithinUSA("AERMOD");
                    double dInUSA = 16;

                    Dictionary<string, Monitors> dicPmMonitorsLatLong = new Dictionary<string, Monitors>();
                    foreach (KeyValuePair<string, Monitors> k in dicAllMonitors)
                    {
                        if (!dicPmMonitorsLatLong.ContainsKey(k.Value.longitudeUTM + "," + k.Value.latitudeUTM))
                        {
                            dicPmMonitorsLatLong.Add(k.Value.longitudeUTM + "," + k.Value.latitudeUTM, k.Value);
                        }
                    }
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicDispersionModel)
                    {
                        if (pUSA.Contains(new DotSpatial.Topology.Point(k.Value.longitudeUTM, k.Value.latitudeUTM)))
                        {
                            dInUSA = 7;
                        }
                        else
                            dInUSA = 15;

                        #region pm values
                        List<double> fsInterPM = new List<double>();
                        fsInterPM.Add(k.Value.longitudeUTM);
                        fsInterPM.Add(k.Value.latitudeUTM);
                        //简化VNA算法：求半径范围内的监测点做VNA，一开始以5个经纬度来算一直达到10个为止
                        Dictionary<string, double> dicDistanceMonitorPM = new Dictionary<string, double>();
                        foreach (KeyValuePair<string, Monitors> kPM in dicAllMonitors)
                        {
                            //----------改成extent----
                            double dLongAbs = Math.Abs(kPM.Value.longitude - k.Value.longitude);
                            if (dLongAbs > dInUSA) continue;
                            double dLatAbs = Math.Abs(kPM.Value.lat - k.Value.lat);
                            if (dLatAbs > dInUSA) continue;
                            if (dLongAbs > dLatAbs)
                            {
                                dicDistanceMonitorPM.Add(kPM.Key, dLongAbs);
                            }
                            else
                            {
                                dicDistanceMonitorPM.Add(kPM.Key, dLatAbs);
                            }
                        }
                        List<KeyValuePair<string, double>> query = new List<KeyValuePair<string, double>>();
                        query = dicDistanceMonitorPM.ToList();
                        bool isSame = false;
                        foreach (KeyValuePair<string, double> kPM in query)
                        {
                            fsInterPM.Add(dicAllMonitors[kPM.Key].longitudeUTM);
                            fsInterPM.Add(dicAllMonitors[kPM.Key].latitudeUTM);
                            if (k.Value.longitudeUTM == dicAllMonitors[kPM.Key].longitudeUTM
                                && k.Value.latitudeUTM == dicAllMonitors[kPM.Key].latitudeUTM)
                            {
                                isSame = true;
                                break;
                            }
                        }
                        //------------end VNA 简化算法
                        List<double> fsoutPM = new List<double>();
                        if (!isSame)
                        {
                            CommonClass.VoronoiPoints(fsInterPM.ToArray(), ref fsoutPM);
                        }
                        else
                        {
                            fsInterPM.Add(k.Value.longitudeUTM);
                            fsInterPM.Add(k.Value.latitudeUTM);
                        }
                        
                        if (fsoutPM.Count == 0) continue;
                        //----------------calculate neighbor distance----------------
                        Dictionary<string, float> fsoutStringPM = new Dictionary<string, float>();
                        for (int ifsoutPM = 0; ifsoutPM < fsoutPM.Count; ifsoutPM++)
                        {
                            if (ifsoutPM % 2 == 1)
                            {
                                float distance = Convert.ToSingle(Math.Sqrt(Math.Pow(k.Value.longitudeUTM - dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].longitudeUTM, 2) + Math.Pow(k.Value.latitudeUTM - dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].latitudeUTM, 2)));//CommonClass.getDistanceFrom2Point(k.Value.longitude, k.Value.lat, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].longitude, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].latitude);
                                fsoutStringPM.Add(dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].id + "," + dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].monitorGridcell, distance);
                            }
                        }
                        if (fsoutStringPM.Count == 0) continue;
                        Dictionary<string, float> dicGradAdjValues = new Dictionary<string, float>();
                        double vnaPM = 0;
                        //--------calculate vna or evna according to the setting ----------------
                        #region
                        for (int i = 0; i < 5; i++)
                        {
                            if (SSIAdailyPMAnalysisConfiguration.monitorInputD.useVNA)
                            {
                                AnnualVNA("Inverse Distance Weights", 9000000000, ref vnaPM, fsoutStringPM, dicAllMonitors, "0");
                            }
                            if (k.Value.dicCIAvna.ContainsKey(i.ToString()))
                                k.Value.dicCIAvna[i.ToString()] = vnaPM;
                            else
                                k.Value.dicCIAvna.Add(i.ToString(), vnaPM);

                        }
                        #endregion
                        fsoutStringPM.Clear();
                        #endregion
                    }
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.");
                    CommonClass.CurrentLog = "Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.";

                    #endregion

                    SaveSSIADailyPMData(baseScenario, null, dicDispersionModel, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                    SaveSSIAQuarterlyPMData(baseScenario, null, dicDispersionModel, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                }
                else if (SSIAdailyPMAnalysisConfiguration.analysisOptionD.useGridOnly)
                {
                    SaveDailyPmPoint(CommonClass.CurrentBaseScenario, dicDailyPoint, "Grid");
                    SaveQuarterPMPoint(CommonClass.CurrentBaseScenario, dicHighDaysDaily, "Grid");

                    #region spatial field
                    sp(ref dicAllMonitors, dicDesignValuePeriod, dicComCodePeriod);
                    _beginTime = DateTime.Now;

                    DotSpatial.Topology.Polygon pUSA = CommonClass.generatePolygonWithinUSA("CMAQ");//new DotSpatial.Topology.Polygon(lstUSA);
                    double dInUSA = 16;

                    Dictionary<string, Monitors> dicPmMonitorsLatLong = new Dictionary<string, Monitors>();
                    foreach (KeyValuePair<string, Monitors> k in dicAllMonitors)
                    {
                        if (!dicPmMonitorsLatLong.ContainsKey(k.Value.longitudeLamber + "," + k.Value.latitudeLamber))
                        {
                            dicPmMonitorsLatLong.Add(k.Value.longitudeLamber + "," + k.Value.latitudeLamber, k.Value);
                        }
                    }
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicGridModel)
                    {
                        if (pUSA.Contains(new DotSpatial.Topology.Point(k.Value.longitudeLamber, k.Value.latitudeLamber)))
                        {
                            dInUSA = 7;
                        }
                        else
                            dInUSA = 15;

                        #region pm values
                        List<double> fsInterPM = new List<double>();
                        fsInterPM.Add(k.Value.longitudeLamber);
                        fsInterPM.Add(k.Value.latitudeLamber);
                        //简化VNA算法：求半径范围内的监测点做VNA，一开始以5个经纬度来算一直达到10个为止
                        Dictionary<string, double> dicDistanceMonitorPM = new Dictionary<string, double>();
                        foreach (KeyValuePair<string, Monitors> kPM in dicAllMonitors)
                        {
                            //----------改成extent----
                            double dLongAbs = Math.Abs(kPM.Value.longitude - k.Value.longitude);
                            if (dLongAbs > dInUSA) continue;
                            double dLatAbs = Math.Abs(kPM.Value.lat - k.Value.lat);
                            if (dLatAbs > dInUSA) continue;
                            if (dLongAbs > dLatAbs)
                            {
                                dicDistanceMonitorPM.Add(kPM.Key, dLongAbs);
                            }
                            else
                            {
                                dicDistanceMonitorPM.Add(kPM.Key, dLatAbs);
                            }
                        }
                        List<KeyValuePair<string, double>> query = new List<KeyValuePair<string, double>>();
                        query = dicDistanceMonitorPM.ToList();
                        bool isSame = false;
                        foreach (KeyValuePair<string, double> kPM in query)
                        {
                            fsInterPM.Add(dicAllMonitors[kPM.Key].longitudeLamber);
                            fsInterPM.Add(dicAllMonitors[kPM.Key].latitudeLamber);
                            if (k.Value.longitudeLamber == dicAllMonitors[kPM.Key].longitudeLamber
                                && k.Value.latitudeLamber == dicAllMonitors[kPM.Key].latitudeLamber)
                            {
                                isSame = true;
                                break;
                            }
                        }
                        //------------end VNA 简化算法
                        List<double> fsoutPM = new List<double>();
                        if (!isSame)
                        {
                            CommonClass.VoronoiPoints(fsInterPM.ToArray(), ref fsoutPM);
                        }
                        else
                        {
                            fsInterPM.Add(k.Value.longitudeLamber);
                            fsInterPM.Add(k.Value.latitudeLamber);
                        }
                        if (fsoutPM.Count == 0) continue;
                        //----------------calculate neighbor distance----------------
                        Dictionary<string, float> fsoutStringPM = new Dictionary<string, float>();
                        for (int ifsoutPM = 0; ifsoutPM < fsoutPM.Count; ifsoutPM++)
                        {
                            if (ifsoutPM % 2 == 1)
                            {
                                float distance = Convert.ToSingle(Math.Sqrt(Math.Pow(k.Value.longitudeLamber - dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].longitudeLamber, 2) + Math.Pow(k.Value.latitudeLamber - dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].latitudeLamber, 2))); //CommonClass.getDistanceFrom2Point(k.Value.longitude, k.Value.lat, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].longitude, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].latitude);
                                fsoutStringPM.Add(dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].id + "," + dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].monitorGridcell, distance);
                            }
                        }
                        if (fsoutStringPM.Count == 0) continue;
                        Dictionary<string, float> dicGradAdjValues = new Dictionary<string, float>();
                        if (SSIAdailyPMAnalysisConfiguration.monitorInputD.useEVNA)
                            GetGradAdjValues(ref dicGradAdjValues, fsoutStringPM, k.Value.dicBaseSpecies, dicGridModel);

                        for (int i = 0; i < 5; i++)
                        {
                            double vnaPM = 0, gvnaPM = 0;
                            //--------calculate vna or evna according to the setting ----------------
                            #region
                            if (SSIAdailyPMAnalysisConfiguration.monitorInputD.useVNA && SSIAdailyPMAnalysisConfiguration.monitorInputD.useEVNA)
                            {
                                AnnualVNAEVNA(dicGradAdjValues, "Inverse Distance Weights", 9000000000, ref vnaPM, ref gvnaPM, fsoutStringPM, dicAllMonitors, i.ToString());
                            }
                            else if (SSIAdailyPMAnalysisConfiguration.monitorInputD.useVNA)
                            {
                                AnnualVNA("Inverse Distance Weights", 9000000000, ref vnaPM, fsoutStringPM, dicAllMonitors, i.ToString());
                            }
                            else if (SSIAdailyPMAnalysisConfiguration.monitorInputD.useEVNA)
                            {
                                AnnualEVNA(dicGradAdjValues, "Inverse Distance Weights", 9000000000, ref gvnaPM, fsoutStringPM, dicAllMonitors, i.ToString());
                            }
                            if (k.Value.dicCIAvna.ContainsKey(i.ToString()))
                                k.Value.dicCIAvna[i.ToString()] = vnaPM;// +k.Value.DeltaModel.pm25;
                            else
                                k.Value.dicCIAvna.Add(i.ToString(), vnaPM);
                            if (k.Value.dicCIAevna.ContainsKey(i.ToString()))
                                k.Value.dicCIAevna[i.ToString()] = gvnaPM;// +k.Value.DeltaModel.pm25;
                            else
                                k.Value.dicCIAevna.Add(i.ToString(), gvnaPM);
                        }
                            #endregion
                        fsoutStringPM.Clear();
                        #endregion
                    }
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.");
                    CommonClass.CurrentLog = "Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.";
                    #endregion

                    SaveSSIADailyPMData(baseScenario, dicGridModel, null, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                    SaveSSIAQuarterlyPMData(baseScenario, dicGridModel, null, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                }
                else
                {
                    #region spatial field
                    sp(ref dicAllMonitors, dicDesignValuePeriod, dicComCodePeriod);
                    _beginTime = DateTime.Now;
                    DotSpatial.Topology.Polygon pUSA = CommonClass.generatePolygonWithinUSA("CMAQ");
                    double dInUSA = 16;

                    Dictionary<string, Monitors> dicPmMonitorsLatLong = new Dictionary<string, Monitors>();
                    foreach (KeyValuePair<string, Monitors> k in dicAllMonitors)
                    {
                        if (!dicPmMonitorsLatLong.ContainsKey(k.Value.longitudeLamber + "," + k.Value.latitudeLamber))
                        {
                            dicPmMonitorsLatLong.Add(k.Value.longitudeLamber + "," + k.Value.latitudeLamber, k.Value);
                        }
                    }
                    Dictionary<string, DailyModelMonitor> dicCombine = new Dictionary<string, DailyModelMonitor>();
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicGridModel)
                    {
                        dicCombine.Add(k.Key, k.Value);
                    }
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicDispersionModel)
                    {
                        dicCombine.Add(k.Key, k.Value);
                    }
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicCombine)
                    {
                        if (pUSA.Contains(new DotSpatial.Topology.Point(k.Value.longitudeLamber, k.Value.latitudeLamber)))
                        {
                            dInUSA = 7;
                        }
                        else
                            dInUSA = 15;

                        #region pm values
                        List<double> fsInterPM = new List<double>();
                        fsInterPM.Add(k.Value.longitudeLamber);
                        fsInterPM.Add(k.Value.latitudeLamber);
                        //简化VNA算法：求半径范围内的监测点做VNA，一开始以5个经纬度来算一直达到10个为止
                        Dictionary<string, double> dicDistanceMonitorPM = new Dictionary<string, double>();
                        foreach (KeyValuePair<string, Monitors> kPM in dicAllMonitors)
                        {
                            //----------改成extent----
                            double dLongAbs = Math.Abs(kPM.Value.longitude - k.Value.longitude);
                            if (dLongAbs > dInUSA) continue;
                            double dLatAbs = Math.Abs(kPM.Value.lat - k.Value.lat);
                            if (dLatAbs > dInUSA) continue;
                            if (dLongAbs > dLatAbs)
                            {
                                dicDistanceMonitorPM.Add(kPM.Key, dLongAbs);
                            }
                            else
                            {
                                dicDistanceMonitorPM.Add(kPM.Key, dLatAbs);
                            }
                        }
                        List<KeyValuePair<string, double>> query = new List<KeyValuePair<string, double>>();
                        query = dicDistanceMonitorPM.ToList();
                        bool isSame = false;
                        foreach (KeyValuePair<string, double> kPM in query)
                        {
                            fsInterPM.Add(dicAllMonitors[kPM.Key].longitudeLamber);
                            fsInterPM.Add(dicAllMonitors[kPM.Key].latitudeLamber);
                            if (k.Value.longitudeLamber == dicAllMonitors[kPM.Key].longitudeLamber
                                && k.Value.latitudeLamber == dicAllMonitors[kPM.Key].latitudeLamber)
                            {
                                isSame = true;
                                break;
                            }
                        }
                        //------------end VNA 简化算法
                        List<double> fsoutPM = new List<double>();
                        if (!isSame)
                        {
                            CommonClass.VoronoiPoints(fsInterPM.ToArray(), ref fsoutPM);
                        }
                        else
                        {
                            fsInterPM.Add(k.Value.longitudeLamber);
                            fsInterPM.Add(k.Value.latitudeLamber);
                        }
                        if (fsoutPM.Count == 0) continue;
                        //----------------calculate neighbor distance----------------
                        Dictionary<string, float> fsoutStringPM = new Dictionary<string, float>();
                        for (int ifsoutPM = 0; ifsoutPM < fsoutPM.Count; ifsoutPM++)
                        {
                            if (ifsoutPM % 2 == 1)
                            {
                                float distance = Convert.ToSingle(Math.Sqrt(Math.Pow(k.Value.longitudeLamber - dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].longitudeLamber, 2) + Math.Pow(k.Value.latitudeLamber - dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].latitudeLamber, 2)));//CommonClass.getDistanceFrom2Point(k.Value.longitude, k.Value.lat, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].longitude, dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].latitude);
                                fsoutStringPM.Add(dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].id + "," + dicPmMonitorsLatLong[fsoutPM[ifsoutPM - 1] + "," + fsoutPM[ifsoutPM]].monitorGridcell, distance);
                            }
                        }
                        if (fsoutStringPM.Count == 0) continue;
                        Dictionary<string, float> dicGradAdjValues = new Dictionary<string, float>();
                        if (SSIAdailyPMAnalysisConfiguration.monitorInputD.useEVNA)
                            GetGradAdjValues(ref dicGradAdjValues, fsoutStringPM, k.Value.dicBaseSpecies, dicCombine);
                        double vnaPM = 0, gvnaPM = 0;
                        //--------calculate vna or evna according to the setting ----------------
                        #region
                        for (int i = 0; i < 5; i++)
                        {
                            if (SSIAdailyPMAnalysisConfiguration.monitorInputD.useVNA && SSIAdailyPMAnalysisConfiguration.monitorInputD.useEVNA)
                            {
                                AnnualVNAEVNA(dicGradAdjValues, "Inverse Distance Weights", 9000000000, ref vnaPM, ref gvnaPM, fsoutStringPM, dicAllMonitors, i.ToString());
                            }
                            else if (SSIAdailyPMAnalysisConfiguration.monitorInputD.useVNA)
                            {
                                AnnualVNA("Inverse Distance Weights", 9000000000, ref vnaPM, fsoutStringPM, dicAllMonitors, i.ToString());
                            }
                            else if (SSIAdailyPMAnalysisConfiguration.monitorInputD.useEVNA)
                            {
                                AnnualEVNA(dicGradAdjValues, "Inverse Distance Weights", 9000000000, ref gvnaPM, fsoutStringPM, dicAllMonitors, i.ToString());
                            }
                            if (k.Value.dicCIAvna.ContainsKey(i.ToString()))
                                k.Value.dicCIAvna[i.ToString()] = vnaPM;// +k.Value.DeltaModel.pm25;
                            else
                                k.Value.dicCIAvna.Add(i.ToString(), vnaPM);
                            if (k.Value.dicCIAevna.ContainsKey(i.ToString()))
                                k.Value.dicCIAevna[i.ToString()] = gvnaPM;// +k.Value.DeltaModel.pm25;
                            else
                                k.Value.dicCIAevna.Add(i.ToString(), gvnaPM);
                            if (dicGridModel.ContainsKey(k.Key))
                            {
                                if (dicGridModel[k.Key].dicCIAvna.ContainsKey(i.ToString()))
                                    dicGridModel[k.Key].dicCIAvna[i.ToString()] = vnaPM;
                                else
                                    dicGridModel[k.Key].dicCIAvna.Add(i.ToString(), vnaPM);
                                if (dicGridModel[k.Key].dicCIAevna.ContainsKey(i.ToString()))
                                    dicGridModel[k.Key].dicCIAevna[i.ToString()] = gvnaPM;
                                else
                                    dicGridModel[k.Key].dicCIAevna.Add(i.ToString(), gvnaPM);
                            }
                        }
                        #endregion
                        fsoutStringPM.Clear();
                        #endregion
                    }
                    _endTime = DateTime.Now;
                    CommonClass.TotalTime = Math.Round(_endTime.Subtract(_beginTime).TotalSeconds, 3);
                    CommonClass.CurrentBaseScenario.log.lstLog.Add("Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.");
                    CommonClass.CurrentLog = "Finish interpolating Spatial Field: " + CommonClass.TotalTime + " s.";

                    #endregion

                    SaveSSIADailyPMData(baseScenario, dicGridModel, dicDispersionModel, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);
                    SaveSSIAQuarterlyPMData(baseScenario, dicGridModel, dicDispersionModel, dicMaxDeltaGrid, dicMaxDeltaDispersion, dicCells);

                    Dictionary<string, PMPoint> dicDispersionModelPoint = new Dictionary<string, PMPoint>();
                    Dictionary<string, PMPoint> dicGridModelPoint = new Dictionary<string, PMPoint>();
                    Dictionary<string, Monitors> dicDispersionHighDaysDaily = new Dictionary<string, Monitors>();
                    Dictionary<string, Monitors> dicGridHighDaysDaily = new Dictionary<string, Monitors>();
                    foreach (var item in dicDailyPoint)
                    {
                        if (dicGridModel.ContainsKey(item.Value.monitorGridcell))
                        {
                            dicGridModelPoint.Add(item.Key, item.Value);
                            dicGridHighDaysDaily.Add(item.Key, dicHighDaysDaily[item.Key]);
                        }
                        else
                        {
                            dicDispersionModelPoint.Add(item.Key, item.Value);
                            dicDispersionHighDaysDaily.Add(item.Key, dicHighDaysDaily[item.Key]);
                        }
                    }
                    SaveDailyPmPoint(CommonClass.CurrentBaseScenario, dicDispersionModelPoint, "Dispersion");
                    SaveDailyPmPoint(CommonClass.CurrentBaseScenario, dicGridModelPoint, "Grid");
                    SaveDailyPmPoint(CommonClass.CurrentBaseScenario, dicDailyPoint, "Combined");
                    SaveQuarterPMPoint(CommonClass.CurrentBaseScenario, dicDispersionHighDaysDaily, "Dispersion");
                    SaveQuarterPMPoint(CommonClass.CurrentBaseScenario, dicGridHighDaysDaily, "Grid");
                    SaveQuarterPMPoint(CommonClass.CurrentBaseScenario, dicHighDaysDaily, "Combined");



                }



                #region 调整lstoutput顺序
                List<BaseOutput> lstNew = new List<BaseOutput>();
                List<BaseOutput> bo = new List<BaseOutput>();
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Combined Daily PM Receptor")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Combined Daily PM Point")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Combined Quarterly PM Receptor")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Combined Quarterly PM Point")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Dispersion Daily PM Receptor")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Dispersion Daily PM Point")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Dispersion Quarterly PM Receptor")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Dispersion Quarterly PM Point")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Grid Daily PM Data")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Grid Daily PM Point")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Grid Quarterly PM Data")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Grid Quarterly PM Point")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                bo = baseScenario.lstOutput.Where(q => q.outputName.Substring(SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName.Length).Contains("SSIA Source Location")).ToList();
                if (bo.Count > 0) lstNew.Add(bo.First());
                baseScenario.lstOutput = lstNew;
                #endregion

                dicGridModel.Clear();
                dicDispersionModel.Clear();
                GC.Collect();

                lstDailyPointPeriod.Clear();
                GC.Collect();
                


                #endregion
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        
        #region get files from csv
        public static string GetDispersionModelData(SSIADailyPMAnalysisConfiguration ssiadailypmanalysisconfiguration, ref Dictionary<string, DailyModelMonitor> dicDispersionModel,Dictionary<string, DailyModelMonitor> dicGridModel ,ref Dictionary<string,Dictionary<int, ModelDataSpecies>> dicMaxDelta)
        {
            try
            {
                Dictionary<string, DailyModelMonitor> dicAERMODModel = new Dictionary<string, DailyModelMonitor>();
                Dictionary<string,string> dicAERMODID=new Dictionary<string,string>();
                int id = 0;
                if (dicGridModel.Count != 0) id = Convert.ToInt32(dicGridModel.Keys.Max(p => Convert.ToInt32(p)));


                FileStream fs = new FileStream(ssiadailypmanalysisconfiguration.modelInputD.dispersionFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                StreamReader sr = new StreamReader(fs, System.Text.Encoding.UTF8);
                try
                {
                    string sLine = "";
                    while (sLine != null)
                    {
                        sLine = sr.ReadLine();
                        if (!string.IsNullOrEmpty(sLine) && sLine.Substring(0, 1) != "*")
                        {
                            sLine = sLine.Trim();
                            sLine = System.Text.RegularExpressions.Regex.Replace(sLine, "\\s+", " ");
                            string[] strs = System.Text.RegularExpressions.Regex.Split(sLine, " ");

                            if (!dicAERMODID.Keys.Contains(strs[0] + ',' + strs[1]))
                            {
                                DailyModelMonitor data = new DailyModelMonitor();
                                data.id = (++id).ToString();
                                data.longitudeUTM = Convert.ToDouble(strs[0])/100;
                                data.latitudeUTM = Convert.ToDouble(strs[1])/100;

                                data.dicFutureSpecies = new Dictionary<string, ModelDataSpecies>();
                                data.dicFutureDailySpecies = new Dictionary<string, Dictionary<string, ModelDataSpecies>>();
                                data.dicFutureDailySpecies.Add("all", new Dictionary<string, ModelDataSpecies>());
                                data.dicBaseSpecies = new Dictionary<string, ModelDataSpecies>();
                                data.dicCIAevna = new Dictionary<string, double>();
                                data.dicCIAvna = new Dictionary<string, double>();

                                dicAERMODModel.Add(id.ToString(), data);

                                dicAERMODID.Add(strs[0] + ',' + strs[1], id.ToString());
                            }
                            string currentID = dicAERMODID[strs[0] + ',' + strs[1]];

                            ModelDataSpecies species = new ModelDataSpecies();
                            species.pm25 = Convert.ToSingle(strs[2]);
                            species.pm25sec = 0;
                            species.pm25prim = Convert.ToSingle(strs[2]);
                            dicAERMODModel[currentID].dicFutureDailySpecies["all"].Add(strs[8], species);

                        }
                    }

                    //---------计算quarterly peak model data--------------
                    double startPercentage = Convert.ToDouble(ssiadailypmanalysisconfiguration.calculationOption.startPercentage) * 0.01;
                    double endPercentage = Convert.ToDouble(ssiadailypmanalysisconfiguration.calculationOption.endPercentage) * 0.01;
                    dicMaxDelta = new Dictionary<string, Dictionary<int, ModelDataSpecies>>();
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicAERMODModel)
                    {
                        int startCount = Convert.ToInt32(Math.Floor((k.Value.dicFutureDailySpecies["all"].Where(q => q.Value.pm25 > 0).ToList().Count - 1) * startPercentage));
                        int endCount = Convert.ToInt32(Math.Ceiling((k.Value.dicFutureDailySpecies["all"].Where(q => q.Value.pm25 > 0).ToList().Count - 1) * endPercentage));
                        List<KeyValuePair<string, ModelDataSpecies>> lstTemp = k.Value.dicFutureDailySpecies["all"].OrderBy(p => p.Value.pm25).Where(q => q.Value.pm25 > 0).Select(p => p).ToList().GetRange(startCount, 1 + endCount - startCount);

                        //all data average ranged from ("start","end")
                        List<ModelDataSpecies> optSpecies = lstTemp.Select(p => p.Value).ToList();
                        ModelDataSpecies Alt = new ModelDataSpecies();
                        Alt.pm25 = optSpecies.Average(p => p.pm25);
                        Alt.pm25prim = optSpecies.Average(p => p.pm25prim);
                        k.Value.dicFutureSpecies.Add("0", Alt);
                        dicMaxDelta.Add(k.Key, new Dictionary<int, ModelDataSpecies>());
                        //alt quarterly data
                        for (int i = 1; i < 5; i++)
                        {
                            int maxMonth = 3 * i;
                            ModelDataSpecies quarterlispecies = new ModelDataSpecies();
                            List<ModelDataSpecies> optQuarter = k.Value.dicFutureDailySpecies["all"].Where(p => Convert.ToInt16(p.Key.Substring(2, 2)) <= maxMonth && Convert.ToInt16(p.Key.Substring(2, 2)) > maxMonth - 3).Where(q => q.Value.pm25 > 0).Select(p => p.Value).ToList();
                            quarterlispecies.pm25 = optQuarter.Average(p => p.pm25);
                            quarterlispecies.pm25prim = optQuarter.Average(p => p.pm25prim);
                            k.Value.dicFutureSpecies.Add(i.ToString(), quarterlispecies);


                        }
                        //dicMaxDelta.Add(k.Key, new ModelDataSpecies());
                        foreach (KeyValuePair<string, ModelDataSpecies> kin in k.Value.dicFutureDailySpecies["all"])
                        {
                            int iQuarter = Convert.ToInt16(kin.Key.Substring(2, 2))/3+1;
                            if (dicMaxDelta[k.Key].ContainsKey(iQuarter))
                            {
                                if (dicMaxDelta[k.Key][iQuarter].pm25 < kin.Value.pm25) dicMaxDelta[k.Key][iQuarter].pm25 = kin.Value.pm25;
                                if (dicMaxDelta[k.Key][iQuarter].pm25sec < kin.Value.pm25sec) dicMaxDelta[k.Key][iQuarter].pm25 = kin.Value.pm25sec;
                                if (dicMaxDelta[k.Key][iQuarter].pm25prim < kin.Value.pm25prim) dicMaxDelta[k.Key][iQuarter].pm25prim = kin.Value.pm25prim;
                            }
                            else
                            {
                                dicMaxDelta[k.Key].Add(iQuarter, new ModelDataSpecies() { pm25 = kin.Value.pm25, pm25prim = kin.Value.pm25prim, pm25sec = kin.Value.pm25sec });
                            }                            
                        }
                        //foreach (KeyValuePair<string, ModelDataSpecies> kin in k.Value.dicFutureDailySpecies["all"])
                        foreach (KeyValuePair<string, ModelDataSpecies> kin in lstTemp)
                        {
                            if (dicMaxDelta[k.Key].ContainsKey(9))
                            {
                                if (dicMaxDelta[k.Key][9].pm25 < kin.Value.pm25) dicMaxDelta[k.Key][9].pm25 = kin.Value.pm25;
                                if (dicMaxDelta[k.Key][9].pm25sec < kin.Value.pm25sec) dicMaxDelta[k.Key][9].pm25 = kin.Value.pm25sec;
                                if (dicMaxDelta[k.Key][9].pm25prim < kin.Value.pm25prim) dicMaxDelta[k.Key][9].pm25prim = kin.Value.pm25prim;
                            }
                            else
                            {
                                dicMaxDelta[k.Key].Add(9, new ModelDataSpecies() { pm25 = kin.Value.pm25, pm25prim = kin.Value.pm25prim, pm25sec = kin.Value.pm25sec });
                            }
                        }
                        k.Value.dicFutureDailySpecies.Clear();
                        
                        #region Set "Base" to zero
                        for (int i = 0; i < 5; i++)
                        {
                            ModelDataSpecies zerospecies = new ModelDataSpecies();
                            zerospecies.pm25 = 0;
                            zerospecies.pm25sec = 0;
                            zerospecies.pm25prim = 0;
                            k.Value.dicBaseSpecies.Add(i.ToString(), zerospecies);
                        }
                        #endregion

                        dicDispersionModel.Add(k.Key, k.Value);
                    }
                }
                catch
                {
                    return "wrong";
                }
                sr.Close();
                fs.Close();
                GC.Collect();
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "wrong";
            }
        }
        

        public static string GetModelDataDailyBaseline(SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration, ref Dictionary<string, DailyModelMonitor> dicQuarterlyPeakModel, ref  bool isSalt, ref string baseYear, ref 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,iPMsec=-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(SSIAdailyPMAnalysisConfiguration.modelInputD.baselineModelDataFile, 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;
                            case "pm25sec":
                                iPMsec = i;
                                break;
                        }
                        i++;
                    }
                    #endregion
                    if (iSalt != -1) isSalt = true;
                    while (strLine != null)
                    {
                        Dictionary<string, ModelDataSpecies> dicDailySpecies = new Dictionary<string, ModelDataSpecies>();
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        strLineArray = strLine.Replace(" ","").Split(new char[] { ',' });
                        if (baseYear == "") baseYear = strLineArray[iDate].ToString().Replace("\"", "").Substring(0, 4);                            
                        #region old
                        //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;
                        //}
                        #endregion
                        
                        #region put all data in Dictionary(dicQuarterlyPeakModel)

                        ModelDataSpecies species = new ModelDataSpecies();
                        species.pm25 = Convert.ToSingle(strLineArray[iPM25]);
                        species.oc = Convert.ToSingle(strLineArray[iOC]);
                        species.no3 = Convert.ToSingle(strLineArray[iNO3]);
                        species.nh4 = Convert.ToSingle(strLineArray[iNH4]);
                        species.ec = Convert.ToSingle(strLineArray[iEC]);
                        species.crustal = Convert.ToSingle(strLineArray[iCrustal]);
                        species.cm = Convert.ToSingle(strLineArray[iCM]);
                        species.so4 = Convert.ToSingle(strLineArray[iSO4]);
                        species.pm25sec = Convert.ToSingle(strLineArray[iPMsec]);                        

                        if(dicQuarterlyPeakModel.Keys.Contains(strLineArray[iID]))
                        {
                            dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies["all"].Add(strLineArray[iDate], species);                            
                        }
                        else
                        {
                            dicQuarterlyPeakModel.Add(strLineArray[iID],new DailyModelMonitor());
                            dicQuarterlyPeakModel[strLineArray[iID]].id=strLineArray[iID];                            
                            dicQuarterlyPeakModel[strLineArray[iID]].lat=Convert.ToDouble(strLineArray[iLat]);
                            dicQuarterlyPeakModel[strLineArray[iID]].longitude = Convert.ToDouble(strLineArray[iLong]);
                            dicQuarterlyPeakModel[strLineArray[iID]].type = strLineArray[iType];
                            dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies = new Dictionary<string, Dictionary<string, ModelDataSpecies>>();
                            dicQuarterlyPeakModel[strLineArray[iID]].dicBaseSpecies = new Dictionary<string, ModelDataSpecies>();
                            dicQuarterlyPeakModel[strLineArray[iID]].dicFutureDailySpecies = new Dictionary<string, Dictionary<string, ModelDataSpecies>>();
                            dicQuarterlyPeakModel[strLineArray[iID]].dicFutureSpecies = new Dictionary<string, ModelDataSpecies>();

                            dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.Add("all", new Dictionary<string, ModelDataSpecies>());
                            dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies["all"].Add(strLineArray[iDate], species);
                            dicQuarterlyPeakModel[strLineArray[iID]].dicFutureDailySpecies.Add("all", new Dictionary<string, ModelDataSpecies>());
                            dicQuarterlyPeakModel[strLineArray[iID]].dicCIAevna = new Dictionary<string, double>();
                            dicQuarterlyPeakModel[strLineArray[iID]].dicCIAvna = new Dictionary<string, double>();
                        }
                        #region old
                        //if (SSIAdailyPMAnalysisConfiguration.modelInputD.RRF_DoUseXTopPercent)
                        //{
                        //    #region
                        //    int topXpercentCount = Convert.ToInt32(Math.Round(Convert.ToDouble(92 * 0.01 * SSIAdailyPMAnalysisConfiguration.modelInputD.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 (SSIAdailyPMAnalysisConfiguration.modelInputD.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 < SSIAdailyPMAnalysisConfiguration.modelInputD.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 < SSIAdailyPMAnalysisConfiguration.modelInputD.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 (SSIAdailyPMAnalysisConfiguration.modelInputD.RRF_DoUseAllModelDaysGreaterThan)
                        //{
                        //    #region
                        //    if (Convert.ToSingle(strLineArray[iPM25]) < SSIAdailyPMAnalysisConfiguration.modelInputD.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
                        #endregion 
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }

                //---------计算quarterly peak model data--------------
                double startPercentage = Convert.ToDouble(SSIAdailyPMAnalysisConfiguration.calculationOption.startPercentage) * 0.01;
                double endPercentage = Convert.ToDouble(SSIAdailyPMAnalysisConfiguration.calculationOption.endPercentage) * 0.01;


                foreach (KeyValuePair<string, DailyModelMonitor> k in dicQuarterlyPeakModel)
                {
                    int startCount = Convert.ToInt32(Math.Floor((k.Value.dicBaseDailySpecies["all"].Where(q => q.Value.pm25 > 0).ToList().Count - 1) * startPercentage));
                    int endCount = Convert.ToInt32(Math.Ceiling((k.Value.dicBaseDailySpecies["all"].Where(q => q.Value.pm25 > 0).ToList().Count - 1) * endPercentage));
                    List<KeyValuePair<string, ModelDataSpecies>> lstTemp = k.Value.dicBaseDailySpecies["all"].OrderBy(p => p.Value.pm25).Where(q => q.Value.pm25 > 0).Select(p => p).ToList().GetRange(startCount, 1 + endCount - startCount);

                    //save the id & date of the selected data for calculating alt model data
                    List<string> lstDate = lstTemp.Select(p => p.Key).ToList();

                    //dicBaseDays --- Selected Days
                    dicBaseDays.Add(k.Key, lstDate);

                    //all data average ranged from ("start","end")
                    List<ModelDataSpecies> optSpecies = lstTemp.Select(p => p.Value).ToList();
                    ModelDataSpecies baseline = new ModelDataSpecies();
                    baseline.pm25 = optSpecies.Average(p => p.pm25);
                    baseline.oc = optSpecies.Average(p => p.oc);
                    baseline.no3 = optSpecies.Average(p => p.no3);
                    baseline.nh4 = optSpecies.Average(p => p.nh4);
                    baseline.ec = optSpecies.Average(p => p.ec);
                    baseline.cm = optSpecies.Average(p => p.cm);
                    baseline.crustal = optSpecies.Average(p => p.crustal);
                    baseline.so4 = optSpecies.Average(p => p.so4);
                    baseline.pm25sec = optSpecies.Average(p => p.pm25sec);
                    baseline.pm25prim = baseline.pm25 - baseline.pm25sec;

                    //Save the average data in ...
                    k.Value.dicBaseSpecies.Add("0", baseline);

                    //quarterly data
                    for (int i = 1; i < 5; i++)
                    {
                        int maxMonth = 3 * i;
                        ModelDataSpecies quarterlispecies = new ModelDataSpecies();
                        List<ModelDataSpecies> optQuarter = k.Value.dicBaseDailySpecies["all"].Where(p => Convert.ToInt16(p.Key.Substring(4, 2)) <= maxMonth && Convert.ToInt16(p.Key.Substring(4, 2)) > maxMonth - 3).Where(q => q.Value.pm25 > 0).Select(p => p.Value).ToList();
                        quarterlispecies.pm25 = optQuarter.Average(p => p.pm25);
                        quarterlispecies.oc = optQuarter.Average(p => p.oc);
                        quarterlispecies.no3 = optQuarter.Average(p => p.no3);
                        quarterlispecies.nh4 = optQuarter.Average(p => p.nh4);
                        quarterlispecies.ec = optQuarter.Average(p => p.ec);
                        quarterlispecies.cm = optQuarter.Average(p => p.cm);
                        quarterlispecies.crustal = optQuarter.Average(p => p.crustal);
                        quarterlispecies.so4 = optQuarter.Average(p => p.so4);
                        quarterlispecies.pm25sec = optQuarter.Average(p => p.pm25sec);
                        quarterlispecies.pm25prim = quarterlispecies.pm25 - baseline.pm25sec;
                        k.Value.dicBaseSpecies.Add(i.ToString(), quarterlispecies);

                    }
                    //k.Value.dicBaseDailySpecies.Clear();                    
                    #region old
                    //if (SSIAdailyPMAnalysisConfiguration.modelInputD.RRF_DoUseAllModelDaysGreaterThan)
                    //{
                    //    #region
                    //    foreach (KeyValuePair<string, ModelDataSpecies> kQ in k.Value.dicBaseSpecies)
                    //    {
                    //        if (dicDayCount[k.Key][kQ.Key] < SSIAdailyPMAnalysisConfiguration.modelInputD.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 (SSIAdailyPMAnalysisConfiguration.modelInputD.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 * SSIAdailyPMAnalysisConfiguration.modelInputD.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 (SSIAdailyPMAnalysisConfiguration.modelInputD.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;
                    //}
                    #endregion 
                }
                //dicDayCount.Clear();
                GC.Collect();
                #endregion
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        public static string GetModelDataDailyFuture(SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration, ref Dictionary<string, DailyModelMonitor> dicQuarterlyPeakModel, ref  bool isSalt, ref string futureYear, Dictionary<string, List<string>> dicBaseDays, ref Dictionary<string, Dictionary<int, ModelDataSpecies>> dicMaxDelta)
        {
            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, iPMsec = -1;

                foreach (KeyValuePair<string, DailyModelMonitor> k in dicQuarterlyPeakModel)
                {
                    dicMaxDelta.Add(k.Key, null);
                }
                //string quarter = "";
                FileStream fs = new FileStream(SSIAdailyPMAnalysisConfiguration.modelInputD.alternativeScenarioFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                Dictionary<string,List<ModelDataSpecies>> dicOptSpecies = new Dictionary<string,List<ModelDataSpecies>>();//

                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;
                            case "pm25sec":
                                iPMsec = i;
                                break;
                        }
                        i++;
                    }
                    #endregion
                    while (strLine != null)
                    {
                        strLine = csv.ReadLine();
                        if (strLine == null) break;
                        strLineArray = strLine.Replace(" ","").Split(new char[] { ',' });
                        if (futureYear == "") futureYear = strLineArray[iDate].ToString().Substring(0, 4).Replace("\"", "");
                        #region old
                        //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;
                        //}
                        #endregion

                        ModelDataSpecies species = new ModelDataSpecies();
                        species.pm25 = Convert.ToSingle(strLineArray[iPM25]);
                        species.oc = Convert.ToSingle(strLineArray[iOC]);
                        species.no3 = Convert.ToSingle(strLineArray[iNO3]);
                        species.nh4 = Convert.ToSingle(strLineArray[iNH4]);
                        species.ec = Convert.ToSingle(strLineArray[iEC]);
                        species.crustal = Convert.ToSingle(strLineArray[iCrustal]);
                        species.cm = Convert.ToSingle(strLineArray[iCM]);
                        species.so4 = Convert.ToSingle(strLineArray[iSO4]);
                        species.pm25sec = Convert.ToSingle(strLineArray[iPMsec]);

                        dicQuarterlyPeakModel[strLineArray[iID]].dicFutureDailySpecies["all"].Add(strLineArray[iDate], species);

                        //--------------------------------------------------------------计算Quartly MaxDelta和 Annual MaxDelta------------------------------------------------------------------
                        float d_pm25 = species.pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25;
                        float d_pm25sec = species.pm25sec - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25sec;
                        float d_pm25prim = (species.pm25 - species.pm25sec) - (dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25sec);

                        int Quarter = Convert.ToInt16(Math.Ceiling(Convert.ToDouble(strLineArray[iDate].Substring(4, 2)) / 3));

                        if (dicMaxDelta[strLineArray[iID]] == null)
                        {
                            try
                            {
                                dicMaxDelta[strLineArray[iID]] =  new Dictionary<int,ModelDataSpecies>();

                                //Quartly Max Delta
                                dicMaxDelta[strLineArray[iID]].Add(Quarter, new ModelDataSpecies());
                                dicMaxDelta[strLineArray[iID]][Quarter].pm25 = d_pm25;
                                dicMaxDelta[strLineArray[iID]][Quarter].pm25sec = d_pm25sec;
                                dicMaxDelta[strLineArray[iID]][Quarter].pm25prim = d_pm25prim;

                                //Annual Max Delta
                                dicMaxDelta[strLineArray[iID]].Add(9, new ModelDataSpecies());
                                dicMaxDelta[strLineArray[iID]][9].pm25 = d_pm25;
                                dicMaxDelta[strLineArray[iID]][9].pm25sec = d_pm25sec;
                                dicMaxDelta[strLineArray[iID]][9].pm25prim = d_pm25prim;
                            }
                            catch
                            {
                                dicMaxDelta[strLineArray[iID]] = null;
                            }
                        }
                        else
                        {
                            //Quartly  Max Delta              
                            if (dicMaxDelta[strLineArray[iID]].ContainsKey(Quarter))
                            {
                                if (d_pm25 > dicMaxDelta[strLineArray[iID]][Quarter].pm25)
                                    dicMaxDelta[strLineArray[iID]][Quarter].pm25 = d_pm25;
                                if (d_pm25sec > dicMaxDelta[strLineArray[iID]][Quarter].pm25sec)
                                    dicMaxDelta[strLineArray[iID]][Quarter].pm25sec = d_pm25sec;
                                if (d_pm25prim > dicMaxDelta[strLineArray[iID]][Quarter].pm25prim)
                                    dicMaxDelta[strLineArray[iID]][Quarter].pm25prim = d_pm25prim;
                            }
                            else
                            {
                                dicMaxDelta[strLineArray[iID]].Add(Quarter, new ModelDataSpecies());
                                dicMaxDelta[strLineArray[iID]][Quarter].pm25 = d_pm25;
                                dicMaxDelta[strLineArray[iID]][Quarter].pm25sec = d_pm25sec;
                                dicMaxDelta[strLineArray[iID]][Quarter].pm25prim = d_pm25prim; 
                            }

                            //Annual Max Delta                
                            if (dicMaxDelta[strLineArray[iID]].ContainsKey(9))
                            {
                                if (d_pm25 > dicMaxDelta[strLineArray[iID]][9].pm25)
                                    dicMaxDelta[strLineArray[iID]][9].pm25 = d_pm25;
                                if (d_pm25sec > dicMaxDelta[strLineArray[iID]][9].pm25sec)
                                    dicMaxDelta[strLineArray[iID]][9].pm25sec = d_pm25sec;
                                if (d_pm25prim > dicMaxDelta[strLineArray[iID]][9].pm25prim)
                                    dicMaxDelta[strLineArray[iID]][9].pm25prim = d_pm25prim;

                            }
                            else
                            {
                                dicMaxDelta[strLineArray[iID]].Add(9, new ModelDataSpecies());
                                dicMaxDelta[strLineArray[iID]][9].pm25 = d_pm25;
                                dicMaxDelta[strLineArray[iID]][9].pm25sec = d_pm25sec;
                                dicMaxDelta[strLineArray[iID]][9].pm25prim = d_pm25prim;
                            }
                            
                        }
                        if (dicBaseDays[strLineArray[iID]].Contains(strLineArray[iDate]))
                        {
                            if (!dicOptSpecies.Keys.Contains(strLineArray[iID])) dicOptSpecies.Add(strLineArray[iID], new List<ModelDataSpecies>());
                            dicOptSpecies[strLineArray[iID]].Add(species);

                            #region Max Delta in Selected Region (95%-98%)
                            //if (dicMaxDelta[strLineArray[iID]] == null)
                            //{
                            //    dicMaxDelta[strLineArray[iID]] = new Dictionary<int, ModelDataSpecies>();
                            //    dicMaxDelta[strLineArray[iID]].Add(9, new ModelDataSpecies());
                            //    dicMaxDelta[strLineArray[iID]][9].pm25 = species.pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25;
                            //    dicMaxDelta[strLineArray[iID]][9].pm25sec = species.pm25sec - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25sec;
                            //    dicMaxDelta[strLineArray[iID]][9].pm25prim = (species.pm25 - species.pm25sec) - (dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25sec);

                            //}
                            //else
                            //{
                            //    float d2 = species.pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25;

                            //    if (dicMaxDelta[strLineArray[iID]].ContainsKey(9))
                            //    {
                            //        if (d2 > dicMaxDelta[strLineArray[iID]][9].pm25) dicMaxDelta[strLineArray[iID]][9].pm25 = d2;// species.pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25;
                            //        d2 = species.pm25sec - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25sec;
                            //        if (d2 > dicMaxDelta[strLineArray[iID]][9].pm25sec) dicMaxDelta[strLineArray[iID]][9].pm25sec = d2;// species.pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25;

                            //        d2 = (species.pm25 - species.pm25sec) - (dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25sec);
                            //        if (d2 > dicMaxDelta[strLineArray[iID]][9].pm25prim) dicMaxDelta[strLineArray[iID]][9].pm25prim = d2;// species.pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25;

                            //    }
                            //    else
                            //    {
                            //        dicMaxDelta[strLineArray[iID]].Add(9, new ModelDataSpecies());
                            //        dicMaxDelta[strLineArray[iID]][9].pm25 = species.pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25;
                            //        dicMaxDelta[strLineArray[iID]][9].pm25sec = species.pm25sec - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25sec;
                            //        dicMaxDelta[strLineArray[iID]][9].pm25prim = (species.pm25 - species.pm25sec) - (dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25 - dicQuarterlyPeakModel[strLineArray[iID]].dicBaseDailySpecies.First().Value[strLineArray[iDate].ToString()].pm25sec);


                             //   }

                            //}
                        #endregion
                        }
                        #region old
                        //if (SSIAdailyPMAnalysisConfiguration.modelInputD.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 (SSIAdailyPMAnalysisConfiguration.modelInputD.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 (SSIAdailyPMAnalysisConfiguration.modelInputD.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
                        //}
                        #endregion
                        //--------------------------------------------------------------计算Quartly MaxDelta和 Annual MaxDelta   End ----------------------------------------------------------------
                    }
                    csv.Dispose(); fs.Dispose();
                    GC.Collect();
                }
                //---------计算quarterly peak model data--------------
                
                foreach (KeyValuePair<string, DailyModelMonitor> k in dicQuarterlyPeakModel)
                {
                    //all data average ranged from ("start","end")
                    ModelDataSpecies alt = new ModelDataSpecies();
                    alt.pm25 = dicOptSpecies[k.Key].Average(p => p.pm25);
                    alt.oc = dicOptSpecies[k.Key].Average(p => p.oc);
                    alt.no3 =  dicOptSpecies[k.Key].Average(p => p.no3);
                    alt.nh4 =  dicOptSpecies[k.Key].Average(p => p.nh4);
                    alt.ec = dicOptSpecies[k.Key].Average(p => p.ec);
                    alt.crustal =  dicOptSpecies[k.Key].Average(p => p.crustal);;
                    alt.cm = dicOptSpecies[k.Key].Average(p => p.cm);
                    alt.so4 = dicOptSpecies[k.Key].Average(p => p.so4);
                    alt.pm25sec = dicOptSpecies[k.Key].Average(p => p.pm25sec);
                    alt.pm25prim = alt.pm25 - alt.pm25sec;

                    k.Value.dicFutureSpecies.Add("0", alt);

                    //quarterly
                    for (int i = 1; i < 5; i++)
                    {
                        int maxMonth = 3 * i;
                        ModelDataSpecies quarterlyspecies = new ModelDataSpecies();
                        List<ModelDataSpecies> optSpecies2 = k.Value.dicFutureDailySpecies["all"].Where(p => Convert.ToInt16(p.Key.Substring(4, 2)) <= maxMonth && Convert.ToInt16(p.Key.Substring(4, 2)) > maxMonth - 3).Where(q => q.Value.pm25 > 0).Select(p => p.Value).ToList();
                        quarterlyspecies.pm25 = optSpecies2.Average(p => p.pm25);
                        quarterlyspecies.oc = optSpecies2.Average(p => p.oc);
                        quarterlyspecies.no3 = optSpecies2.Average(p => p.no3);
                        quarterlyspecies.nh4 = optSpecies2.Average(p => p.nh4);
                        quarterlyspecies.ec = optSpecies2.Average(p => p.ec);
                        quarterlyspecies.cm = optSpecies2.Average(p => p.cm);
                        quarterlyspecies.crustal = optSpecies2.Average(p => p.crustal);
                        quarterlyspecies.so4 = optSpecies2.Average(p => p.so4);
                        quarterlyspecies.pm25sec = optSpecies2.Average(p => p.pm25sec);
                        quarterlyspecies.pm25prim = quarterlyspecies.pm25 - quarterlyspecies.pm25sec;

                        k.Value.dicFutureSpecies.Add(i.ToString(), quarterlyspecies);
                    }
                    //k.Value.dicFutureDailySpecies.Clear();
                    #region old
                    //if (SSIAdailyPMAnalysisConfiguration.modelInputD.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 (SSIAdailyPMAnalysisConfiguration.modelInputD.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 (SSIAdailyPMAnalysisConfiguration.modelInputD.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
                    //}
                    #endregion
                }
                dicBaseDays.Clear();

                GC.Collect();
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "unknow";
            }
        }

        public static string GetModelDataQuarterly(SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration, 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(SSIAdailyPMAnalysisConfiguration.modelInputD.baselineModelDataFile, 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(SSIAdailyPMAnalysisConfiguration.modelInputD.alternativeScenarioFile) + "\".";
                CommonClass.CurrentBaseScenario.log.lstLog.Add(CommonClass.CurrentLog);

                //---------future model data---------------
                #region future quarterly peak model data
                fs = new FileStream(SSIAdailyPMAnalysisConfiguration.modelInputD.alternativeScenarioFile, 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(SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration)
        {
            try
            {
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }


        public static string GetOfficialPM(SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration, 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;
                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(SSIAdailyPMAnalysisConfiguration.monitorInputD.officialMonitorDataFile, 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;
                        strLineArray = strLine.Replace("\"","").Split(',');
                        int startyear= Convert.ToInt32(SSIAdailyPMAnalysisConfiguration.monitorInputD.monitorDataStartYear);
                        int endyear=Convert.ToInt32(SSIAdailyPMAnalysisConfiguration.monitorInputD.monitorDataEndYear);
                        if (Convert.ToInt32(strLineArray[iDate].Substring(0, 4)) >= startyear && Convert.ToInt32(strLineArray[iDate].Substring(0, 4)) <= endyear && Convert.ToInt32(strLineArray[iEPA]) == 0)
                        {
                            quarter = "";
                            if (strLineArray[iID] == id && strLineArray[iDate].Substring(0, 4) == date && strLineArray[iType] == type)
                            {
                                #region
                                pmMonitors = new PM25Monitors();
                                switch (strLineArray[iDate].Substring(4, 2))
                                {
                                    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], pmMonitors);
                                        }
                                        else
                                        {
                                            dicPM1 = new Dictionary<string, PM25Monitors>();
                                            dicPM1.Add(strLineArray[iDate], 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], pmMonitors);
                                        }
                                        else
                                        {
                                            dicPM2 = new Dictionary<string, PM25Monitors>();
                                            dicPM2.Add(strLineArray[iDate], 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], pmMonitors);
                                        }
                                        else
                                        {
                                            dicPM3 = new Dictionary<string, PM25Monitors>();
                                            dicPM3.Add(strLineArray[iDate], 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], pmMonitors);
                                        }
                                        else
                                        {
                                            dicPM4 = new Dictionary<string, PM25Monitors>();
                                            dicPM4.Add(strLineArray[iDate], 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] != 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];
                                type = strLineArray[iType];
                                date = strLineArray[iDate].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],
                                        countyName = strLineArray[iCountyName],
                                        rank98 = Convert.ToInt32(strLineArray[iRank98]),
                                        dicOfficialPM25Daily = new Dictionary<string, Dictionary<string, Dictionary<string, PM25Monitors>>>(),
                                    });
                                }
                                pmMonitors = new PM25Monitors();
                                switch (strLineArray[iDate].Substring(4, 2))
                                {
                                    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], pmMonitors);
                                        }
                                        else
                                        {
                                            dicPM1 = new Dictionary<string, PM25Monitors>();
                                            dicPM1.Add(strLineArray[iDate], 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], pmMonitors);
                                        }
                                        else
                                        {
                                            dicPM2 = new Dictionary<string, PM25Monitors>();
                                            dicPM2.Add(strLineArray[iDate], 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], pmMonitors);
                                        }
                                        else
                                        {
                                            dicPM3 = new Dictionary<string, PM25Monitors>();
                                            dicPM3.Add(strLineArray[iDate], 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], pmMonitors);
                                        }
                                        else
                                        {
                                            dicPM4 = new Dictionary<string, PM25Monitors>();
                                            dicPM4.Add(strLineArray[iDate], pmMonitors);
                                            dicQYpm4.Add(date, dicPM4);
                                        }
                                        break;
                                }
                                count++;
                                #endregion
                            }
                        }                        
                    }
                    #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> dicGridModel, Dictionary<string, DailyModelMonitor> dicDispersionModel, ref Dictionary<string, Monitors> dicOfficialPMDaily)
        {
            try
            {
                if(dicGridModel==null)//dispersion only
                {
                    double dLon = 0, dLat = 0;
                    //int iFirst = Convert.ToInt32(dicModelDataPM.First().Key);
                    //int iLast = Convert.ToInt32(dicModelDataPM.Last().Key);
                    //dLon = Math.Abs(dicModelDataPM[iFirst.ToString()].longitudeLamber - dicModelDataPM[iLast.ToString()].longitudeLamber) / Math.Abs(iFirst / 1000 - iLast / 1000) * 5;//要看aermod网格怎么排列，这个是最外围的网格的最大距离
                    //dLat = Math.Abs(dicModelDataPM[iFirst.ToString()].latitudeLamber - dicModelDataPM[iLast.ToString()].latitudeLamber) / Math.Abs(iFirst % 1000 - iLast % 1000) * 5;
                    List<double> lstLat = dicDispersionModel.Select(q => q.Value.latitudeUTM).ToList();
                    List<double> lstLon = dicDispersionModel.Select(q => q.Value.longitudeUTM).ToList();
                    lstLat.Sort();
                    lstLon.Sort();
                    for (int i = 0; i < lstLat.Count - 1; i++)
                    {
                        dLat = Math.Max(dLat, lstLat[i + 1] - lstLat[i]);
                    }
                    for (int i = 0; i < lstLon.Count - 1; i++)
                    {
                        dLon = Math.Max(dLat, lstLon[i + 1] - lstLon[i]);
                    }
                    dLat = dLat / 2;
                    dLon = dLon / 2;
                    lstLat.Clear();
                    lstLon.Clear();

                    foreach (KeyValuePair<string, Monitors> k in dicOfficialPMDaily)
                    {
                        try
                        {
                            var query = dicDispersionModel.Where(p => Math.Abs(p.Value.longitudeUTM - k.Value.longitudeUTM) < dLon && Math.Abs(p.Value.latitudeUTM - k.Value.latitudeUTM) < dLat).ToList();
                            string sModelIDTemp = "";
                            if (query.Count() > 0)
                            {
                                DotSpatial.Topology.Coordinate coor = new DotSpatial.Topology.Coordinate(k.Value.longitudeUTM, k.Value.latitudeUTM);
                                sModelIDTemp = query.OrderBy(p => Math.Pow(p.Value.longitudeUTM - k.Value.longitudeUTM, 2) + Math.Pow(p.Value.latitudeUTM - k.Value.latitudeUTM, 2)).First().Key;
                                dicOfficialMonitorInModel.Add(k.Key, sModelIDTemp);
                            }
                            else
                            {
                                sModelIDTemp = dicDispersionModel.OrderBy(p => Math.Pow(p.Value.longitudeUTM - k.Value.longitudeUTM, 2) + Math.Pow(p.Value.latitudeUTM - k.Value.latitudeUTM, 2)).First().Key;
                                //dicOfficialMonitorInModel.Add(k.Key, sModelIDTemp);//test
                            }
                            k.Value.monitorGridcell = sModelIDTemp;
                        }
                        catch
                        {
                        }
                    }
                }
                else if (dicDispersionModel == null)//grid only
                {
                    //得到monitor属于哪个网格--------简单的方法可以判断以最近的点作为它的网格。首先可以求出第一个网格的大小，在小于一倍网格宽度和长度的最大值求最近点
                    double dLon = 0, dLat = 0;
                    int iFirst = Convert.ToInt32(dicGridModel.First().Key);
                    if (dicGridModel.ContainsKey((((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()))
                    {
                        dLon = Math.Abs(dicGridModel[(((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()].longitudeLamber -
                                dicGridModel.First().Value.longitudeLamber
                                );
                        dLat = Math.Abs(dicGridModel[(((iFirst / 1000)) * 1000 + iFirst % 1000 + 1).ToString()].latitudeLamber -
                            dicGridModel.First().Value.latitudeLamber
                            );
                        dLon /= 2; dLat /= 2;
                    }

                    //---------计算两个网格之内；然后属于哪个的网格，根据距离判断属于哪个网格
                    foreach (KeyValuePair<string, Monitors> k in dicOfficialPMDaily)
                    {
                        try
                        {
                            var query = dicGridModel.Where(p => Math.Abs(p.Value.longitudeLamber - k.Value.longitudeLamber) < dLon && Math.Abs(p.Value.latitudeLamber - k.Value.latitudeLamber) < dLat).ToList();
                            string sModelIDTemp = "";
                            if (query.Count() > 0)
                            {
                                DotSpatial.Topology.Coordinate coor = new DotSpatial.Topology.Coordinate(k.Value.longitudeLamber, k.Value.latitudeLamber);
                                sModelIDTemp = query.OrderBy(p => Math.Pow(p.Value.longitudeLamber - k.Value.longitudeLamber, 2) + Math.Pow(p.Value.latitudeLamber - k.Value.latitudeLamber, 2)).First().Key;
                                dicOfficialMonitorInModel.Add(k.Key, sModelIDTemp);
                            }
                            else
                            {
                                sModelIDTemp = dicGridModel.OrderBy(p => Math.Pow(p.Value.longitudeLamber - k.Value.longitudeLamber, 2) + Math.Pow(p.Value.latitudeLamber - k.Value.latitudeLamber, 2)).First().Key;
                            }
                            k.Value.monitorGridcell = sModelIDTemp;
                        }
                        catch
                        {
                        }
                    }
                }
                else //dispersion+grid
                {
                    double dFirst = dicGridModel.First().Value.longitudeLamber, dLen = 0, dLat = 0;
                    int iFirst = Convert.ToInt32(dicGridModel.First().Key);
                    if (dicGridModel.ContainsKey((((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()))
                    {
                        dLen = Math.Abs(dicGridModel[(((iFirst / 1000) + 1) * 1000 + iFirst % 1000).ToString()].longitudeLamber -
                                dicGridModel.First().Value.longitudeLamber
                                );
                        dLat = Math.Abs(dicGridModel[(((iFirst / 1000)) * 1000 + iFirst % 1000 + 1).ToString()].latitudeLamber -
                            dicGridModel.First().Value.latitudeLamber
                            );
                        dLen *= 2; dLat *= 2;
                    }

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

        public static bool GetValidPeriods(SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration, Dictionary<string, Monitors> dicOfficialPMDaily, List<string> dicDesignValuePeriod, ref Dictionary<string, List<string>> dicValidYear, 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 = s.Split('-').Distinct().ToList();
                        int j = Convert.ToInt32(lstYearPeriod.First()) + 1;
                        while (j < Convert.ToInt32(lstYearPeriod.Last()))
                        {
                            lstYearPeriod.Insert(1, j.ToString());
                            j++;
                        }
                        lstYearPeriod.Sort();
                        if (dicComCode.Where(p => lstYearPeriod.Contains(p.Key)).ToList().Count() > 0 && dicComCode.Where(p => lstYearPeriod.Contains(p.Key)).ToList().Count == lstYearPeriod.Count)
                        {
                            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 (SSIAdailyPMAnalysisConfiguration.outputChoiceAdvancedD.doDesignValuePeriods)
                        //{
                        //    var queryComCode = dicComCode.Where(p => lstYearPeriod.Contains(p.Key)).Select(p => p.Value).ToList();
                        //    if (queryComCode.Contains(1) || queryComCode.Contains(2))
                        //    {

                        //        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 => 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() >= SSIAdailyPMAnalysisConfiguration.pm25CalculationOptionsD.minNumDVPeriodsForValidFRMMonitors)
                    if (dvNum - doDV.Where(p => p == 0).Count() >= 1)
                    {
                        //根据用户选择的dv period进行筛选
                        //if (SSIAdailyPMAnalysisConfiguration.pm25CalculationOptionsD.requiredDesignValuePeriodsForValidFRMMonitors == "None selected")
                        if(true)
                        {
                            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 = SSIAdailyPMAnalysisConfiguration.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(SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration, 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>(),
                        dicOfficialPM25Daily=new Dictionary<string,Dictionary<string,Dictionary<string,PM25Monitors>>>(),
                    });
                    foreach (var item in k.Value.dicOfficialPM25Daily)
                    {
                        dicHighDaysDaily[k.Key].dicOfficialPM25Daily.Add(item.Key,item.Value);
                    }
                    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 GetDailyPointFutureVlues(SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration, Dictionary<string, Monitors> dicHighDaysDaily, List<string> dicDesignValuePeriod, Dictionary<string, Dictionary<string, int>> dicComCodePeriod, ref Dictionary<string, PMPoint> dicDailyPoint, ref List<Dictionary<string, PMPoint>> lstDailyPointPeriod,Dictionary<string,DailyModelMonitor> dicModel)
        {
            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('-').Distinct().ToList();
                        int j = Convert.ToInt32(lstYear.First()) + 1;
                        while (j < Convert.ToInt32(lstYear.Last()))
                        {                            
                            lstYear.Insert(1,j.ToString());
                            j++;
                        }
                        //lstYear.Insert(1, (Convert.ToInt32((lstYear[0])) + 1).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(),
                            //fPM25 = query.Count() < 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 (SSIAdailyPMAnalysisConfiguration.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 (SSIAdailyPMAnalysisConfiguration.pm25CalculationOptionsD.requiredDesignValuePeriodsForValidFRMMonitors == "None selected")
                    if(true)
                    {
                        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.bPM25).Average() + dicModel[k.Key].dicFutureSpecies["0"].pm25 - dicModel[k.Key].dicBaseSpecies["0"].pm25,
                            maxDelta = dicModel[k.Key].dicMaxDeltaSpecies.First().Value.pm25,
                            //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 = SSIAdailyPMAnalysisConfiguration.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;
            }
        }

        public static bool GetQuarterlyPointFutureValue(SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration,ref Dictionary<string, Monitors> dicHighDaysDaily, List<string> dicDesignValuePeriod, Dictionary<string, Dictionary<string, int>> dicComCodePeriod)
        {
            try
            {
                List<string> lstYear = new List<string>();
                foreach (KeyValuePair<string, Monitors> k in dicHighDaysDaily)
                {
                    k.Value.dicQuarterlyPM = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                    for (int i = 1; i < 5; i++)
                    {
                        k.Value.dicQuarterlyPM.Add(i.ToString(), new Dictionary<string, PM25Monitors>());
                    }

                    //跨年求均值为3年一组
                    for (int i = 0; i < dicDesignValuePeriod.Count; i++)
                    {
                        string s = dicDesignValuePeriod[i];
                        lstYear = new List<string>();
                        lstYear = s.Split('-').Distinct().ToList();
                        int j = Convert.ToInt32(lstYear.First())+1;
                        while (j < Convert.ToInt32(lstYear.Last()))
                        {
                            lstYear.Insert(1,j.ToString());
                            j++;
                        }
                        //lstYear.Insert(1, (Convert.ToInt32((lstYear[0])) + 1).ToString());
                        //lstYear.Sort();
                        var query = k.Value.dicOfficialPM25Daily.Where(p => lstYear.Contains(p.Key.Substring(0,4)));
                        if (dicComCodePeriod[k.Key][s] != 1) continue;
                        for (int quarter = 1; quarter < 5; quarter++)
                        {
                            List<double> lstBase = new List<double>();
                            List<double> lstAlt = new List<double>();
                            foreach (var item in query)
                            {
                                lstBase.AddRange(item.Value[quarter.ToString()].Select(p => p.Value.bPM25).ToList());
                                lstAlt.AddRange(item.Value[quarter.ToString()].Select(p => p.Value.fPM25).ToList());
                            }
                            PM25Monitors opt = new PM25Monitors();
                            opt.bPM25 = lstBase.Average();
                            opt.fPM25 = lstAlt.Average();
                            k.Value.dicQuarterlyPM[quarter.ToString()].Add(s, opt);
                        }
                    }
                }
                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 SSIADailyPMAnalysisConfiguration)) return false;

                SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration = baseScenario.configuration as SSIADailyPMAnalysisConfiguration;

                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("Base_PM25");
                dt.Columns.Add("Alt_PM25");
                dt.Columns.Add("DeltaPM25(Max)");

                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] = k.Value.bPMDV;
                    dr[8] = k.Value.fPMDV;
                    if (k.Value.maxDelta >= 0)
                        dr[9] = k.Value.maxDelta;
                    else
                        dr[9] = 0;
                    dt.Rows.Add(dr);
                }


                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);
                //}
                string strFile = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA " + period + " Daily PM Point.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;
            }
        }
        public static bool SaveQuarterPMPoint(BaseScenario baseScenario, Dictionary<string, Monitors> dicHighDaysDaily, string period)
        {
            try
            {
                if (!(baseScenario.configuration is SSIADailyPMAnalysisConfiguration)) return false;

                SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration = baseScenario.configuration as SSIADailyPMAnalysisConfiguration;

                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("quarter");
                dt.Columns.Add("Base_PM25");
                dt.Columns.Add("Alt_PM25");
                dt.Columns.Add("DeltaPM25");

                foreach (var k in dicHighDaysDaily)
                {
                    for (int i = 1; i < 5; i++)
                    {
                        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.lat, 6);
                        dr[5] = Math.Round(k.Value.longitude, 6);
                        dr[6] = k.Value.monitorGridcell;
                        dr[7] = i.ToString();
                        dr[8] = k.Value.dicQuarterlyPM[i.ToString()].Average(p => p.Value.bPM25);
                        dr[9] = k.Value.dicQuarterlyPM[i.ToString()].Average(p => p.Value.fPM25);
                        dr[10] = Convert.ToDouble(dr[9]) - Convert.ToDouble(dr[8]);
                        dt.Rows.Add(dr);
                    }
                }

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);
                //}
                string strFile = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA " + period + " Quarterly PM Point.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 void CalculateDistance(ref Dictionary<string, double[]> dicGrid, Dictionary<string, double[]> dicSource)
        {
            try
            {
                double lat0,long0;
                double lat1,long1;
                foreach (var source in dicSource)
                {
                    lat0 = source.Value[0];
                    long0 = source.Value[1];

                    foreach (var grid in dicGrid)
                    {
                        lat1 = grid.Value[0];
                        long1 = grid.Value[1];

                        double distance = CommonClass.GetDistance(lat0, long0, lat1, long1);
                        if (grid.Value[2] == 0) grid.Value[2] = distance;
                        grid.Value[2] = Math.Min(distance, grid.Value[2]);
                    }
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);                
            }
        }



        public static bool SaveSSIADailyPMData(BaseScenario baseScenario, Dictionary<string, DailyModelMonitor> dicCMAQData, Dictionary<string, DailyModelMonitor> dicAERMODData, Dictionary<string, Dictionary<int, ModelDataSpecies>> dicDeltaGrid, Dictionary<string, Dictionary<int, ModelDataSpecies>> dicDeltaDispersion,Dictionary<string,double[]>dicDistanceFromSource)
        {
            if (!(baseScenario.configuration is SSIADailyPMAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                int decimaldigits = 8;
                SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration = baseScenario.configuration as SSIADailyPMAnalysisConfiguration;

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                if (dicCMAQData != null )
                {
                    DataTable dt = new DataTable();
                    DataRow dr = null;
                    dt.Columns.Add("_id");
                    dt.Columns.Add("lat");
                    dt.Columns.Add("long");
                    dt.Columns.Add("Base_PM25_2ndary_only");
                    dt.Columns.Add("Alt_PM25_2ndary_only");
                    dt.Columns.Add("DeltaPM25 (Max)_2ndary_only");
                    dt.Columns.Add("Base_PM25");
                    dt.Columns.Add("Alt_PM25");
                    dt.Columns.Add("DeltaPM25 (Max)");
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                    {
                        dt.Columns.Add("PM25 (BG_eVNA)");//C(CIA_eVNA)
                        dt.Columns.Add("Alt_PM25 (BG_eVNA)");
                    }
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                    {
                        dt.Columns.Add("PM25 (BG_VNA)");//C(CIA_VNA)
                        dt.Columns.Add("Alt_PM25 (BG_VNA)");
                    }
                    dt.Columns.Add("Cell center distance from source(km)");

                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicCMAQData)
                    {
                        int i = 0;
                        dr = dt.NewRow();
                        dr[i++] = k.Value.id;
                        dr[i++] = Math.Round(k.Value.lat, 6);
                        dr[i++] = Math.Round(k.Value.longitude, 6);
                        dr[i++] = Math.Round(k.Value.dicBaseSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicFutureSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = Math.Round(dicDeltaGrid[k.Value.id][9].pm25sec, decimaldigits);// Math.Round(k.Value.dicFutureSpecies["0"].pm25sec - k.Value.dicBaseSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicFutureSpecies["0"].pm25, decimaldigits);
                        dr[i++] = Math.Round(dicDeltaGrid[k.Value.id][9].pm25, decimaldigits);//Math.Round(k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                        {
                            dr[i++] = Math.Round(k.Value.dicCIAevna["0"], decimaldigits);
                            dr[i++] = Math.Round(k.Value.dicCIAevna["0"] + dicDeltaGrid[k.Value.id][9].pm25, decimaldigits);// Math.Round(k.Value.dicCIAevna["0"] + k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        }
                        if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                        {
                            dr[i++] = Math.Round(k.Value.dicCIAvna["0"], decimaldigits);
                            dr[i++] = Math.Round(k.Value.dicCIAvna["0"] + dicDeltaGrid[k.Value.id][9].pm25, decimaldigits);// Math.Round(k.Value.dicCIAvna["0"] + k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        }
                        dr[i++] = dicDistanceFromSource[k.Value.id][2];
                        dt.Rows.Add(dr);
                    }
                    //modify file name
                    string strFile = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA Grid Daily PM Data.csv";
                    BaseOutput baseOutput = new BaseOutput();
                    CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Daily");
                    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;
                    }
                    baseScenario.lstOutput.Add(baseOutput);
                    dt.Dispose();
                }
                if (dicAERMODData != null)
                {
                    DataTable dt = new DataTable();
                    DataRow dr = null;
                    dt.Columns.Add("_id");
                    dt.Columns.Add("lat");
                    dt.Columns.Add("long");
                    dt.Columns.Add("DeltaPM25 (Max)");
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                    {
                        dt.Columns.Add("PM25 (BG_VNA)");//C(CIA_VNA)
                        dt.Columns.Add("Alt_PM25 (BG_VNA)");
                    }
                    dt.Columns.Add("Cell center distance from source(km)");
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicAERMODData)
                    {
                        int i = 0;
                        dr = dt.NewRow();
                        dr[i++] = k.Value.id;
                        dr[i++] = Math.Round(k.Value.lat, 6);
                        dr[i++] = Math.Round(k.Value.longitude, 6);
                        dr[i++] = Math.Round(dicDeltaDispersion[k.Value.id][9].pm25prim, decimaldigits);// Math.Round(k.Value.dicFutureSpecies["0"].pm25prim - k.Value.dicBaseSpecies["0"].pm25prim, decimaldigits);
                        if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                        {
                            dr[i++] = Math.Round(k.Value.dicCIAvna["0"], decimaldigits);
                            dr[i++] = Math.Round(k.Value.dicCIAvna["0"] + dicDeltaDispersion[k.Value.id][9].pm25prim, decimaldigits);// Math.Round(k.Value.dicCIAvna["0"] + (k.Value.dicFutureSpecies["0"].pm25prim - k.Value.dicBaseSpecies["0"].pm25prim), decimaldigits);
                        }
                        dr[i++] = dicDistanceFromSource[k.Value.id][2];
                        dt.Rows.Add(dr);
                    }
                    //modify file name
                    string strFile = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA Dispersion Daily PM Receptor.csv";
                    BaseOutput baseOutput = new BaseOutput();
                    CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Daily");
                    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;
                    }
                    baseScenario.lstOutput.Add(baseOutput);
                    dt.Dispose();
                }
                 if (dicCMAQData != null && dicAERMODData != null) 
                {
                    DataTable dt = new DataTable();
                    DataRow dr = null;
                    dt.Columns.Add("_id");
                    dt.Columns.Add("lat");
                    dt.Columns.Add("long");
                    dt.Columns.Add("Base_PM25");
                    dt.Columns.Add("Alt_PM25");
                    dt.Columns.Add("DeltaPM25 (Max)");
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                    {
                        dt.Columns.Add("PM25 (BG_eVNA)");//C(CIA_eVNA)
                        dt.Columns.Add("Alt_PM25 (BG_eVNA)");
                    }
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                    {
                        dt.Columns.Add("PM25 (BG_VNA)");//C(CIA_VNA)
                        dt.Columns.Add("Alt_PM25 (BG_VNA)");
                    }
                    dt.Columns.Add("Base_PM25_prim_only");
                    dt.Columns.Add("ALT_PM25_prim_only");
                    dt.Columns.Add("DeltaPM25 (Max)_prim_only");
                    dt.Columns.Add("Base_PM25_2ndary_only");
                    dt.Columns.Add("ALT_PM25_2ndary_only");
                    dt.Columns.Add("DeltaPM25 (Max)_2ndary_only");
                    dt.Columns.Add("Cell center distance from source(km)");
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicCMAQData)
                    {
                        int i=0;
                        dr = dt.NewRow();
                        dr[i++] = k.Value.id;
                        dr[i++] = Math.Round(k.Value.lat, 6);
                        dr[i++] = Math.Round(k.Value.longitude, 6);
                        dr[i++] = Math.Round(k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicFutureSpecies["0"].pm25, decimaldigits);
                        dr[i++] = Math.Round(dicDeltaGrid[k.Value.id][9].pm25, decimaldigits);// Math.Round(k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                        {
                            dr[i++] = Math.Round(k.Value.dicCIAevna["0"], decimaldigits);
                            dr[i++] = Math.Round(k.Value.dicCIAevna["0"] + dicDeltaGrid[k.Value.id][9].pm25, decimaldigits);// Math.Round(k.Value.dicCIAevna["0"] + k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        }
                        if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                        {
                            dr[i++] = Math.Round(k.Value.dicCIAvna["0"], decimaldigits);
                            dr[i++] = Math.Round(k.Value.dicCIAvna["0"] + dicDeltaGrid[k.Value.id][9].pm25, decimaldigits);// Math.Round(k.Value.dicCIAvna["0"] + k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        }
                        dr[i++] = Math.Round(k.Value.dicBaseSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicFutureSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = Math.Round(dicDeltaGrid[k.Value.id][9].pm25prim, decimaldigits);// Math.Round((k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicFutureSpecies["0"].pm25sec) - (k.Value.dicBaseSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25sec), decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicBaseSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicFutureSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = Math.Round(dicDeltaGrid[k.Value.id][9].pm25sec, decimaldigits);// Math.Round(k.Value.dicFutureSpecies["0"].pm25sec - k.Value.dicBaseSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = dicDistanceFromSource[k.Value.id][2];
                        dt.Rows.Add(dr);
                    }
                    foreach (var k in dicAERMODData)
                    {
                        int i=0;
                        dr = dt.NewRow();
                        dr[i++] = k.Value.id;
                        dr[i++] = Math.Round(k.Value.lat, 6);
                        dr[i++] = Math.Round(k.Value.longitude, 6);
                        dr[i++] = Math.Round(k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicFutureSpecies["0"].pm25, decimaldigits);
                        dr[i++] = Math.Round(dicDeltaDispersion[k.Value.id][9].pm25, decimaldigits);// Math.Round(k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                        {
                            dr[i++] = Math.Round(k.Value.dicCIAevna["0"], decimaldigits);
                            dr[i++] = Math.Round(k.Value.dicCIAevna["0"] + dicDeltaDispersion[k.Value.id][9].pm25, decimaldigits);// Math.Round(k.Value.dicCIAevna["0"] + k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        }
                        if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                        {
                            dr[i++] = Math.Round(k.Value.dicCIAvna["0"], decimaldigits);
                            dr[i++] = Math.Round(k.Value.dicCIAvna["0"] + dicDeltaDispersion[k.Value.id][9].pm25, decimaldigits);// Math.Round(k.Value.dicCIAvna["0"] + k.Value.dicFutureSpecies["0"].pm25 - k.Value.dicBaseSpecies["0"].pm25, decimaldigits);
                        }
                        dr[i++] = Math.Round(k.Value.dicBaseSpecies["0"].pm25prim, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicFutureSpecies["0"].pm25prim, decimaldigits);
                        dr[i++] = Math.Round(dicDeltaDispersion[k.Value.id][9].pm25prim, decimaldigits);// Math.Round(k.Value.dicFutureSpecies["0"].pm25prim - k.Value.dicBaseSpecies["0"].pm25prim, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicBaseSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = Math.Round(k.Value.dicFutureSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = Math.Round(dicDeltaDispersion[k.Value.id][9].pm25sec, decimaldigits);//Math.Round(k.Value.dicFutureSpecies["0"].pm25sec - k.Value.dicBaseSpecies["0"].pm25sec, decimaldigits);
                        dr[i++] = dicDistanceFromSource[k.Value.id][2];
                        dt.Rows.Add(dr);
                        //dt.Rows.Add(dr);
                    }

                    //modify file name
                    string strFile = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA Combined Daily PM Receptor.csv";
                    BaseOutput baseOutput = new BaseOutput();
                    CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Daily");
                    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;
                    }
                    baseScenario.lstOutput.Add(baseOutput);
                    dt.Dispose();
                }               
                ////modify file name
                //string strFile = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA Daily PM Data.csv";
                //BaseOutput baseOutput = new BaseOutput();
                //CommonClass.SaveCSV(dt, _resultFilePath + @"\" + strFile, "Daily");
                //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;
                //}
                //baseScenario.lstOutput.Add(baseOutput);
                //dt.Dispose();
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }
        public static bool SaveSSIAQuarterlyPMData(BaseScenario baseScenario, Dictionary<string, DailyModelMonitor> dicCMAQData, Dictionary<string, DailyModelMonitor> dicAERMODData, Dictionary<string, Dictionary<int, ModelDataSpecies>> dicDeltaGrid, Dictionary<string, Dictionary<int, ModelDataSpecies>> dicDeltaDispersion, Dictionary<string, double[]> dicDistanceFromSource)
        {
            if (!(baseScenario.configuration is SSIADailyPMAnalysisConfiguration))
            {
                return false;
            }
            try
            {
                int decimaldigits = 8;
                SSIADailyPMAnalysisConfiguration SSIAdailyPMAnalysisConfiguration = baseScenario.configuration as SSIADailyPMAnalysisConfiguration;

                if (!CommonClass.IsBatch)
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\Result\Output\" + (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.scenarioName;
                }
                else
                {
                    if (_resultFilePath == "" && _resultFilePath.Length == 0 || _resultFilePath != CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.scenarioName)
                        _resultFilePath = CommonClass.ResultFilePath + @"\" + (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.scenarioName;
                }
                if (!Directory.Exists(_resultFilePath))
                    System.IO.Directory.CreateDirectory(_resultFilePath);

                if (dicCMAQData != null)
                {
                    DataTable dt = new DataTable();
                    DataRow dr = null;
                    dt.Columns.Add("_id");
                    dt.Columns.Add("lat");
                    dt.Columns.Add("long");
                    dt.Columns.Add("quarter");
                    dt.Columns.Add("Base_PM25_2ndary_only");
                    dt.Columns.Add("Alt_PM25_2ndary_only");
                    dt.Columns.Add("DeltaPM25 (Max)_2ndary_only");
                    dt.Columns.Add("Base_PM25");
                    dt.Columns.Add("Alt_PM25");
                    dt.Columns.Add("DeltaPM25 (Max)");
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                    {
                        dt.Columns.Add("PM25 (BG_eVNA)");//C(CIA_eVNA)
                        dt.Columns.Add("Alt_PM25 (BG_eVNA)");
                    }
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                    {
                        dt.Columns.Add("PM25 (BG_VNA)");//C(CIA_VNA)
                        dt.Columns.Add("Alt_PM25 (BG_VNA)");
                    }
                    dt.Columns.Add("Cell center distance from source(km)");

                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicCMAQData)
                    {
                        for (int i = 1; i < 5; i++)
                        {
                            int j = 0;
                            dr = dt.NewRow();
                            dr[j++] = k.Value.id;
                            dr[j++] = Math.Round(k.Value.lat, 6);
                            dr[j++] = Math.Round(k.Value.longitude, 6);
                            dr[j++] = i.ToString();
                            dr[j++] = Math.Round(k.Value.dicBaseSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = Math.Round(dicDeltaGrid[k.Key][i].pm25sec, decimaldigits);// Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25sec - dicDeltaGrid[k.Key][i].pm25sec, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25, decimaldigits);
                            dr[j++] = Math.Round(dicDeltaGrid[k.Key][i].pm25, decimaldigits);//  Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                            {
                                dr[j++] = Math.Round(k.Value.dicCIAevna[i.ToString()], decimaldigits);
                                dr[j++] = Math.Round(k.Value.dicCIAevna[i.ToString()]+dicDeltaGrid[k.Key][i].pm25, decimaldigits);//  Math.Round(k.Value.dicCIAevna[i.ToString()] + k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            }
                            if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                            {
                                dr[j++] = Math.Round(k.Value.dicCIAvna[i.ToString()], decimaldigits);
                                dr[j++] = Math.Round(k.Value.dicCIAevna[i.ToString()] + dicDeltaGrid[k.Key][i].pm25, decimaldigits);// Math.Round(k.Value.dicCIAvna[i.ToString()] + k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            }

                            dr[j++] = dicDistanceFromSource[k.Value.id][2];
                            dt.Rows.Add(dr);
                        }
                    }
                    //modify file name
                    string strFile = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA Grid Quarterly PM Data.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;
                    }
                    baseScenario.lstOutput.Add(baseOutput);
                    dt.Dispose();
                }
                if (dicAERMODData != null)
                {
                    DataTable dt = new DataTable();
                    DataRow dr = null;
                    dt.Columns.Add("_id");
                    dt.Columns.Add("lat");
                    dt.Columns.Add("long");
                    dt.Columns.Add("quarter");
                    dt.Columns.Add("DeltaPM25 (Max)");
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                    {
                        dt.Columns.Add("PM25 (BG_VNA)");//C(CIA_VNA)
                        dt.Columns.Add("Alt_PM25 (BG_VNA)");
                    }
                    dt.Columns.Add("Cell center distance from source(km)");

                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicAERMODData)
                    {
                        for (int i = 1; i < 5; i++)
                        {
                            int j = 0;
                            dr = dt.NewRow();
                            dr[j++] = k.Value.id;
                            dr[j++] = Math.Round(k.Value.lat, 6);
                            dr[j++] = Math.Round(k.Value.longitude, 6);
                            dr[j++] = i.ToString();
                            dr[j++] = Math.Round(dicDeltaDispersion[k.Key][i].pm25prim, decimaldigits);//  Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25prim - k.Value.dicBaseSpecies[i.ToString()].pm25prim, decimaldigits);
                            if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                            {
                                dr[j++] = Math.Round(k.Value.dicCIAvna[i.ToString()], decimaldigits);
                                dr[j++] = Math.Round(k.Value.dicCIAvna[i.ToString()] + dicDeltaDispersion[k.Key][i].pm25prim, decimaldigits);//  Math.Round(k.Value.dicCIAvna[i.ToString()] + (k.Value.dicFutureSpecies[i.ToString()].pm25prim - k.Value.dicBaseSpecies[i.ToString()].pm25prim), decimaldigits);
                            }
                            dr[j++] = dicDistanceFromSource[k.Value.id][2];
                            dt.Rows.Add(dr);
                        }
                    }
                    //modify file name
                    string strFile = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA Dispersion Quarterly PM Receptor.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;
                    }
                    baseScenario.lstOutput.Add(baseOutput);
                    dt.Dispose();
                }
                if (dicCMAQData != null && dicAERMODData != null)
                {
                    DataTable dt = new DataTable();
                    DataRow dr = null;
                    dt.Columns.Add("_id");
                    dt.Columns.Add("lat");
                    dt.Columns.Add("long");
                    dt.Columns.Add("quarter");
                    dt.Columns.Add("Base_PM25");
                    dt.Columns.Add("Alt_PM25");
                    dt.Columns.Add("DeltaPM25 (Max)");
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                    {
                        dt.Columns.Add("PM25 (BG_eVNA)");//C(CIA_eVNA)
                        dt.Columns.Add("Alt_PM25 (BG_eVNA)");
                    }
                    if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                    {
                        dt.Columns.Add("PM25 (BG_VNA)");//C(CIA_VNA)
                        dt.Columns.Add("Alt_PM25 (BG_VNA)");
                    }
                    dt.Columns.Add("Base_PM25_prim_only");
                    dt.Columns.Add("ALT_PM25_prim_only");
                    dt.Columns.Add("DeltaPM25 (Max)_prim_only");
                    dt.Columns.Add("Base_PM25_2ndary_only");
                    dt.Columns.Add("ALT_PM25_2ndary_only");
                    dt.Columns.Add("DeltaPM25 (Max)_2ndary_only");
                    dt.Columns.Add("Cell center distance from source(km)");
                    foreach (KeyValuePair<string, DailyModelMonitor> k in dicCMAQData)
                    {
                        for (int i = 1; i < 5; i++)
                        {
                            int j = 0;
                            dr = dt.NewRow();
                            dr[j++] = k.Value.id;
                            dr[j++] = Math.Round(k.Value.lat, 6);
                            dr[j++] = Math.Round(k.Value.longitude, 6);
                            dr[j++] = i.ToString();
                            dr[j++] = Math.Round(k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25, decimaldigits);
                            dr[j++] = Math.Round(dicDeltaGrid[k.Key][i].pm25, decimaldigits);// Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                            {
                                dr[j++] = Math.Round(k.Value.dicCIAevna[i.ToString()], decimaldigits);
                                dr[j++] = Math.Round(k.Value.dicCIAevna[i.ToString()] + dicDeltaGrid[k.Key][i].pm25, decimaldigits);// Math.Round(k.Value.dicCIAevna[i.ToString()] + k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            }
                            if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                            {
                                dr[j++] = Math.Round(k.Value.dicCIAvna[i.ToString()], decimaldigits);
                                dr[j++] = Math.Round(k.Value.dicCIAevna[i.ToString()] + dicDeltaGrid[k.Key][i].pm25, decimaldigits);// Math.Round(k.Value.dicCIAvna[i.ToString()] + k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            }
                            dr[j++] = Math.Round(k.Value.dicBaseSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicFutureSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = Math.Round((k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicFutureSpecies[i.ToString()].pm25sec) - (k.Value.dicBaseSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25sec), decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicBaseSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = Math.Round(dicDeltaGrid[k.Key][i].pm25sec, decimaldigits);// Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25sec - k.Value.dicBaseSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = dicDistanceFromSource[k.Value.id][2];
                            dt.Rows.Add(dr);
                        }
                    }

                    foreach (var k in dicAERMODData)
                    {
                        for (int i = 1; i < 5; i++)
                        {
                            int j = 0;
                            dr = dt.NewRow();
                            dr[j++] = k.Value.id;
                            dr[j++] = Math.Round(k.Value.lat, 6);
                            dr[j++] = Math.Round(k.Value.longitude, 6);
                            dr[j++] = i.ToString();
                            dr[j++] = Math.Round(k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25, decimaldigits);
                            dr[j++] = Math.Round(dicDeltaDispersion[k.Key][i].pm25, decimaldigits);// Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useEVNA)
                            {
                                dr[j++] = Math.Round(k.Value.dicCIAevna[i.ToString()], decimaldigits);
                                dr[j++] = Math.Round(k.Value.dicCIAevna[i.ToString()] + dicDeltaDispersion[k.Key][i].pm25, decimaldigits);// Math.Round(k.Value.dicCIAevna[i.ToString()] + k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            }
                            if ((CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).analysisOptionD.useModelFRMData && (CommonClass.CurrentBaseScenario.configuration as SSIADailyPMAnalysisConfiguration).monitorInputD.useVNA)
                            {
                                dr[j++] = Math.Round(k.Value.dicCIAvna[i.ToString()], decimaldigits);
                                dr[j++] = Math.Round(k.Value.dicCIAevna[i.ToString()] + dicDeltaDispersion[k.Key][i].pm25, decimaldigits);// Math.Round(k.Value.dicCIAvna[i.ToString()] + k.Value.dicFutureSpecies[i.ToString()].pm25 - k.Value.dicBaseSpecies[i.ToString()].pm25, decimaldigits);
                            }
                            dr[j++] = Math.Round(k.Value.dicBaseSpecies[i.ToString()].pm25prim, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25prim, decimaldigits);
                            dr[j++] = Math.Round(dicDeltaDispersion[k.Key][i].pm25prim, decimaldigits);// Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25prim - k.Value.dicBaseSpecies[i.ToString()].pm25prim, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicBaseSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = Math.Round(dicDeltaDispersion[k.Key][i].pm25sec, decimaldigits);// Math.Round(k.Value.dicFutureSpecies[i.ToString()].pm25sec - k.Value.dicBaseSpecies[i.ToString()].pm25sec, decimaldigits);
                            dr[j++] = dicDistanceFromSource[k.Value.id][2];
                            dt.Rows.Add(dr);
                        }
                        //dt.Rows.Add(dr);
                    }
                    //modify file name
                    string strFile = SSIAdailyPMAnalysisConfiguration.analysisOptionD.scenarioName + " SSIA Combined Quarterly PM Receptor.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;
                    }
                    baseScenario.lstOutput.Add(baseOutput);
                    dt.Dispose();
                }

                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }


        #region spatial field

        private static void sp(ref Dictionary<string,Monitors> dicMonitors,List<string> lstDesignValueYear,Dictionary<string,Dictionary<string,int>> dicComCodePeriod)
        {
            try
            {
                foreach (var k1 in dicMonitors)
                {
                    k1.Value.dicQuarterlyPM = new Dictionary<string, Dictionary<string, PM25Monitors>>();
                    k1.Value.dicPM = new Dictionary<string, PM25Monitors>();

                    List<double> lstDesignValue = new List<double>();
                    Dictionary<string, List<double>> dicvalue = new Dictionary<string, List<double>>();

                    for (int i = 1; i < 5; i++)
                    {
                        k1.Value.dicQuarterlyPM.Add(i.ToString(),new Dictionary<string,PM25Monitors>());
                        foreach (var k2 in k1.Value.dicOfficialPM25Daily[i.ToString()])
                        {
                            int rank = k2.Value.First().Value.rank98;
                            if (!dicvalue.ContainsKey(k2.Key + rank.ToString()))
                                dicvalue.Add(k2.Key + rank.ToString(), new List<double>());
                            List<double> lsttemp = k2.Value.Select(p => p.Value.bPM25).OrderByDescending(p => p).Take(8).ToList();
                            k1.Value.dicQuarterlyPM[i.ToString()].Add(k2.Key, new PM25Monitors() { bPM25 = lsttemp.Average() });
                            dicvalue[k2.Key + rank.ToString()].AddRange(lsttemp);                
                        }
                        lstDesignValue = new List<double>();
                        foreach (var item in lstDesignValueYear)
                        {
                            List<string> lstYear = new List<string>();
                            string s = item;
                            lstYear = s.Split('-').Distinct().ToList();
                            int j = Convert.ToInt32(lstYear.First()) + 1;
                            while (j < Convert.ToInt32(lstYear.Last()))
                            {
                                lstYear.Insert(1, j.ToString());
                                j++;
                            }
                            double temp2 = 0;
                            if (dicComCodePeriod[k1.Key][s] != 1) continue;
                            if (k1.Value.dicQuarterlyPM[i.ToString()].Keys.Count < 3)
                            {
                                temp2 = k1.Value.dicQuarterlyPM[i.ToString()].Average(p => p.Value.bPM25);
                            }
                            else
                            {
                                temp2 = k1.Value.dicQuarterlyPM[i.ToString()].Where(p => lstYear.Contains(p.Key)).Average(p => p.Value.bPM25);
                            }
                            lstDesignValue.Add(temp2);
                        }
                        k1.Value.dicPM.Add(i.ToString(), new PM25Monitors() { bPM25 = lstDesignValue.Average() });
                    }
                    foreach (var item in dicvalue)
                    {
                        double temp = item.Value.OrderByDescending(p => p).Take(Convert.ToInt16(item.Key.Substring(4))).Last();
                        item.Value.Clear();
                        item.Value.Add(temp);
                    }
                    lstDesignValue = new List<double>();
                    foreach (var item in lstDesignValueYear)
                    {
                        List<string> lstYear = new List<string>();
                        string s = item;
                        lstYear = s.Split('-').Distinct().ToList();
                        int j = Convert.ToInt32(lstYear.First()) + 1;
                        while (j < Convert.ToInt32(lstYear.Last()))
                        {
                            lstYear.Insert(1, j.ToString());
                            j++;
                        }

                        if (dicComCodePeriod[k1.Key][s] != 1) continue;
                        double temp2 = dicvalue.Where(p => lstYear.Contains(p.Key.Substring(0,4))).Average(p => p.Value.First());
                        lstDesignValue.Add(temp2);
                    }
                    k1.Value.dicPM.Add("0", new PM25Monitors() { bPM25 = lstDesignValue.Average() });
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        public static bool GetGradAdjValues(ref Dictionary<string, float> dicGradAdjValues, Dictionary<string, float> fsoutStringPM, Dictionary<string, ModelDataSpecies> dicBaselineModel, Dictionary<string, DailyModelMonitor> dicModelDataPM)
        {
            try
            {                
                foreach (KeyValuePair<string, float> s in fsoutStringPM)
                {
                    string id = s.Key.Substring(0, s.Key.IndexOf(","));
                    string gridcell = s.Key.Substring(s.Key.IndexOf(",") + 1);
                    for (int i = 0; i < 5; i++)
                    {
                        float pm25 = dicBaselineModel[i.ToString()].pm25 / dicModelDataPM[gridcell].dicBaseSpecies[i.ToString()].pm25;
                        dicGradAdjValues.Add(s.Key + "," + i.ToString(), pm25);
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool AnnualVNA(string interpolationMethod, double distanceInterpolation, ref double dVNA, Dictionary<string, float> fsoutStringPM, Dictionary<string, Monitors> dicMonitors, string quarter)
        {
            try
            {
                double distanceSpecies = 0, distanceSumSpecies = 0, vnaSum = 0;
                int n = 0;
                switch (interpolationMethod)
                {
                    case "Equal Weighting of Monitors":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringPM)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                if ((!dicMonitors.ContainsKey(id) || double.IsNaN(dicMonitors[id].dicPM[quarter].bPM25))) continue;
                                n++;
                                vnaSum += dicMonitors[id].dicPM[quarter].bPM25;
                            }
                            catch { }
                        }
                        try
                        {
                            dVNA = Math.Round(Double.IsNaN(vnaSum / n) ? 0 : vnaSum / n, CommonClass.Species_calc_precision);
                        }
                        catch
                        { }
                        #endregion
                        break;
                    case "Inverse Distance Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringPM)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                if ((!dicMonitors.ContainsKey(id) || double.IsNaN(dicMonitors[id].dicPM[quarter].bPM25))) continue;
                                distanceSpecies = s.Value == 0 ? 1 : Convert.ToSingle(1.0000 / s.Value);
                                distanceSumSpecies += distanceSpecies;
                                vnaSum += dicMonitors[id].dicPM[quarter].bPM25 * distanceSpecies;
                            }
                            catch
                            { }
                        }
                        try
                        {
                            dVNA = Math.Round(Double.IsNaN(vnaSum / distanceSumSpecies) ? 0 : vnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                        }
                        catch
                        { }
                        #endregion
                        break;
                    case "Inverse Distance Squared Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringPM)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                if ((!dicMonitors.ContainsKey(id) || double.IsNaN(dicMonitors[id].dicPM[quarter].bPM25))) continue;
                                distanceSpecies = s.Value == 0 ? 1 : Convert.ToSingle(1.0000 / Math.Pow(s.Value, 2));
                                distanceSumSpecies += distanceSpecies;
                                vnaSum += dicMonitors[id].dicPM[quarter].bPM25 * distanceSpecies;
                            }
                            catch
                            {
                            }
                        }
                        try
                        {
                            double d = Double.IsNaN(vnaSum / distanceSumSpecies) ? 0 : vnaSum / distanceSumSpecies;
                            dVNA = Math.Round(Double.IsNaN(vnaSum / distanceSumSpecies) ? 0 : vnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                        }
                        catch
                        { }
                        #endregion
                        break;
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool AnnualEVNA(Dictionary<string, float> dicGradAdjValues, string interpolationMethod, double distanceInterpolation, ref double dEVNA, Dictionary<string, float> fsoutStringPM, Dictionary<string, Monitors> dicMonitors, string quarter)
        {
            try
            {
                double distanceSpecies = 0, distanceSumSpecies = 0, gvnaSum = 0;
                int n = 0;
                switch (interpolationMethod)
                {
                    case "Equal Weighting of Monitors":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringPM)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                if ((!dicMonitors.ContainsKey(id) || double.IsNaN(dicMonitors[id].dicPM[quarter].bPM25))) continue;
                                n++;
                                gvnaSum += dicMonitors[id].dicPM[quarter].bPM25 * dicGradAdjValues[s.Key + "," + quarter];
                            }
                            catch { }
                        }
                        try
                        {
                            dEVNA = Math.Round(Double.IsNaN(gvnaSum / n) ? 0 : gvnaSum / n, CommonClass.Species_calc_precision);
                        }
                        catch
                        {
                        }
                        #endregion
                        break;
                    case "Inverse Distance Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringPM)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                if ((!dicMonitors.ContainsKey(id) || double.IsNaN(dicMonitors[id].dicPM[quarter].bPM25))) continue;
                                distanceSpecies = s.Value == 0 ? 1 : 1.0000 / s.Value;
                                distanceSumSpecies += distanceSpecies;
                                gvnaSum += dicMonitors[id].dicPM[quarter].bPM25 * distanceSpecies * dicGradAdjValues[s.Key + "," + quarter];
                            }
                            catch { }
                        }
                        try
                        {
                            dEVNA = Math.Round(Double.IsNaN(gvnaSum / distanceSumSpecies) ? 0 : Convert.ToSingle(gvnaSum / distanceSumSpecies), CommonClass.Species_calc_precision);
                        }
                        catch { }
                        #endregion
                        break;
                    case "Inverse Distance Squared Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringPM)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                if ((!dicMonitors.ContainsKey(id) || double.IsNaN(dicMonitors[id].dicPM[quarter].bPM25))) continue;
                                distanceSpecies = s.Value == 0 ? 1 : 1.0000 / Math.Pow(s.Value, 2);
                                distanceSumSpecies += distanceSpecies;
                                gvnaSum += dicMonitors[id].dicPM[quarter].bPM25 * distanceSpecies * dicGradAdjValues[s.Key + "," + quarter];
                            }
                            catch
                            {
                            }
                        }
                        try
                        {
                            dEVNA = Math.Round(Double.IsNaN(gvnaSum / distanceSumSpecies) ? 0 : Convert.ToSingle(gvnaSum / distanceSumSpecies), CommonClass.Species_calc_precision);
                        }
                        catch { }
                        #endregion
                        break;
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        public static bool AnnualVNAEVNA(Dictionary<string, float> dicGradAdjValues, string interpolationMethod, double distanceInterpolation, ref double dVNA, ref double dEVNA, Dictionary<string, float> fsoutStringPM, Dictionary<string, Monitors> dicMonitors, string quarter)
        {
            try
            {
                double distanceSpecies = 0, distanceSumSpecies = 0, vnaSum = 0, gvnaSum = 0;
                int n = 0;
                Dictionary<string, float> dic = new Dictionary<string, float>();
                switch (interpolationMethod)
                {
                    case "Equal Weighting of Monitors":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringPM)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                if ((!dicMonitors.ContainsKey(id) || double.IsNaN(dicMonitors[id].dicPM[quarter].bPM25))) continue;
                                n++;
                                vnaSum += dicMonitors[id].dicPM[quarter].bPM25;
                                gvnaSum += dicMonitors[id].dicPM[quarter].bPM25 * dicGradAdjValues[s.Key + "," + quarter];
                            }
                            catch { }
                        }
                        try
                        {
                            dVNA = Math.Round(Double.IsNaN(vnaSum / n) ? 0 : vnaSum / n, CommonClass.Species_calc_precision);
                            dEVNA = Math.Round(Double.IsNaN(gvnaSum / n) ? 0 : gvnaSum / n, CommonClass.Species_calc_precision);
                        }
                        catch { }
                        #endregion
                        break;
                    case "Inverse Distance Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringPM)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                if ((!dicMonitors.ContainsKey(id) || double.IsNaN(dicMonitors[id].dicPM[quarter].bPM25))) continue;
                                distanceSpecies = s.Value == 0 ? 1 : 1.0000 / s.Value;
                                distanceSumSpecies += distanceSpecies;
                                vnaSum += dicMonitors[id].dicPM[quarter].bPM25 * distanceSpecies;
                                gvnaSum += dicMonitors[id].dicPM[quarter].bPM25 * distanceSpecies * dicGradAdjValues[s.Key + "," + quarter];
                            }
                            catch { }
                        }
                        try
                        {
                            dVNA = Math.Round(Double.IsNaN(vnaSum / distanceSumSpecies) ? 0 : vnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                            dEVNA = Math.Round(Double.IsNaN(gvnaSum / distanceSumSpecies) ? 0 : gvnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                        }
                        catch { }
                        #endregion
                        break;
                    case "Inverse Distance Squared Weights":
                        #region
                        foreach (KeyValuePair<string, float> s in fsoutStringPM)
                        {
                            string id = s.Key.Substring(0, s.Key.IndexOf(","));
                            if (s.Value > distanceInterpolation) continue;
                            try
                            {
                                if ((!dicMonitors.ContainsKey(id) || double.IsNaN(dicMonitors[id].dicPM[quarter].bPM25))) continue;
                                distanceSpecies = s.Value == 0 ? 1 : 1.0000 / Math.Pow(s.Value, 2);
                                distanceSumSpecies += distanceSpecies;
                                vnaSum += dicMonitors[id].dicPM[quarter].bPM25 * distanceSpecies;
                                gvnaSum += dicMonitors[id].dicPM[quarter].bPM25 * distanceSpecies * dicGradAdjValues[s.Key + "," + quarter];
                            }
                            catch
                            {
                            }
                        }
                        try
                        {
                            dVNA = Math.Round(Double.IsNaN(vnaSum / distanceSumSpecies) ? 0 : vnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                            dEVNA = Math.Round(Double.IsNaN(gvnaSum / distanceSumSpecies) ? 0 : gvnaSum / distanceSumSpecies, CommonClass.Species_calc_precision);
                        }
                        catch { }
                        #endregion
                        break;
                }
                return true;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return false;
            }
        }

        #endregion
    }
}
