private void ParseRow(int rowIndex, string[] rowAsStrings) { if ((rowIndex == 0) || (rowAsStrings[Constant.Psp.ColumnIndex.Tag] == null)) { return; } int plot = Int32.Parse(rowAsStrings[Constant.Psp.ColumnIndex.Plot]); this.plotCount = Math.Max(this.plotCount, plot); int tag = Int32.Parse(rowAsStrings[Constant.Psp.ColumnIndex.Tag]); if (this.MeasurementsByTag.TryGetValue(tag, out PspTreeMeasurementSeries? tree) == false) { FiaCode species = FiaCodeExtensions.Parse(rowAsStrings[Constant.Psp.ColumnIndex.Species]); if (species == FiaCode.Alnus) { // remap Alnus viridis ssp sinuata to Alnus rubra as no Organon variant has support species = FiaCode.AlnusRubra; } tree = new PspTreeMeasurementSeries(tag, species); this.MeasurementsByTag.Add(tag, tree); } int status = Int32.Parse(rowAsStrings[Constant.Psp.ColumnIndex.Status]); int year = Int32.Parse(rowAsStrings[Constant.Psp.ColumnIndex.Year]); if (status < Constant.Psp.TreeStatus.Dead) // dead or not found trees lack diameter measurements { float dbhInCentimeters = float.Parse(rowAsStrings[Constant.Psp.ColumnIndex.Dbh]); Debug.Assert(dbhInCentimeters >= 5.0F); if (tree.DbhInCentimetersByYear.TryAdd(year, dbhInCentimeters) == false) { // in case of a conflict, use whichever DBH comes last for consistency with the code above. // For example, tree 8824 in RS39 has two 2013 records. tree.DbhInCentimetersByYear[year] = dbhInCentimeters; } } this.MeasurementYears.Add(year); }
private void ParseRow(int rowIndex, string[] rowAsStrings) { if (rowIndex == 0) { // parse header for (int columnIndex = 0; columnIndex < rowAsStrings.Length; ++columnIndex) { string columnHeader = rowAsStrings[columnIndex]; if (String.IsNullOrWhiteSpace(columnHeader)) { break; } if (columnHeader.Equals("species", StringComparison.OrdinalIgnoreCase)) { this.speciesColumnIndex = columnIndex; } else if (columnHeader.Equals("plot", StringComparison.OrdinalIgnoreCase)) { this.plotColumnIndex = columnIndex; } else if (columnHeader.Equals("tree", StringComparison.OrdinalIgnoreCase)) { this.treeColumnIndex = columnIndex; } else if (columnHeader.Equals("age", StringComparison.OrdinalIgnoreCase)) { this.ageColumnIndex = columnIndex; } else if (columnHeader.StartsWith("dbh", StringComparison.OrdinalIgnoreCase)) { this.dbhColumnIndex = columnIndex; if (columnHeader.EndsWith("mm", StringComparison.Ordinal)) { this.dbhScaleFactor = 0.1F; // otherwise, assume cm } } else if (columnHeader.Equals("height", StringComparison.OrdinalIgnoreCase) || columnHeader.Equals("height, m", StringComparison.OrdinalIgnoreCase)) { this.heightColumnIndex = columnIndex; } else if (columnHeader.Equals("height, dm", StringComparison.OrdinalIgnoreCase)) { this.heightColumnIndex = columnIndex; this.heightScaleFactor = 0.1F; // otherwise, assume m } else if (columnHeader.StartsWith("expansion factor", StringComparison.OrdinalIgnoreCase)) { this.expansionFactorColumnIndex = columnIndex; } else if (columnHeader.Equals("treecond", StringComparison.OrdinalIgnoreCase)) { this.treeConditionColumnIndex = columnIndex; } else { // ignore column for now } } // check header if (this.speciesColumnIndex < 0) { throw new ArgumentOutOfRangeException(nameof(this.speciesColumnIndex), "Species column not found."); } if (this.plotColumnIndex < 0) { throw new ArgumentOutOfRangeException(nameof(this.plotColumnIndex), "Plot column not found."); } if (this.treeColumnIndex < 0) { throw new ArgumentOutOfRangeException(nameof(this.treeColumnIndex), "Tree number column not found."); } if (this.ageColumnIndex < 0) { throw new ArgumentOutOfRangeException(nameof(this.ageColumnIndex), "Tree age column not found."); } if (this.dbhColumnIndex < 0) { throw new ArgumentOutOfRangeException(nameof(this.dbhColumnIndex), "DBH column not found."); } if (this.heightColumnIndex < 0) { throw new ArgumentOutOfRangeException(nameof(this.heightColumnIndex), "Height column not found."); } if ((this.expansionFactorColumnIndex < 0) && (this.defaultExpansionFactor <= 0.0F)) { throw new ArgumentOutOfRangeException(nameof(this.expansionFactorColumnIndex), "Expansion factor column not found."); } return; } if (rowAsStrings[this.treeColumnIndex] == null) { return; // assume end of data in file } // filter by plot int plot = Int32.Parse(rowAsStrings[this.plotColumnIndex]); bool treeInPlotList = false; for (int idIndex = 0; idIndex < this.plotIDs.Count; ++idIndex) { if (plot == this.plotIDs[idIndex]) { treeInPlotList = true; break; } } if (treeInPlotList == false) { // tree is not in the list of plots specified return; } // exclude dead trees if (this.treeConditionColumnIndex >= 0) { if (String.IsNullOrWhiteSpace(rowAsStrings[this.treeConditionColumnIndex]) == false) { int treeCondition = Int32.Parse(rowAsStrings[this.treeConditionColumnIndex]); if (treeCondition == Constant.MalcolmKnapp.TreeCondition.Dead) { return; } } } // parse data int age = Int32.Parse(rowAsStrings[this.ageColumnIndex]); if (this.byAge.TryGetValue(age, out Stand? plotAtAge) == false) { plotAtAge = new Stand(); this.byAge.Add(age, plotAtAge); } FiaCode species = FiaCodeExtensions.Parse(rowAsStrings[this.speciesColumnIndex]); if (plotAtAge.TreesBySpecies.TryGetValue(species, out Trees? treesOfSpecies) == false) { treesOfSpecies = new Trees(species, 1, Units.Metric); plotAtAge.TreesBySpecies.Add(species, treesOfSpecies); } int tag = Int32.Parse(rowAsStrings[this.treeColumnIndex]); string dbhAsString = rowAsStrings[this.dbhColumnIndex]; float dbh = Single.NaN; if ((String.IsNullOrWhiteSpace(dbhAsString) == false) && (String.Equals(dbhAsString, "NA", StringComparison.OrdinalIgnoreCase) == false)) { dbh = this.dbhScaleFactor * Single.Parse(dbhAsString); } string heightAsString = rowAsStrings[this.heightColumnIndex]; float height = Single.NaN; if ((String.IsNullOrWhiteSpace(heightAsString) == false) && (String.Equals(heightAsString, "NA", StringComparison.OrdinalIgnoreCase) == false)) { height = this.heightScaleFactor * Single.Parse(heightAsString); } float expansionFactor = this.defaultExpansionFactor; if (this.expansionFactorColumnIndex >= 0) { expansionFactor = Single.Parse(rowAsStrings[this.expansionFactorColumnIndex]); } // add trees with placeholder crown ratio treesOfSpecies.Add(tag, dbh, height, this.defaultCrownRatio, expansionFactor); }