HP Early MSD (Pascal) Chemstation Datafile Structure


{====================================================================
  This Delphi unit contains routines to access and manipulate data 
    from Hewlett-Packard MSD Data Files.  Derived from published
      Hewlett-Packard documentation.  © Quadtech Associates, 1997.
=====================================================================}

unit Hpunit3;

interface

Uses StLArr,SysUtils, Dialogs;  //uses TurboPower SysTools StLArr
                                
Type
 Byte = 0 .. 255;
 String80 = String[80];  {for filenames}
 gTicType
 Int_File_Type = File of SmallInt;

 Header_Info_Type = Record
   File_num_Str : String[3];
   File_String : String[19];
   Data_name : String[61];
   Misc_info : String[61];
   Operator : String[29];
   Date_time : String[29];
   Inst_model : String[9];
   Inlet : String[9];
   Method_File : String[19];
   File_type : LongInt;
   Seq_index : SmallInt;
   Als_bottle : SmallInt;
   Replicate : SmallInt;
   Dir_ent_type : SmallInt;
   Dir_Offset : LongInt;
   Data_Offset : LongInt;
   Run_Tbl_Offset : LongInt;
   Norm_Offset : LongInt;
   Extra_Records : SmallInt;
   Num_Records : LongInt;
   Start_rTime : LongInt;
   End_rTime : LongInt;
   Max_Signal : LongInt;
   Min_Signal : LongInt;
  End;

 File_Header_Type = Record
   Info : Header_Info_Type;
   Filler: Packed Array [1..(512 - SizeOf (Header_Info_Type))]
           of Byte;
  End;

 Spec_Rec_Type = Record
   NumWds : SmallInt;
   RetTime : Longint;
   WdsLess3 : SmallInt;
   DataType : SmallInt;
   Status : SmallInt;
   NumPks : SmallInt;
   BasePk : Word;
   BaseAb : SmallInt;
  End;

 Mass_Abund_Type = Packed Record
   Mass : Word;
   Abund : Longint;
  End;

  Function SwapLong (Incoming:LongInt):LongInt;
  Function SwapDble (Incoming:Double):Double;
  Function Unpack (Incoming:Word):LongInt;
  Procedure Read_Data_Header (File_Name : String;
                              Var Data_Header : File_Header_Type);
  Procedure Get_Tic (File_Name:String; DirOff:LongInt;
                     NumRecs:LongInt);
  Procedure Get_Spec_Head (File_Name:String; DirOff:LongInt;
                           Var theRTime:LongInt;
                           Var SpecHead:Spec_Rec_Type;
                           Var TotAb:LongInt);
  Procedure Get_Spec_Data (File_Name:String; DirOff:LongInt;
                           SpecRecs:SmallInt;Caller:SmallInt);

implementation

{ ===================== Variable Declarations ==================== }

 Var
  Header : File_Header_Type;
  SwapInt : LongInt;
  TheDir_Offset : LongInt;
  Data_File : Int_File_Type;
  File_Name : String;
  Output_File_Name : String;
  NumRecs, DirOff: LongInt;
  SpecRecs : SmallInt;
  ThisArray: array [1..3] of LongInt;
  gTicType:TStLArray;
  MA,MD,ME:Array[1..1000] of Mass_Abund_Type;

