Original Sciex API-III zipd Datafile Structure


PROGRAM SCIEXAPI-IIIREAD;

{The purpose of this program is to read original Sciex API III   }
{quantitation data files (zipd)collected on the Macintosh system }
{(with Motorola CPU). Compiled in ThinkPASCAL for the Macintosh  }
{on  April 23, 1993.  © Quadtech Associates, 1993.               }

CONST
 BASE = 128;
 KEEP_ON = 1;
 QUIT = 2;

VAR
 gEndit, gIsOpen: boolean;
 gResFile, gHor, gVer, gCnt, gSrcFile: Integer;
 gNMass, gNScans: Integer;
 gtheWindow: WindowPtr;
 gReply: SFReply;
 gRect: Rect;
 gS: str255;

{----------------------- PROCEDURES ----------------------- }

PROCEDURE Windowlnit;
BEGIN
 gtheWindow := GetNewWindow(Base, NIL, WindowPtr(-1));
 ShowWindow(gtheWindow);
 SetPort(gtheWindow);
 InitCursor;
 gEndit:=false;
END;


{This procedure calls a filename and stores the filename and volume }
{reference numbers in a global record accessed as gReply.fName and  }
{gReply.vRefNum, respectively. The typelist is set to ZIPD to access}
{only ZIPD Sciex Data File types, and the numtypes is set to 1      }

{---------------------------------------------------------}
PROCEDURE GetFileName (VAR replyPtr: SFReply);
VAR
 Apoint: Point;
 typelist: SFTypeList;
 numtypes: integer;
