Пример #1
0
        //This should be one section passed in, and described intervals on the same section. So they would have the same SampleID
        private static ICollection <DrillingDisturbanceRecord> CoreToSectionAlgo(DrillingDisturbanceRecord newSectionRecord, ICollection <DrillingDisturbanceRecord> describedSectionIntervals)
        {
            double seedTop    = newSectionRecord.Top_cm.ToDouble();
            double seedBottom = newSectionRecord.Bottom_cm.ToDouble();

            //Check if there are any describedSectionIntervals that overlap the entire newSectionRecord:
            var match = describedSectionIntervals.Where(d => d.Top_cm == newSectionRecord.Top_cm && d.Bottom_cm == newSectionRecord.Bottom_cm).FirstOrDefault();
            var gapIntervalsDescriptions = new List <DrillingDisturbanceRecord>();


            //This entire section has been described, so do not add in my artifical section description
            if (match != null)
            {
                return(describedSectionIntervals);
            }

            //There are described intervals on the section which only take up part of the section. I need to create artifical section descriptions to fill in the gaps.
            //Find described intervals on the section which overlap the new section description I've created, return the one with the greatest depth
            // var intervalDescription = describedSectionIntervals.Where(d => d.Top_cm.ToDouble() <= seedTop && d.Bottom_cm.ToDouble() > seedTop).OrderBy(d => d.Bottom_cm.ToDouble()).LastOrDefault();
            foreach (var intervalDescription in describedSectionIntervals.OrderBy(d => d.TopDepth_m).Select(x => x))
            {
                //Interval has been described, change the TOP reference and go again.
                if (intervalDescription.Top_cm.ToDouble() <= seedTop && intervalDescription.Bottom_cm.ToDouble() > seedTop)
                {
                    seedTop = intervalDescription.Bottom_cm.ToDouble();
                    continue;
                }
                else if (intervalDescription.Top_cm.ToDouble() > seedTop)
                {
                    //Create a new drilling description to account for this interval;
                    //Remember these fields are from the CORE description, aside from the TOP/BOTTOM offsets and depths
                    DrillingDisturbanceRecord gapInterval = new DrillingDisturbanceRecord
                    {
                        Column1   = newSectionRecord.Column1,
                        SampleID  = newSectionRecord.SampleID,
                        Top_cm    = seedTop.ToString(),                                                                                                   //Gap interval goes from seedTop to the top of the next shallowest core description interval
                        Bottom_cm = intervalDescription.Top_cm,                                                                                           //This is correct

                        TopDepth_m    = (intervalDescription.TopDepth_m.ToDouble() - (intervalDescription.Top_cm.ToDouble() - seedTop) / 100).ToString(), //Both the top depth and bottom depth need to be adjusted....
                        BottomDepth_m = intervalDescription.TopDepth_m,

                        DrillingDisturbanceType          = newSectionRecord.DrillingDisturbanceType,
                        DrillingDisturbanceIntensity     = newSectionRecord.DrillingDisturbanceIntensity,
                        DrillingDisturbanceComment       = newSectionRecord.DrillingDisturbanceComment,
                        DrillingDisturbanceIntensityRank = newSectionRecord.DrillingDisturbanceIntensityRank,
                        ShipFileLinks  = newSectionRecord.ShipFileLinks,
                        ShoreFileLinks = newSectionRecord.ShoreFileLinks,
                        FileData       = newSectionRecord.FileData
                    };

                    gapIntervalsDescriptions.Add(gapInterval);

                    seedTop = intervalDescription.Bottom_cm.ToDouble(); //Set the new seed top to be at the bottom of the last described interval
                }
            }

            return(gapIntervalsDescriptions);
        }