{ ========================== PROCEDURES ============================ }

  Function SwapLong (Incoming:LongInt):LongInt;
   { This routine swaps type LongInt variables.  These variables 
     are all stored in reverse byte order.  
     Last Edited: Dec 2, 1995}
   type
    AType = Array[1..4] of Byte;
   var
    i,j:Integer;
    A1,A2:AType;
    L2: Longint;

   begin
     A1:=AType(Incoming);
     j:=4;
     for i:=1 to 4 do
      begin
       A2[j]:=A1[i];
       j:=j-1;
      end;
     L2 := LongInt(A2);
     SwapLong := L2;
   end;

 {===================================================================}
  Function SwapDble (Incoming:Double):Double;
   { This routine swaps type Double variables.  
     Last Edited: Dec 2, 1995.}
   type
    AType = array[1..8] of Byte;
   var
    i,j:Integer;
    A1,A2:AType;

   begin
     A1:=AType(Incoming);
     j:=8;
     for i:=1 to 8 do
      begin
       A2[j]:=A1[i];
       j:=j-1;
      end;
     SwapDble:=Double(A2);
   end;

 {===================================================================}
  Function Unpack (Incoming:Word):LongInt;
   { This routine is used to unpack HP Packed-Abundance values.  The
     HP Packed-Abundance value is in a 16-bit (unsigned) integer such
     that the two high-order bits are the scale and the remaining 14
     bits are the mantissa.  Then abundance = mantissa * (8 ^ scale).
     Last edited on June 7, 1997}
   var
    J : Integer;

   begin
     J:=HI(Incoming) DIV 64;
     Case J of
      0: J:=1;
      1: J:=8;
      2: J:=64;
      3: J:=512;
     end;
    Unpack := (Longint(HI(Incoming) AND 63)*256 + LO(Incoming))*J;
   end;

 {===================================================================}
  Procedure Read_Data_Header (File_Name : String;
                             Var Data_Header : File_Header_Type);
  {  This routine is used to assign file labels and read & store the
     Data Header information from the HP data file.
     Last edited December 2, 1995 }
  var
   Header_File : file of File_Header_Type;

   begin
    try
     Assign (Header_File, File_Name);
     Reset (Header_File);
     Read (Header_File, Data_Header);
     Close (Header_File)
    except
     MessageDlg('Error in accessing file.',
               mtInformation,[mbOk], 0);
     Close(Header_File);
     exit;
    end;
   end;

 {===================================================================}
  Procedure Get_Tic (File_Name:String; DirOff:LongInt;
                    NumRecs:LongInt);
{ Procedure to obtain the Tic data from the file.  These data are
  extracted from the directory records which also provides offset
  information for individual spectra.  There are 3 longints per record
  in the following order: (1)file offset; (2)RT;(3) Total abundance.
  Last edited Dec 6, 1995 }
  var
   Tic_File: file of SmallInt;
   TheEntry: array [1..2] of SmallInt;
   I, J, k:SmallInt;
  begin
   Assign (Tic_File, File_Name);
   Reset (Tic_File);
   Seek (Tic_File, DirOff - 1);
   If (Assigned(gTicType)) then gTicType.Free;
   gTicType := TStLArray.Create(NumRecs+1,SizeOf(ThisArray));
   gTicType.ElementsStorable := True;
   k:=0;
   for I:=1 to NumRecs do
    begin
     for J:= 1 to 3 do
      begin
       Read (Tic_File, TheEntry[1]);
       Read (Tic_File, TheEntry[2]);
       ThisArray[J]:= SwapLong(LongInt(TheEntry));
      end;
     gTicType.Put(i,ThisArray);
     k:=k+1;
     if k= 10 then
      begin
       k:=0;
       Form1.Label14.Caption:=IntToStr(I);
       Form1.Label14.Refresh;
      end;
    end;
   Close(Tic_File);
  end;

 {===================================================================}
  Procedure Get_Spec_Head (File_Name:String; DirOff:LongInt;
                           Var theRTime:LongInt;
                           Var SpecHead:Spec_Rec_Type;
                           Var TotAb:LongInt);
  { Procedure to recover a selected spectrums Header information. 
    This is then used by the Get_Spec_Data procedure below.
    Last edited  December 23, 1995 }
  var
   Spec_File: file of SmallInt;
   RTime: array [1..2] of SmallInt;
   tStr:String;
   RT:Single;

  begin
   Assign (Spec_File, File_Name);
   Reset (Spec_File);
   Seek (Spec_File, DirOff - 1);
   Read (Spec_File, SpecHead.NumWds);
   SpecHead.NumWds := Swap(SpecHead.NumWds);
   Read (Spec_File, RTime[1]);
   Read (Spec_File, RTime[2]);
   theRTime := SwapLong(Longint(RTime));
   Read (Spec_File, SpecHead.WdsLess3);
   SpecHead.WdsLess3 := Swap(SpecHead.WdsLess3);
   Read (Spec_File, SpecHead.DataType);
   SpecHead.DataType := Swap(SpecHead.DataType);
   Read (Spec_File, SpecHead.Status);
   SpecHead.Status := Swap(SpecHead.Status);
   Read (Spec_File, SpecHead.NumPks);
   SpecHead.NumPks := Swap(SpecHead.NumPks);
   SpecRecs := SpecHead.NumPks;
   Read (Spec_File, SmallInt(SpecHead.BasePk));
   SpecHead.BasePk := Swap(SpecHead.BasePk);
   Read (Spec_File, SpecHead.BaseAb);
   TotAb:=Unpack(Swap(SpecHead.BaseAb));
   Close (Spec_File);
   RT:=theRTime/60000;
  end;


 {===================================================================}
  Procedure Get_Spec_Data (File_Name:String; DirOff:LongInt;
                          SpecRecs:SmallInt; Caller:SmallInt);
  { Procedure to recover the mass & abundance information for a
    spectrum and store it in a typed-array (MA).  NOTE: the array
    dimensions here are only temporary.  This should be changed to
    dynamically alocate memory for the array on the heap using size
    information from the Get_Spec_Head call.
    Last edited on June 7, 1997 }
  var
   Spec_File: file of Word;
   I, Incoming : Word;

  begin
   Assign (Spec_File, File_Name);
   Reset (Spec_File);
   Seek (Spec_File, (DirOff-1) + SizeOf(Spec_Rec_Type) DIV 2);
   If Caller=0 then     {standard procs (Not MDA)}
    begin
     MA[0].Abund:=0;
     for I := 1 to SpecRecs do
      begin
       Read (Spec_File, Incoming);
       MA[I].Mass := Swap(Incoming);
       Read (Spec_File, Incoming);
       MA[I].Abund := Unpack(Swap(Incoming));
      end;
    end
   else If Caller=1 then       {MDA Call}
     for I := 1 to SpecRecs do
      begin
       Read (Spec_File, Incoming);
       MD[I].Mass := Swap(Incoming);
       Read (Spec_File, Incoming);
       MD[I].Abund := Unpack(Swap(Incoming));
      end
   else                        {EXTion call}
     for i:=1 to SpecRecs Do
       begin
       Read (Spec_File, Incoming);
       ME[I].Mass := Swap(Incoming);
       Read (Spec_File, Incoming);
       ME[I].Abund := Unpack(Swap(Incoming));
      end;
   Close (Spec_File);
  end;

end.

Top