BEGIN
 Apoint.h := 100;
 Apoint.v := 100;
 typelist[0] := 'ZIPD';
 numtypes := 1;
 SFGetFile(Apoint, ", NIL, numtypes, typelist, NIL, replyPtr);
END;


{---------------------------------------------------------}
PROCEDURE DoError (msg: STRING; theSrc: Integer);
VAR
 err: OSerr;
 dummy: longint;
BEGIN
  Moveto(150, 350);
  WriteDraw('ERROR: ', msg);
  CloseResFile(gResFile);
  {dangerous to FSClose a closed file so test if open & if so Close}
  IF gIsOpen THEN
    dummy := FSClose(theSrc);
  err := NoteAlert(129, NIL);
  Halt;
END;

{---------------------------------------------------------}
PROCEDURE MoveIt (VAR VSet: Integer; VAR HSet: Integer;
                      VI, HI:Integer);
BEGIN
 VSet := VSet + VI;
 HSet := HSet + HI;
 Moveto(HSet, VSet);
END;

{Procedure to access mass intensity data}
{---------------------------------------------------------}
PROCEDURE GetData;

TYPE
 RealPtr = ^Real;

VAR
 DataPtr: RealPtr;
 Offset, Buff: Longint;
 i, j: Integer;
 A: ARRAY[1..8] OF Real;
 err: OSerr;
 watch: cursHandle;

BEGIN
  if NOT gIsOpen then
   BEGIN
    gEndIt;
    Exit;
   END;
  watch := GetCursor(4);
  SetCursor(watch^^);
  {set Buffer size and data offset based on # of masses}
  Buff := Sizeof(Real);
  Offset := Sizeof(Real) * gNMass;
  Ptr(DataPtr) := NewPtr(Sizeof(Real));
  {Process each scan in file}
  FOR i:= 1 TO gNScans DO
   BEGIN
    FOR j:= 1 TO gNMass DO
     {read each MRM mass pair into DataPtr and copy to array}
     BEGIN
      err := FSRead(gSrcFile, Buff, Ptr(DataPtr));
      A[j] := DataPtr^;
      {---------------------------------------}
      {A[j] is an element in an array of Reals}
      { process data here - print,store, etc  }
      {---------------------------------------}
     END;
   END;
END;


{Main routine here.  Declares three Record types for the 4 resources }
{accessed: GRUP, HEAD, and STAT (TEXT doesn't need a Record structure}
{Additional types are declared for STATArrayType(a 23 element array  }
{of StatType)and a ScanIndex Type which is declared but not used in  }
{this program.  The Resources are accessed sequentially and a Handle }
{is assigned which is then doubly dereferenced to access the records.}
{After printing the relevant data in each section, the Handle is     }
{released and the next resource is accessed.                         }

{---------------------------------------------------------}
PROCEDURE DoFile;

 TYPE
  GroupType = RECORD
    StartTime: Longint;
    StepSize: Real;
    ScanType: Integer;
    FirstScan: Integer;
    NumScans: Integer;
    NumMasses:Integer;
    MaxTicScan: Integer;
    TicMax: Real;
   END;
  HeadType = RECORD
    Name: PACKED ARRAY[1..20] OF Char;
    OrigiD: PACKED ARRAY[1..6] OF Char;
    Day: Integer;
    Month: Integer;
    Year: Integer;
    totScans: Integer;
    beginTime: Longint;
    lastTime: Longint;
   END;
  ScanIndex = RECORD
    offset: Longint;
    startTime: Real;
   END;
  StatType = RECORD
    ShortName: PACKED ARRAY[1..6] OF Char;
    LongName: PACKED ARRAY[1..32] OF Char;
    Flag: Integer;
    Value: Real;
   END;
  StatArrayType = ARRAY[1..23] OF StatType;
  DataArray = ARRAY[1..100] OF Real;

VAR
  i,j,z,err,srcFile,dummy,ScanT:Integer;
  VSet, HSet, VI, HI, theFlag: Integer;
  offset: Longint;
  Step, SSD, ScanRate, theValue: Real;
  fGroup: GroupType;
  fHead: HeadType;
  fStat: StatArrayType;
  fScan: Scanindex;
  theResult, DType: integer;
  S, S1: STRING;
  theString: STRING[6];
  theDate, theTime: Str255;
  UseIt: StatType;
  testC: PACKED ARRAY[1 ..4] OF Char;
  theS: ARRAY[1..8] OF STRING;
  bufSize, headerSize, runTime: longint;
  ResH, docText, IHandle: Handle;
  fGroupHandle, fHeadHandle, fStatHandle, fScanHandle: Handle;
  fGroupPtr: ^GroupType;
  fHeadPtr: ^HeadType;
  fStatPtr: ^StatArrayType;
  fScanPtr: ^Scan Index;
  DataPtr: ^DataArray;
  MI: DataArray;
  IRect, r1: Rect;

BEGIN
{Call GetFileName and store the selected file. The filename and      }
{volume reference number are displayed. Then Open the file and return}
{a file handle in srcFile. Error checking is through the returned    }
{value. The current volume must be set before accessing the resource }
{fork (only the data fork has been opened at this point). Then check }
{size of the file with the GetEOF function and store the result in   }
{bufSize of type longint.  Open the resource fork with a file handle }
{returned in gResFile and process selected resources.                }

 GetFileName(gReply);
 IF gReply.good <> True THEN
  Halt;
 s := concat('Filename: ', gReply.fName);
 gHor := 20;
 gVer := 20;
 moveto(gHor, gVer);
 SetRect(r1, 5, 5, 600, 500);
 EraseRect(r1);
 TextMode(srcCopy);
 WriteDraw(s);
 gVer := gVer + 20;
 moveto(gHor, gVer);

 I:= (FSOpen(gReply.fName, gReply.vRefNum, gsrcFile));
 IF I <> 0 THEN
  BEGIN
   IF i = -43 THEN
     Halt
   ELSE
    BEGIN
     si := concat('Cannot open file. Error Code: ', Stringof(i));
     DoError(sl, gsrcFile);
    END;
  END;

{File was opened without error - first set the File Open variable}
 gIsOpen := True;
 err := SetVol(NIL, gReply.vRefNum);
 IF err <> 0 THEN
  BEGIN
   s := concat(' in call to SetVol. Error number was ',
        Stringof(err));
   DoError(s, gsrcFile);
  END;

{SetVol Occured without error}
 err := GetEOF(gsrcFile, bufSize);
 IF err = 0 THEN
  BEGIN
   si := Stringof(bufSize);
   s := concat('Data Fork Size: ', si, bytes');
   WriteDraw(s);
  END
 ELSE
  BEGIN
   s := concat(' in call to GetEOF. Error number was ',
        Stringof(err));
   DoError(s, gsrcFile);
  END;

{GetEOF occured without error}
gResFile := OpenResFile(gReply.fName);
IF gResFile = -1 THEN
 BEGIN
  s := ('in call to OpenResFile.'); DoError(s, gsrcFile);
 END;

ResH := GetResource('TEXT', 1001);
{Note: in ZIPD files 1000 is generic; the others refer to periods - }
{e.g. 1001,1002, etc.  This program accesses only one period, 1001  }
IF ResH <> NIL THEN
 BEGIN
  SetRect(gRect, 10, 60, 300, 400);
  {Need to lock this rascal first}
  HLock(ResH);
  TextBox(Ptr(ResH^), GetHandleSize(ResH), gRect, 0);
  HUnlock(ResH);
  ReleaseResource(ResH);
 END
ELSE
 DoError(' in Accessing TEXT Resource', gsrcFile);

ResH := GetResource('GRUP', 1001);
IF ResH <> NIL THEN
 BEGIN
  HLock(ResH);
   {Coerce the fGroupPtr to a Pointer type and assign to}
   {dereferenced ResH Handle}
  Ptr(fGroupPtr) := ResH^;
   {assign pointer to fGroup}
  fGroup := GroupType(fGroupPtr^);
   {can now access fields in the fGroup Record}
  Step := (fGroup.StepSize);
  ScanT := fGroup.ScanType;
  CASE fGroup.ScanType OF
    17:  theS[2] := 'Q1 MI';
    18:  theS[2] := 'Q3 MI';
    19:  theS[2] := 'MRM';
  OTHERWISE
    {must be a spectrum scantype so can't use MacQuan}
    theS[2] := 'Not Quantifiable';
  END;
  IF fGroup.ScanType = 19 THEN
   {MRM. So correct for Parent-Daughter pair in Numlons count}
    gNMass := fGroup.NumMasses DIV 2
  ELSE
   gNMass := fGroup.NumMasses;
  gNScans := fGroup.NumScans;
  HUnlock(ResH);
  ReleaseResource(ResH);
  Vset := 60;
  HSet := 300;
  VI := 16;
  HI := 0;
  MoveIt(VSet, HSet, VI, HI);
  WriteDraw('Step Size: ', Step : 4 : 3);
  MoveIt(VSet, HSet, VI, HI);
  WriteDraw('Type of Analysis: ',theS[2]);
  MoveIt(VSet, HSet, VI, HI);
  WriteDraw('Number of Ions Monitored: ', gNMass : 2);
  MoveIt(VSet, HSet, VI, HI);
  WriteDraw('Total Scans: ', gNScans);
  gVer := VSet;
 END
ELSE
 DoError(' in Accessing GROUP Resource', gsrcFile);

ResH := GetResource('HEAD', 1000);
IF ResH <> NIL THEN
 BEGIN
  HLock(ResH);
    {same as above}
  Ptr(fHeadPtr) := ResH^;
  fHead := Headtype(fHeadPtr^);
  SSD := fHead.lastTime / fHead.totScans;
  ScanRate := fHead.totScans / fHead.lastTime;
  runTime := fHead.lastTime;
  IUDateString(fHead.beginTime, longdate, theDate);
  IUTimeString(fHead.beginTime, False, theTime);
  HUnlock(ResH);
  ReleaseResource(ResH);
  Vset := 0;
  HSet := 300;
  VI := 20;
  HI := 0;
  MoveIt(VSet, HSet, VI, HI);
  WriteDraw('Date of Analysis:   the Date);
  MoveIt(VSet, HSet, VI, HI);
  WriteDraw('Time of Analysis:   theTime);
  VSet := gVer;
  MoveIt(VSet, HSet, VI, HI);
  WriteDraw('Run Time (seconds): ', RunTime : 5);
  VI := 16;
  MoveIt(VSet, HSet, VI, HI);
  WriteDraw('Scans per second: ScanRate : 5 : 1);
  MoveIt(VSet, HSet, VI, HI);
  WriteDraw('Single scan duration: ', SSD : 5 : 2, ' seconds');
  MoveIt(VSet, HSet, VI, HI);
 END
ELSE
 DoError(' in Accessing HEAD Resource', gsrcFile);

ResH := GetResource('STAT', 1000);
  {Note - only one STAT (State File) Resource -- so 1000}
IF ResH <> NIL THEN
 BEGIN
  HLock(ResH);
  Ptr(fStatPtr) := ResH^;
  fStat := StatArrayType(fStatPtr^);
  HSet := 260;
  gVer := Vset;
  FOR i:=1 TO 8 DO
   BEGIN
    UseIt := fStat[i];
    MoveIt(VSet, HSet, VI, HI);
    CASE i OF
     2, 7, 8:
       WriteDraw(UseIt.shortName : 3, ' ', UseIt.Value : 8 : 2);
    OTHERWISE
       WriteDraw(UseIt.shortName : 2, '   ', UseIt.Value : 8 : 2);
    END;
   END;
  HSet := 370;
  VSet := gVer;
  FOR i:= 9 TO 16 DO
   BEGIN
    UseIt := fStat[i];
    MoveIt(VSet, HSet, VI, HI);
    CASE i OF
     13, 14:
      WriteDraw(UseIt.shortName :3, ' ',UseIt.Value :8 :2);
    OTHERWISE
      WriteDraw(UseIt.shortName :2, ' ',UseIt.Value :8 :2);
    END;
   END;
  HSet := 480;
  VSet := gVer;
  FOR i:= 17 TO 23 DO
   BEGIN
    UseIt := fStat[i];
    MoveIt(VSet, HSet, VI, HI);
    CASE i OF
     19:
      {This is the CC which is entered as a 4 byte Packed Array of}
      {Char - however, reading it here as a Real. So 'calculate' the}
      {true result based on the float value}
      BEGIN
       IF UseIt.Value > 2e-09 THEN
         UseIt.Value := 10
       ELSE
         UseIt.Value := 1;
       WriteDraw(UseIt.shortName : 2, '   ', UseIt.Value
      END;
     20:
       CASE ScanT OF
         19, 22, 23, 24:
         {This is MRM, Daughter, Parent or Constant Neutral}
         {'cheating' again here to show the 'proper' output}
           WriteDraw(UseIt.shortName : 2, '  Ar');
         OTHERWISE
           WriteDraw(UseIt.shortName : 2, '  OFF');
       END; {Case of ScanT}
         22, 23:
           WriteDraw(UseIt.shortName : 3, ' ', UseIt.Value : 8 : 2);
         OTHERWISE
          WriteDraw(UseIt.shortName : 2, '   ', UseIt.Value : 8 : 2);
       END;
     END;
    HUnlock(ResH);
    ReleaseResource(ResH);
  END
ELSE
  DoError(' in Accessing STAT Resource', gsrcFile);

CloseResFile(gResFile);
GetData;

{close and end program}
IF gIsOpen THEN
 BEGIN
  gIsOpen := False;
  err := FSClose(gsrcFile);
  gEndIt;
 END;
END;

{---------------------------------------------------------}
PROCEDURE GetEvent;
 BEGIN
  WHILE NOT gEndit DO
   BEGIN
    DoFile;
   END;
 END;

{==========================MAIN===========================}
BEGIN
  Windowinit;
  GetEvent;
END.

Top