示例#1
0
        /// <summary>
        /// Attaches the corresponding descriptions for a measurement interval from the database to the measurement.
        /// </summary>
        /// <param name="dbContext">A DESCDatabase context</param>
        /// <param name="measurement">A measurement interval</param>
        /// <param name="columnNames">The description columns to return</param>
        /// <returns></returns>
        public static async Task <Measurement> MatchDescriptionForMeasurementAsync(DescDBContext dbContext, Measurement measurement, [Optional] ICollection <string> columnNames)
        {
            measurement.SectionInfo = measurement.SectionInfo ?? throw new Exception("Measurement does not have Section information");


            SectionInfo section = await dbContext.Sections.Where(x => measurement.SectionInfo.Equals(x))
                                  .FirstOrDefaultAsync().ConfigureAwait(true);

            if (section == null)
            {
                return(measurement);
            }

            var x = dbContext.LithologicDescriptions
                    .Where(description => description.SectionInfo.Equals(measurement.SectionInfo))
                    .Where(description => description.StartOffset <= measurement.StartOffset && description.EndOffset >= measurement.EndOffset);


            if (columnNames.Any())
            {
                x = x.Include(description => description.DescriptionColumnValues.Where(columnValuPair => columnNames.Contains(columnValuPair.ColumnName))
                              );
            }
            measurement.Descriptions = x.Select(g => g).ToHashSet();

            return(measurement);
        }
示例#2
0
        public static Dictionary <int, Measurement> Convert(IODPDataTable dataTable, SectionInfoCollection SectionCollection)
        {
            _ = SectionCollection ?? throw new ArgumentNullException(nameof(SectionCollection));
            _ = dataTable ?? throw new ArgumentNullException(nameof(dataTable));

            Dictionary <int, Measurement> _measurements = new Dictionary <int, Measurement>();

            int measurementCount = _measurements.Count + 1;

            //TODO: Ignore record if error is thrown, ex: offsets with TCON
            foreach (DataRow record in dataTable.DataTable.Rows)
            {
                SectionInfo measurementSectionInfo = new SectionInfo();
                try
                {
                    measurementSectionInfo.Expedition = record[dataTable.ExpeditionColumn].ToString();
                    measurementSectionInfo.Site       = record[dataTable.SiteColumn].ToString();
                    measurementSectionInfo.Hole       = record[dataTable.HoleColumn].ToString();
                    measurementSectionInfo.Core       = record[dataTable.CoreColumn].ToString();
                    measurementSectionInfo.Type       = record[dataTable.TypeColumn].ToString();
                    measurementSectionInfo.Section    = record[dataTable.SectionColumn].ToString();
                }
                catch (Exception)
                {
                    throw new IndexOutOfRangeException(nameof(record));
                }

                Measurement measurement = new Measurement(measurementSectionInfo);

                measurement.SectionInfo = SectionCollection.GetExistingElseAddAndGetCurrentSection(measurement.SectionInfo);

                //CARB files throw error here because there isn't an offset field within the file. Ensure there is.
                try
                {
                    if (!string.IsNullOrEmpty(dataTable.OffsetColumn))
                    {
                        measurement.StartOffset = double.Parse(record[dataTable.OffsetColumn].ToString(), CultureInfo.CurrentCulture);
                        measurement.EndOffset   = double.Parse(record[dataTable.OffsetColumn].ToString(), CultureInfo.CurrentCulture);
                    }
                    if (!string.IsNullOrEmpty(dataTable.TopOffsetColumn))
                    {
                        measurement.StartOffset = double.Parse(record[dataTable.TopOffsetColumn].ToString(), CultureInfo.CurrentCulture);
                    }
                    if (!string.IsNullOrEmpty(dataTable.BottomOffsetColumn))
                    {
                        measurement.EndOffset = double.Parse(record[dataTable.BottomOffsetColumn].ToString(), CultureInfo.CurrentCulture);
                    }

                    measurement.DataRow = record;

                    _measurements.Add(measurementCount, measurement);
                    measurementCount++;
                }
                catch (Exception)
                {
                    //throw;
                }
            }
            return(_measurements);
        }
示例#3
0
        public SectionInfo GetExistingElseAddAndGetCurrentSection(SectionInfo section)
        {
            var matchedSection = Sections.Where(x => section.Equals(x)).FirstOrDefault();

            if (matchedSection != null)
            {
                return(matchedSection);
            }

            Sections.Add(section);
            return(section);
        }