Пример #2
0
        public static List <DrillingDisturbanceRecord> FormatDrillingDisturbanceFile(string filename, string exportFilename)
        {
            Log.Information("--------Parsing a new file--------");
            DataTable sections = SectionInfoCollection.ImportAllSections(ConfigurationManager.AppSettings["AllSectionsFile"]);
            ICollection <DrillingDisturbanceRecord> descriptions           = new HashSet <DrillingDisturbanceRecord>();
            List <DrillingDisturbanceRecord>        FinalDescriptionsToAdd = new List <DrillingDisturbanceRecord>();

            #region ImportDrillingDisturbances
            var dataTableReader = new CSVReader();
            dataTableReader.ReadPath = filename;
            DataTable drillingDisturbances = dataTableReader.Read();


            //Correct Column Names:

            ChangeColumn(drillingDisturbances, "Drilling disturbance intensity [rank]", "Drilling disturbance intensity rank");
            ChangeColumn(drillingDisturbances, "Drilling disturbance intensity rank(read only)", "Drilling disturbance intensity rank");
            ChangeColumn(drillingDisturbances, "Drilling disturbance intensity rank (read only)", "Drilling disturbance intensity rank");

            ChangeColumn(drillingDisturbances, "Label ID", "Sample");

            ChangeColumn(drillingDisturbances, "Top depth [m]", "Top Depth [m]");
            ChangeColumn(drillingDisturbances, "Bottom depth [m]", "Bottom Depth [m]");

            ChangeColumn(drillingDisturbances, "Disturbance [name]", "Disturbance");

            ChangeColumn(drillingDisturbances, "File data", "File Data");

            //Add additional columns
            if (!drillingDisturbances.Columns.Contains("Drilling disturbance comment"))
            {
                drillingDisturbances.Columns.Add("Drilling disturbance comment");
            }
            if (!drillingDisturbances.Columns.Contains("Drilling disturbance type"))
            {
                drillingDisturbances.Columns.Add("Drilling disturbance type");
            }
            if (!drillingDisturbances.Columns.Contains("Drilling disturbance intensity"))
            {
                drillingDisturbances.Columns.Add("Drilling disturbance intensity");
            }
            if (!drillingDisturbances.Columns.Contains("Drilling disturbance intensity rank"))
            {
                drillingDisturbances.Columns.Add("Drilling disturbance intensity rank");
            }

            try
            {
                //Collection of all drilling disturbances
                foreach (DataRow row in drillingDisturbances.Rows)
                {
                    DrillingDisturbanceRecord record = new DrillingDisturbanceRecord()
                    {
                        Column1                          = row["Column1"].ToString(),
                        SampleID                         = row["Sample"].ToString(),
                        Top_cm                           = row["Top [cm]"].ToString(),
                        Bottom_cm                        = row["Bottom [cm]"].ToString(),
                        TopDepth_m                       = row["Top Depth [m]"].ToString(),
                        BottomDepth_m                    = row["Bottom Depth [m]"].ToString(),
                        DrillingDisturbanceType          = row["Drilling disturbance type"].ToString(),
                        DrillingDisturbanceIntensity     = row["Drilling disturbance intensity"].ToString(),
                        DrillingDisturbanceIntensityRank = row["Drilling disturbance intensity rank"].ToString(),
                        DrillingDisturbanceComment       = row["Drilling disturbance comment"].ToString(),
                        // ShipFileLinks = row["Ship File Links"].ToString(),
                        // ShoreFileLinks = row["Shore File Links"].ToString(),
                        FileData = row["File Data"].ToString()
                    };
                    descriptions.Add(record);
                }
            }
            catch (Exception ex)
            {
                Log.Warning(ex.Message);
                Log.Warning($"Could not created disturbance records from {filename}");
                return(FinalDescriptionsToAdd);
            }

            #endregion


            #region GetTheSectionsInCoreDescription
            foreach (var description in descriptions)
            {
                //Find rows where sample Id doesn't end in A OR W
                if (description.SampleID.EndsWith("A") || description.SampleID.EndsWith("W"))
                {
                    FinalDescriptionsToAdd.Add(description);
                    continue;
                }

                Log.Information($"{description.SampleID} is a description on the Core");
                Log.Information($"{description.SampleID} TOP OFFSET: {description.Top_cm} BOTTOM OFFSET: {description.Bottom_cm} TOPDEPTH: {description.TopDepth_m} BOTTOM DEPTH: {description.BottomDepth_m}");

                //At this point the description should be of the entire Core;
                //Parse Core information from the Sample:
                SectionInfo coreInfo = new SectionInfo(description.SampleID);

                //Find all the sections within the AllSectionsTable which overlap with the Top/Bottom offsets of the Core description
                var constituentSections = sections.AsEnumerable()
                                          .Where(x => x.Field <string>("Exp") == coreInfo.Expedition)
                                          .Where(x => x.Field <string>("Site") == coreInfo.Site)
                                          .Where(x => x.Field <string>("Hole") == coreInfo.Hole)
                                          .Where(x => x.Field <string>("Core") == coreInfo.Core)
                                          .Where(x => x.Field <string>("Type") == coreInfo.Type)
                                          .Where(x =>

                                                 (x.Field <string>("Top depth CSF-A (m)").ToDouble() >= description.TopDepth_m.ToDouble() && x.Field <string>("Top depth CSF-A (m)").ToDouble() < description.BottomDepth_m.ToDouble()) ||
                                                 (x.Field <string>("Bottom depth CSF-A (m)").ToDouble() > description.TopDepth_m.ToDouble() && x.Field <string>("Bottom depth CSF-A (m)").ToDouble() <= description.BottomDepth_m.ToDouble())
                                                 )
                                          .Select(x => x)
                                          .ToHashSet(); //collection of datarows...

                //Create new drilling disturbance records by mashing up data between original Disturbances and sections:
                //Need to relook at this: Use only the top and bottom offsets from the Sample
                //Find the sections from the allsections table which overlap those intervals
                //Create new drilling disturbances with section information
                HashSet <DrillingDisturbanceRecord> newDrillingRecords = new HashSet <DrillingDisturbanceRecord>();
                foreach (var section in constituentSections)
                {
                    //Create new sampleID, All of them will be on the Archive half
                    string newSampleID = string.Format("{0}-{1}{2}-{3}{4}-{5}-A",
                                                       section["Exp"],
                                                       section["Site"],
                                                       section["Hole"],
                                                       section["Core"],
                                                       section["Type"],
                                                       section["Sect"]);

                    //Create a new drilling disturbance record
                    var record = new DrillingDisturbanceRecord
                    {
                        Column1                          = description.Column1,
                        SampleID                         = newSampleID,
                        Top_cm                           = "0", //section["Top Offset (cm)"].ToString(),
                        Bottom_cm                        = Math.Round((section["Curated length (m)"].ToString().ToDouble() * 100), 2).ToString(),
                        TopDepth_m                       = section["Top depth CSF-A (m)"].ToString(),
                        BottomDepth_m                    = section["Bottom depth CSF-A (m)"].ToString(),
                        DrillingDisturbanceType          = description.DrillingDisturbanceType,
                        DrillingDisturbanceIntensity     = description.DrillingDisturbanceIntensityRank,
                        DrillingDisturbanceComment       = description.DrillingDisturbanceComment,
                        DrillingDisturbanceIntensityRank = description.DrillingDisturbanceIntensityRank,
                        ShipFileLinks                    = description.ShipFileLinks,
                        ShoreFileLinks                   = description.ShoreFileLinks,
                        FileData                         = description.FileData
                    };


                    newDrillingRecords.Add(record);
                    Log.Information($"{newSampleID}: Section Added: TOP OFFSET: {record.Top_cm} BOTTOM OFFSET: {record.Bottom_cm} TOP DEPTH: {record.TopDepth_m} BOTTOM DEPTH: {record.BottomDepth_m}");
                }
                #endregion region


                #region SetTheOffsetsForBorderingSections
                //Set the TOP/BOTTOM offsets for core description's first and last sections to be equal to the core descriptions TOP/BOTTOM Offsets
                var topSection    = newDrillingRecords.OrderBy(x => x.TopDepth_m).First();
                var topCorrection = topSection.Top_cm.ToDouble() + (description.TopDepth_m.ToDouble() - topSection.TopDepth_m.ToDouble()) * 100;
                topCorrection         = Math.Round(topCorrection, 2);
                topSection.Top_cm     = topCorrection.ToString(); //Need to calculate offsets based on depths
                topSection.TopDepth_m = description.TopDepth_m;

                Log.Information($"{topSection.SampleID}: Changed TopDepth to {topSection.TopDepth_m} and TopOffset to {topSection.Top_cm}");

                var bottomSection    = newDrillingRecords.OrderBy(x => x.BottomDepth_m).Last();
                var bottomCorrection = bottomSection.Bottom_cm.ToDouble() - (bottomSection.BottomDepth_m.ToDouble() - description.BottomDepth_m.ToDouble()) * 100;
                bottomCorrection            = Math.Round(bottomCorrection, 2);
                bottomSection.Bottom_cm     = bottomCorrection.ToString();
                bottomSection.BottomDepth_m = description.BottomDepth_m;

                #endregion
                Log.Information($"{bottomSection.SampleID}: Changed BottomDepth to {bottomSection.BottomDepth_m} and BottomOffset to {bottomSection.Bottom_cm}");

                foreach (var newSectionDescription in newDrillingRecords)
                {
                    //Find all descriptions the core describer's made for this SECTION. The sample ID's should be equal
                    var describedIntervalsOnSection = descriptions.Where(x => x.SampleID == newSectionDescription.SampleID).ToHashSet();



                    //If they described any intervals, pass those intervals into the algo to correctly process gap intervals
                    if (describedIntervalsOnSection.Any())
                    {
                        ICollection <DrillingDisturbanceRecord> finalRecords = CoreToSectionAlgo(newSectionDescription, describedIntervalsOnSection);
                        FinalDescriptionsToAdd.AddRange(finalRecords);

                        foreach (var record in finalRecords)
                        {
                            Log.Information($"{newSectionDescription.SampleID}: Adding to final descriptions");
                        }
                    }
                    else if (!describedIntervalsOnSection.Any())
                    {
                        FinalDescriptionsToAdd.Add(newSectionDescription);
                        Log.Information($"{newSectionDescription.SampleID}: Adding to final descriptions");
                    }
                }
            }

            //These are new descriptions to add to the file
            foreach (var record in FinalDescriptionsToAdd)
            {
                var offsetDifference = Math.Round(record.Bottom_cm.ToDouble() - record.Top_cm.ToDouble(), 2);
                var depthDifference  = Math.Round((record.BottomDepth_m.ToDouble() - record.TopDepth_m.ToDouble()) * 100, 2);

                if (offsetDifference != depthDifference)
                {
                    Log.Warning($"Error in Offsets: {record.SampleID}: TOP OFFSET: {record.Top_cm} BOTTOMOFFSET: {record.Bottom_cm} TOPDEPTH: {record.TopDepth_m} BOTTOMDEPTH: {record.BottomDepth_m}");
                }
                else
                {
                    Log.Information($"{record.SampleID}: TOP OFFSET: {record.Top_cm} BOTTOMOFFSET: {record.Bottom_cm} TOPDEPTH: {record.TopDepth_m} BOTTOMDEPTH: {record.BottomDepth_m}");
                }
            }


            DataTable dt = new DataTable();
            // DataColumn[] columns = new DataColumn[drillingDisturbances.Columns.Count];
            // drillingDisturbances.Columns.CopyTo(columns, 0);
            // dt.Columns.AddRange(columns);

            for (int i = 0; i < drillingDisturbances.Columns.Count; i++)
            {
                dt.Columns.Add(drillingDisturbances.Columns[i].ColumnName, drillingDisturbances.Columns[i].DataType);
            }

            //Add in new corrected drilling disturbances
            foreach (var item in FinalDescriptionsToAdd)
            {
                DataRow row = dt.NewRow();
                //row.BeginEdit();
                row["Column1"]                             = item.Column1;
                row["Sample"]                              = item.SampleID;
                row["Top [cm]"]                            = item.Top_cm;
                row["Bottom [cm]"]                         = item.Bottom_cm;
                row["Top Depth [m]"]                       = item.TopDepth_m;
                row["Bottom Depth [m]"]                    = item.BottomDepth_m;
                row["Drilling disturbance type"]           = item.DrillingDisturbanceType;
                row["Drilling disturbance intensity"]      = item.DrillingDisturbanceIntensity;
                row["Drilling disturbance intensity rank"] = item.DrillingDisturbanceIntensityRank;
                row["Drilling disturbance comment"]        = item.DrillingDisturbanceComment;
                //row["Ship File Links"] = item.ShipFileLinks;
                //row["Shore File Links"] = item.ShoreFileLinks;
                row["File Data"] = item.FileData;

                dt.Rows.Add(row);
                //row.EndEdit();
            }

            Importer.ExportDataTableAsNewFile(exportFilename, dt);
            return(FinalDescriptionsToAdd);
        }