next up previous contents
Next: The .slf File Up: Program Execution & Data Previous: The .elev File
Go to: SmartForest Home Printer-friendly: sf-impl.pdf


The .trl File

The function called trlReader is responsible for parsing the .trl file. It utilizes the scanner found in tokenizer.c. The .trl file is formatted like the output of a database query. Thus trlReader is equipped to detect when it sees the periodic header information that the query reports. Once detected, the periodic header is simply skipped.

The algorithm that this parser follows is given below:

  1. Initialize invalidTree to FALSE
  2. While there is still data in the file
    1. Skip the periodic header
    2. Read the stand identifier (standID)
    3. Determine whether a stand already exists for this stand identifier. If so, use it. Otherwise, create a new stand for the stand identifier. For some reason, the stand is represented by the TreeList data type. It's an awful name since the stand contains, among other things, a linked list of trees represented by the Node data type. Holy terrible names.
    4. While we haven't detected the new periodic header
      1. We want to create a new empty Node to hold the current line of data. This new Node will be at the head of the stand's linked list of trees. There are three cases when obtaining the ``empty'' Node:
        • If we have detected an invalid tree via invalidTree and if the stand has a non-empty linked list of trees, then use the current head of that list as the ``empty'' Node. Note that the data currently in that Node will be overwritten.
        • If we have detected an invalid tree via invalidTree and if the stand has an empty linked list of trees, then create a new Node, add it as the new head of the stand's linked list and use the new Node to hold the current line's data.
        • If we did not detect an invalid tree via invalidTree, then create a new Node, add it as the new head of the stand's linked list and use the new Node to hold the current line's data.

      2. Parse the current line into the Node. The fields are described in the table below.
      3. If the value read for the CURRHT field is $< 5$, then the tree is considered invalid. Otherwise it is considered valid. invalidTree is set accordingly.
      4. If we reach the end of the file here, simply fall out of the inner while loop. The outer while will subsequently detect that we are at the end of the file and end nicely.

The information that is stored for each tree in the stand's linked list is as follows:

Never Data Field Purpose
Used Type Name  
X int TREENUMBER The first four digits are the plot number. The last three
      digits are the tree number on the plot.
X int TREEINDX Forest Vegetation Simulator's (FVS) primary key for this
      record.
  char[5] SPCD Species code. These are different for the different
      geographic variants of FVS.
X int SPNO Species number. These are different for the different
      geographic variants of FVS. The treelist file is sorted by this
      column and secondarily by TREENUMBER.
  int TRCL Tree class. 1==desirable, 2==acceptable, 3==poor
X int SSCD Special status code. User defined, no inherent meaning.
X int PNTNUM Point (or plot) number. The point is the basic unit in the
      sampling design.
  float TREESPERACRE Trees per acre.
  float MORTALPERACRE Number of trees per acre that went to tree heaven during
      the cycle.
  float CURRDIAM Current diameter (inches)
  float DIAMINCR Diameter increment (inches). This is the change in
      diameter during the cycle.
  float CURRHT Current height (feet). Must be $\ge 5.0$.
  float HTINCR Height increment (feet). This is the change in height
      during the cycle.
  int CR Crown ratio--crown length as a percentage of total tree
      height.
  float MAXCW Maximum crown width. This is the diameter of the crown
      at the longest axis. No units given (assumed feet).
  int MS Hawksworth mistletoe rating code. Range 0-6.
      0==uninfested, 6==completely/heavily infested.
X float BATILE Basal area percentile. This is the ranking of that tree record
      in terms of the total basal area of the stand.
X int POINTBAL Point basal area larger. This is the total basal area per acre
      represented by tree records from the same plot (or point)
      that have a larger diameter than that record.
  float TOTCUFTVOL Total cubic foot volume per tree.
  float MCHCUFTVOL Merchantable cubic foot volume per tree.
  float MCHBDFTVOL Merchantable board foot volume per tree.
  int MCDF Merchantable cubic foot defect per tree.
  int BFDF Merchantable board foot defect per tree.
X int TRCHT Truncated height (feet). This is the height to a broken top or
      to topkill.

Once the data is read from the file into the Tree struct, it may only be accessed using the findTreeList accessor. findTreeList takes a stand identifier as a parameter and returns the corresponding linked list of trees.

The data in the Tree struct is used (almost)1 solely as an interface to the .trl file. It is used to populate the tree_arrays global variable of type TREE_TYPE in function F_ReadTreeList in file standInterface.c. There is also a global variable called tree_default that is never initialized; the code that performs initialization is currently commented out. Note that this ``file interface'' data is (almost) always accessed via a path from F_LoadStandData found in standInterface.c.

tree_arrays-$>$tree_types Field Name Initialized by Tree Field
(Application Abstraction) (File Interface)
species SPCD
num_trees TREESPERACRE
ave_dbh CURRDIAM
ave_height CURRHT
ave_cr CR
db_height MAXCW
age MS
tree_status TRCL
height_gro HTINCR
diameter_gro DIAMINCR
volume_gro MCHBDFTVOL
total_cubic TOTCUFTVOL
merch_cubic MCHCUFTVOL
assortment1 MCDF
assortment2 BFDF
x_coord MORTALPERACRE

There are four fields in the TREE_TYPE structure that are not initialized with values that are read from the .trl file -- these are calculated from the other fields once they are populated. The reason for the ``almost'' qualifier in the previous paragraph is that these four fields are not simply file interfaces but they are also the application's data abstractions. It is odd that the application's original authors would be inconsistent with the treatment of these four fields. This could be a place for improvement in the design since the TREE_TYPE structure consumes a large amount of memory that, potentially, could be freed once the data abstraction variables were populated. Until these four fields are treated consistently with the other fields as file interfaces only and not also as data abstractions, that is not possible. These four special fields are:

Field Name Purpose Initialization
DBH Average diameter at breast ave_dbh
  height (meters)  
crown_height crown height of the trees If ave_cr = 0, it is 0.6667 * ave_height
  (meters) Otherwise it is ave_cr * ave_height / 100.0
base_height (meters) ave_height - crown_height
crown_diameter (meters) If ave_height $>$ 40 feet, it is 10 feet.
    If ave_height $\le$ 40 feet, it is 0.4 * ave_height.
    Convert final result to meters.

Some unit conversions are necessary for the four computed fields defined above.


next up previous contents
Next: The .slf File Up: Program Execution & Data Previous: The .elev File
Matthew S. Davis
2002-08-07