<> <> <> DIRECTORY AIS USING [WriteSample, Raster, RasterPart, FRef, CreateFile, WRef, OpenWindow, CloseWindow, CloseFile], Basics USING [BITSHIFT], BasicTime USING [GMT, Now, Period], Convert USING [CardFromRope, Error], Eikonix, EikonixProtocol USING [BitsPerPoint, Color, Height, Width, SampleLength], FileNames USING [FileWithSearchRules], FS USING [ComponentPositions, Error, ExpandName, StreamOpen], IO USING [card, GetCard, Close, PutChar, PutF, PutFR, PutRope, real, rope, STREAM], PieViewers USING [Set], Process USING [Pause, MsecToTicks, Yield], Rope USING [IsEmpty, ROPE], ViewerClasses USING [Viewer], ViewerTools USING [GetContents, SetContents], ScannerInternal ; ScannerOpsImpl: CEDAR MONITOR IMPORTS AIS, Basics, BasicTime, Convert, Eikonix, FileNames, FS, IO, PieViewers, Process, Rope, ViewerTools EXPORTS ScannerInternal ~ BEGIN OPEN Tool: ScannerInternal; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; bits: EikonixProtocol.BitsPerPoint _ bp8; LoadCalFile: PUBLIC PROC [tool: Tool.Tool] = BEGIN calFile: ROPE _ tool.scannerCalFile; h: Eikonix.Handle; s: STREAM; fullPath: ROPE; ambiguous: BOOL; it: ROPE ~ ViewerTools.GetContents[tool.iTimeViewer]; iTime: Eikonix.IntegrationTime _ 0; iTime _ Convert.CardFromRope[it ! Convert.Error => {iTime _ 4500; CONTINUE}]; calFile _ IO.PutFR["%g-%g.txt", IO.rope[calFile], IO.card[iTime]]; [fullPath: fullPath, ambiguous: ambiguous] _ FileNames.FileWithSearchRules[root: calFile, defaultExtension: "txt", searchRules: tool.searchRules]; calFile _ fullPath; IF Rope.IsEmpty[calFile] THEN calFile _ IO.PutFR["%g-%g.txt", IO.rope[calFile], IO.card[iTime]]; tool.out.PutF["Loading calibration from %g .. ", IO.rope[calFile]]; s _ FS.StreamOpen[calFile ! FS.Error => {tool.out.PutRope[error.explanation]; GOTO Out}]; tool.dc _ NEW [Eikonix.NBufferRecord]; tool.gain _ NEW[Eikonix.NBufferRecord]; tool.iTime _ iTime; IF IO.GetCard[s] # iTime THEN GOTO Out; ViewerTools.SetContents[tool.iTimeViewer, IO.PutFR["%g", IO.card[tool.iTime]]]; FOR i: CARDINAL IN Eikonix.PixelIndex DO p: CARDINAL _ IO.GetCard[s]; IF p # i THEN ERROR; tool.dc[p] _ IO.GetCard[s]; tool.gain[p] _ IO.GetCard[s]; ENDLOOP; IO.Close[s]; tool.out.PutRope[" loading normalizer .. "]; BEGIN ENABLE Eikonix.EikonixError => {tool.out.PutRope[ec]; Eikonix.Close[h]; GOTO Out}; h _ Eikonix.Open [tool.params.defaultServer]; Eikonix.LoadNormalizer[h, tool.dc, tool.gain]; Eikonix.SetIntegrationTime[h, iTime, bits]; Eikonix.SelectWheel[h, tool.color]; Eikonix.Close[h]; END; tool.out.PutRope["Done\n"]; EXITS Out => {tool.dc _ tool.gain _ NIL; tool.out.PutRope[" Error.\n"]; RETURN;}; END; <<>> <> <> <> <> <> < {tool.out.PutRope[error.explanation]; GOTO Out}]; >> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < {tool.dc _ tool.gain _ NIL; tool.out.PutRope[" Error.\n"]; RETURN;};>> <> <<>> SaveCalFile: PUBLIC PROC [tool: Tool.Tool] = BEGIN calFile: ROPE _ tool.scannerCalFile; cp: FS.ComponentPositions _ FS.ExpandName[calFile].cp; s: STREAM; wDir: ROPE _ ViewerTools.GetContents[tool.wDirViewer]; it: ROPE ~ ViewerTools.GetContents[tool.iTimeViewer]; iTime: Eikonix.IntegrationTime _ 0; iTime _ Convert.CardFromRope[it ! Convert.Error => {iTime _ 4500; CONTINUE}]; calFile _ IO.PutFR["%g-%g.txt", IO.rope[calFile], IO.card[iTime]]; s _ FS.StreamOpen[fileName: calFile, accessOptions: create, wDir: wDir ! FS.Error => {tool.out.PutRope[error.explanation]; ERROR ABORTED}]; IO.PutF[s, "%g\n", IO.card[tool.iTime]]; <> FOR i: CARDINAL IN Eikonix.PixelIndex DO IO.PutF[s, "%g %g %g ", IO.card[i], IO.card[tool.dc[i]], IO.card[tool.gain[i]]]; <> <> <> IO.PutChar[s, '\n]; ENDLOOP; IO.Close[s]; END; Calibrate: PUBLIC PROC [tool: Tool.Tool] = BEGIN OPEN Eikonix; BEGIN ENABLE { UNWIND => NULL; Eikonix.EikonixError => {tool.out.PutRope[ec]; ERROR ABORTED}}; tool.out.PutF["Calibrating at integration time: %g .. dark .. ", IO.card[tool.iTime]]; tool.dc _ CalibrateDarkCurrent[tool.params.defaultServer, tool.iTime]; tool.out.PutRope[" lights .. "]; tool.gain _ CalibrateLightsOn[server: tool.params.defaultServer, t: tool.iTime, dc: tool.dc, color: tool.color]; tool.out.PutRope[" Done\n"]; <> <> <> <> <> <> <> < Clear, Red => Red, Green => Green, Blue => Blue, ENDCASE => ERROR)];>> <> <> END; -- of begin for enable SaveCalFile[tool]; END; SampleScanToAisFile: PUBLIC PROC [tool: Tool.Tool, fileName: ROPE, iTime: Eikonix.IntegrationTime] = BEGIN OPEN Eikonix; h: Handle _ NIL; f: AIS.FRef _ NIL; w: AIS.WRef; raster: AIS.Raster; BEGIN -- THis is for the ABORTED stuff. BEGIN ENABLE { UNWIND => {IF h # NIL THEN {TurnOffLights[h ! EikonixError => CONTINUE]; Close[h ! EikonixError => CONTINUE]}; IF f # NIL THEN AIS.CloseFile[f];}; Eikonix.EikonixError => {tool.out.PutRope[ec]; ERROR ABORTED}}; proc: LineConsumerProc = BEGIN <> FOR i: CARDINAL IN [0 .. b.cnt) DO IF bits = bp8 THEN AIS.WriteSample[w, b[i], scanNumber/EikonixProtocol.SampleLength, i] ELSE { sample: CARDINAL _ Basics.BITSHIFT[b[i], -4]; AIS.WriteSample[w, sample, scanNumber/EikonixProtocol.SampleLength, i]}; ENDLOOP; ViewerTools.SetContents[tool.atScanViewer, IO.PutFR["%G", IO.card[scanNumber]]]; RETURN [b]; END; tool.out.PutF["Opening %g .. ", IO.rope[fileName]]; raster _ NEW[AIS.RasterPart _ [scanCount: EikonixProtocol.Width/EikonixProtocol.SampleLength, scanLength: EikonixProtocol.Height/EikonixProtocol.SampleLength, scanMode: rd, bitsPerPixel: 8, linesPerBlock: -1, paddingPerBlock: 0]]; f _ AIS.CreateFile[fileName, raster]; BEGIN b: Buffer _ NEW [BufferRecord[EikonixProtocol.Width/EikonixProtocol.SampleLength]]; w _ AIS.OpenWindow[f]; h _ Open [tool.params.defaultServer]; tool.out.PutRope[" Lights .. "]; <> <> <> TurnOnLights[h]; tool.out.PutRope[" Sample Scanning .. "]; SampleScan[h, b, proc, bits]; TurnOffLights[h]; AIS.CloseWindow[w]; AIS.CloseFile[f]; Close[h ! EikonixError => CONTINUE]; END; END; END; END; Monitor: PROC [tool: Tool.Tool, lineStart: Eikonix.LineIndex, lineCount: Eikonix.LineCount] = BEGIN DO scan: CARDINAL = GetScan[]; kill: BOOL = GetKill[]; num: REAL = 100.0 - (((scan - lineStart) * 100.0)/lineCount); IF tool = NIL THEN RETURN; IF kill THEN RETURN ELSE ViewerTools.SetContents[tool.atScanViewer, IO.PutFR["%G", IO.card[scan]]]; PieViewers.Set[tool.pieBW, (IF num NOT IN [0.0 .. 100.0] THEN 0.0 ELSE num)]; Process.Pause[Process.MsecToTicks[1000]]; ENDLOOP; END; scanLine: CARDINAL _ 0; kill: BOOL _ FALSE; GetKill: ENTRY PROC [] RETURNS [BOOL] = {RETURN[kill]}; SetKill: ENTRY PROC [k: BOOL] = {kill _ k}; GetScan: ENTRY PROC [] RETURNS [CARDINAL] = {RETURN[scanLine]}; SetScan: ENTRY PROC [line: CARDINAL] = {scanLine_ line}; ScanToAisFile: PUBLIC PROC [tool: Tool.Tool, fileName: ROPE, iTime: Eikonix.IntegrationTime, color: EikonixProtocol.Color _ Clear, lineStart: Eikonix.LineIndex _ 0, pixelStart: Eikonix.PixelIndex _ 0, lineCount: Eikonix.LineCount _ 2048, pixelCount: Eikonix.PixelCount _ 2048] = BEGIN OPEN Eikonix; h: Handle _ NIL; f: AIS.FRef _ NIL; w: AIS.WRef; raster: AIS.Raster; pr: PROCESS _ NIL; BEGIN -- THis is for the ABORTED stuff. BEGIN ENABLE { UNWIND => TRUSTED {IF h # NIL THEN {TurnOffLights[h ! EikonixError => CONTINUE]; Close[h ! EikonixError => CONTINUE]}; IF f # NIL THEN AIS.CloseFile[f]; SetKill[TRUE]; IF pr # NIL THEN JOIN pr; PieViewers.Set[tool.pieBW, 0]; }; Eikonix.EikonixError => {tool.out.PutRope[ec]; ERROR ABORTED}}; proc: LineConsumerProc = BEGIN <> FOR i: CARDINAL IN [0 .. pixelCount) DO IF bits = bp8 THEN AIS.WriteSample[w, b[i], scanNumber, i] ELSE AIS.WriteSample[w, Basics.BITSHIFT[b[i], -4], scanNumber, i]; ENDLOOP; Process.Yield[]; SetScan[scanNumber + lineStart]; IF tool.abort THEN {tool.abort _ FALSE; ERROR ABORTED}; RETURN [b]; END; tool.out.PutF["Opening %g .. ", IO.rope[fileName]]; PieViewers.Set[tool.pieBW, 100]; raster _ NEW[AIS.RasterPart _ [scanCount: lineCount, scanLength: pixelCount, scanMode: rd, bitsPerPixel: 8, linesPerBlock: -1, paddingPerBlock: 0]]; f _ AIS.CreateFile[fileName, raster]; SetKill[FALSE]; pr _ FORK Monitor[tool, lineStart, lineCount]; BEGIN ndc, ngain: Eikonix.NBuffer _ NIL; <> b: Buffer _ NEW [BufferRecord[EikonixProtocol.Width]]; startTime: BasicTime.GMT; < Clear, Red => Red, Green => Green, Blue => Blue, ENDCASE => ERROR);>> w _ AIS.OpenWindow[f]; h _ Open [tool.params.defaultServer]; tool.out.PutRope[" Lights .. "]; <> <> <> TurnOnLights[h]; <> <> <> <<[min: min, max: max] _ ScanForMinMax[h, lineStart, pixelStart, lineCount, pixelCount];>> <<[ndc, ngain] _ ComputeCorrectedCalibrate[tool.dc, tool.gain, min, max];>> <> <> <> <> tool.out.PutRope[" Scanning .. "]; startTime _ BasicTime.Now[]; Scan[h, lineStart, pixelStart, lineCount, pixelCount, b, proc, bits]; TurnOffLights[h]; tool.out.PutF[" %-3.2f min .. ", IO.real[BasicTime.Period[startTime, BasicTime.Now[]]/60.0]]; <> AIS.CloseWindow[w]; AIS.CloseFile[f]; Close[h ! EikonixError => CONTINUE]; SetKill[TRUE]; TRUSTED {IF pr # NIL THEN JOIN pr}; PieViewers.Set[tool.pieBW, 0]; END; END; END; END; ReadCalibration: PUBLIC PROC [fileName: ROPE, wDir: ROPE _ NIL] RETURNS [dc, gain: Eikonix.NBuffer] = BEGIN s: STREAM _ FS.StreamOpen[FS.ExpandName[fileName, wDir].fullFName]; dc _ NEW [Eikonix.NBufferRecord]; gain _ NEW[Eikonix.NBufferRecord]; FOR i: CARDINAL IN Eikonix.PixelIndex DO p: CARDINAL _ IO.GetCard[s]; IF p # i THEN ERROR; dc[p] _ IO.GetCard[s]; gain[p] _ IO.GetCard[s]; ENDLOOP; END; <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < CONTINUE];>> <> <> END.