示例#4
0
        /// <summary>
        /// Gets a collection of LithologicDescriptions from a corrected file.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="columnIdentifiers"></param>
        /// <returns></returns>
        public static async Task <ICollection <LithologicDescription> > GetDescriptionsFromFileAsync(string filename, [Optional] IntervalHierarchyNames columnIdentifiers)
        {
            columnIdentifiers = columnIdentifiers ?? new IntervalHierarchyNames()
            {
                Expedition    = "Expedition_VP",
                Site          = "Site_VP",
                Hole          = "Hole_VP",
                Core          = "Core_VP",
                Type          = "Type_VP",
                Section       = "Section_VP",
                Half          = "SectionHalf_VP",
                TopOffset     = "TopOffset_VP",
                BottomOffset  = "BottomOffset_VP",
                ArchiveTextID = "ArchiveSectionTextID_VP",
                WorkingTextID = "WorkingSectionTextID_VP",
                ParentTextID  = "ParentSectionTextID_VP"
            };

            IODPDataTable iODPDataTable = Importer.ImportDataTableFromFile(filename, columnIdentifiers);

            ICollection <LithologicDescription> descriptions = new HashSet <LithologicDescription>();

            using (DescDBContext dbContext = new DescDBContext())
            {
                try
                {
                    foreach (DataRow row in iODPDataTable.DataTable.Rows)
                    {
                        SectionInfo           section     = new SectionInfo(Importer.GetHierarchyValuesFromDataRow(row, columnIdentifiers));
                        LithologicDescription description = new LithologicDescription();
                        // description.SectionInfo = section;
                        description.SectionInfo = await DatabaseWorkflowHandler.GetSectionInfoFromDatabaseForIntervalAsync(dbContext, section).ConfigureAwait(true);

                        description.LithologicID      = row["LithologicID_VP"].ToString();
                        description.DataRow           = row;
                        description.DescriptionReport = row["Filename_VP"].ToString();;
                        description.StartOffset       = double.TryParse(row[columnIdentifiers.TopOffset].ToString(), out double startOffset) ? startOffset : -1;
                        description.EndOffset         = double.TryParse(row[columnIdentifiers.BottomOffset].ToString(), out double endOffset) ? endOffset : -1;

                        descriptions.Add(description);
                    }
                }
                catch (Exception)
                {
                    throw new Exception("Error creating lithologic description from data row");
                }
            }

            return(descriptions);
        }
示例#5
0
 public void ParseSectionInfoFromDataTable(DataTable sectionsDatatable, IntervalHierarchyNames hierarchyNames)
 {
     foreach (DataRow row in sectionsDatatable.Rows)
     {
         try
         {
             IntervalHierarchyValues values  = Importer.GetHierarchyValuesFromDataRow(row, hierarchyNames);
             SectionInfo             section = new SectionInfo(values);
             Sections.Add(section);
         }
         catch (Exception)
         {
             throw new Exception("Error parsing SectionInfo from data row");
         }
     }
 }
示例#6
0
        }                                                                  //Issue with new SectionInfo Overwriting data from database

        public LithologicDescription(SectionInfo sectionInfo)
        {
            SectionInfo = sectionInfo;
        }
示例#7
0
 /// <summary>
 /// Instantiates a new Lithologic Description
 /// </summary>
 public LithologicDescription()
 {
     SectionInfo = new SectionInfo();
 }                                                                  //Issue with new SectionInfo Overwriting data from database
示例#8
0
 /// <summary>
 /// Instantiates a new Lithologic Description
 /// </summary>
 /// <param name="SampleID">A IODP sample ID to be parsed to fill the Lithologic Description's SectionInfo fields</param>
 public LithologicDescription(string SampleID) : this()
 {
     SectionInfo = new SectionInfo(SampleID);
 }
示例#9
0
 public static SectionInfo GetSectionInfoFromCollection(ICollection <SectionInfo> sections, SectionInfo section)
 {
     return(sections.Where(record => section.Equals(record)).FirstOrDefault());
 }
示例#10
0
 /// <summary>
 /// Asynchronously gets a SectionInfo from the databse for a given measurement or lithologic description interval
 /// </summary>
 /// <param name="dbContext">A DESCDatabase context</param>
 /// <param name="interval">An interval</param>
 /// <returns>A single SectionInfo</returns>
 public static async Task <SectionInfo> GetSectionInfoFromDatabaseForIntervalAsync(DescDBContext dbContext, SectionInfo section)
 {
     return(await dbContext.Sections.Where(record =>
                                           record.Expedition == section.Expedition &&
                                           record.Site == section.Site &&
                                           record.Hole == section.Hole &&
                                           record.Core == section.Core &&
                                           record.Type == section.Type &&
                                           record.Section == section.Section).FirstOrDefaultAsync().ConfigureAwait(true));
 }
示例#11
0
        public static async Task <bool> CheckForSectionAsync(DescDBContext dBContext, SectionInfo section)
        {
            bool recordExists;

            if (section.ID != 0)
            {
                recordExists = await dBContext.Sections
                               .Where(x => x.ID == section.ID)
                               .AnyAsync().ConfigureAwait(true);
            }
            else if (section.ParentTextID != "")
            {
                recordExists = await dBContext.Sections
                               .Where(x => x.ParentTextID == section.ParentTextID)
                               .AnyAsync().ConfigureAwait(true);
            }
            else if (section.ID == 0)
            {
                recordExists = await dBContext.Sections
                               .Where(x => section.Equals(x))
                               .AnyAsync().ConfigureAwait(true);
            }
            else
            {
                return(false);
            }

            return(recordExists);
        }
示例#12
0
 public Measurement(SectionInfo sectionInfo) : this()
 {
     SectionInfo = sectionInfo;
 }
示例#13
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);
        }