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; 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"]; 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; w _ AIS.OpenWindow[f]; h _ Open [tool.params.defaultServer]; tool.out.PutRope[" Lights .. "]; TurnOnLights[h]; 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; END.  ScannerOpsImpl.mesa Copyright (C) 1985, Xerox Corporation. All rights reserved. Last edited by Tim Diebert: January 30, 1986 10:17:33 am PST LoadCalFile: PUBLIC PROC [tool: Tool.Tool] = BEGIN calFile: ROPE ~ tool.scannerCalFile; s: STREAM; 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]; FOR c: Tool.Color IN Tool.Color DO tool.colorDC[c] _ NEW [Eikonix.NBufferRecord]; tool.colorGain[c] _ NEW [Eikonix.NBufferRecord]; ENDLOOP; tool.iTime _ IO.GetCard[s]; FOR c: Tool.Color IN Tool.Color DO tool.colorITime[c] _ IO.GetCard[s]; ENDLOOP; 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]; FOR c: Tool.Color IN Tool.Color DO tool.colorDC[c][p] _ IO.GetCard[s]; tool.colorGain[c][p] _ IO.GetCard[s]; ENDLOOP; ENDLOOP; IO.Close[s]; tool.out.PutRope["Done\n"]; EXITS Out => {tool.dc _ tool.gain _ NIL; tool.out.PutRope[" Error.\n"]; RETURN;}; END; IO.PutF[s, "%g %g %g %g %g\n", IO.card[tool.iTime], IO.card[tool.colorITime[Clear]], IO.card[tool.colorITime[Red]], IO.card[tool.colorITime[Green]], IO.card[tool.colorITime[Blue]]]; FOR c: Tool.Color IN Tool.Color DO IO.PutF[s, "%g %g ", IO.card[tool.colorDC[c][i]], IO.card[tool.colorGain[c][i]]]; ENDLOOP; FOR c: Tool.Color IN Tool.Color DO tool.out.PutF["Calibrating at integration time: %g .. dark .. ", IO.card[tool.colorITime[c]]]; tool.colorDC[c] _ CalibrateDarkCurrent[tool.params.defaultServer, tool.colorITime[c]]; tool.out.PutRope[" Done\n"]; ENDLOOP; FOR c: Tool.Color IN Tool.Color DO tool.out.PutF["Calibrating at integration time: %g .. light .. ", IO.card[tool.colorITime[c]]]; tool.colorGain[c] _ CalibrateLightsOn[server: tool.params.defaultServer, t: tool.colorITime[c], dc: tool.colorDC[c], color: (SELECT c FROM Clear => Clear, Red => Red, Green => Green, Blue => Blue, ENDCASE => ERROR)]; tool.out.PutRope[" Done\n"]; ENDLOOP; PROC [scanNumber: LineIndex, b: Buffer, clientData: REF ANY _ NIL] RETURNS [Buffer]; LoadNormalizer[h, tool.dc, tool.gain]; SetIntegrationTime[h, iTime, bits]; SelectWheel[h, tool.color]; PROC [scanNumber: LineIndex, b: Buffer, clientData: REF ANY _ NIL] RETURNS [Buffer]; min, max: BYTE12; c: Tool.Color _ (SELECT color FROM Clear => Clear, Red => Red, Green => Green, Blue => Blue, ENDCASE => ERROR); SetIntegrationTime[h, tool.iTime, bits]; SelectWheel[h, color]; LoadNormalizer[h, tool.dc, tool.gain]; IF tool.doMinMaxPreScan THEN BEGIN tool.out.PutRope[" Computing min/max .. "]; startTime _ BasicTime.Now[]; [min: min, max: max] _ ScanForMinMax[h, lineStart, pixelStart, lineCount, pixelCount]; [ndc, ngain] _ ComputeCorrectedCalibrate[tool.dc, tool.gain, min, max]; LoadNormalizer[h, ndc, ngain]; tool.out.PutF[" %-3.2f min ..", IO.real[BasicTime.Period[startTime, BasicTime.Now[]]/60.0]]; END; IF tool.doMinMaxPreScan THEN LoadNormalizer[h, tool.dc, tool.gain]; HackCalibrate: PUBLIC PROC [] RETURNS [] = BEGIN OPEN Eikonix; ra: REF ARRAY Eikonix.PixelIndex OF REAL; s: STREAM _ FS.StreamOpen["///CalibrationDefault.txt"]; dc: Eikonix.NBuffer _ NEW[Eikonix.NBufferRecord]; gain: Eikonix.NBuffer _ NEW[Eikonix.NBufferRecord]; rawData: Eikonix.NBuffer _ NEW[Eikonix.NBufferRecord]; h: Handle _ Open ["York"]; FOR i: CARDINAL IN Eikonix.IntegrationTime DO d[i].dc _ NEW [Eikonix.NBufferRecord _ ALL [0]]; d[i].gain _ NEW [Eikonix.NBufferRecord _ ALL [800H]]; FOR j: CARDINAL IN Eikonix.PixelIndex DO md: MACHINE DEPENDENT RECORD [a, b: CHAR]; md.a_ s.GetChar[]; md.b_ s.GetChar[]; d[i].dc[j] _ LOOPHOLE [md]; md.a_ s.GetChar[]; md.b_ s.GetChar[]; d[i].gain[j] _ LOOPHOLE [md]; ENDLOOP; ENDLOOP; s.Close[]; ra _ NEW[ARRAY Eikonix.PixelIndex OF REAL _ ALL [0.0]]; FOR i: CARDINAL DECREASING IN [1 .. 11] DO FOR j: CARDINAL IN Eikonix.PixelIndex DO ra[j] _ ra[j] + (d[i].dc[j] - d[i-1].dc[j]); ENDLOOP; ENDLOOP; FOR j: CARDINAL IN Eikonix.PixelIndex DO ra[j] _ ra[j] / 11.0; ENDLOOP; s _ FS.StreamOpen["///Scanner/DarkCurrentDelta.txt", create]; FOR j: CARDINAL IN Eikonix.PixelIndex DO IO.PutF[s, "%g %g\n", IO.card[d[0].dc[j]], IO.real[ra[j]]]; ENDLOOP; gain^ _ ALL [0800H]; FOR i: CARDINAL IN [0 .. 4] DO FOR j: CARDINAL IN Eikonix.PixelIndex DO dc[j] _ LOOPHOLE[Basics.BITAND[Real.RoundC[d[0].dc[j] + (ra[j] * (i + 1))], 0FFFH]]; ENDLOOP; LoadNormalizer[h, dc, gain]; SetIntegrationTime[h, i, bits]; SelectWheel[h, Clear]; TurnOnLights[h]; rawData _ GetCal[h]; TurnOffLights[h]; IO.PutRope[s, "\n\n"]; FOR i: CARDINAL IN [0 .. EikonixProtocol.Width) DO IO.PutF[s, "%g %g\n", IO.card[rawData[i]], IO.card[dc[i]]]; ENDLOOP; IO.Flush[s]; ENDLOOP; Close[h ! EikonixError => CONTINUE]; IO.Close[s]; END; Κ¦˜code™K™š˜šœ˜šœœ˜Kšœ/œœ˜?——KšœAœ˜VKšœF˜FK˜ Kšœr˜rK˜šœœ ™"KšœAœ™^KšœV™VK™Kšœ™—šœœ ™"KšœBœ™_Kš œ}œœ;œœ™ΨK™Kšœ™—KšœΟc˜—Kšœ˜Kšœ˜—K˜K˜š žœœœœ$œœ ˜zKšœ œ˜Kšœœœ˜Kšœœ˜ Kšœœ˜šœ‘!˜'š˜šœ˜šœœœ˜šœ#œ˜-Kšœœ˜%—Kšœœœœ˜#—Kšœ/œœ˜?—šœ˜Kš œ0œœœœ ™Tšœœœ˜"šœ ˜KšœA˜Dšœ˜Kšœœ œ ˜-KšœE˜H——Kšœ˜—Kšœ+œ œ˜PKšœ˜ Kšœ˜—Kšœ œ˜3šœ˜KšœœΪ˜α—Kšœœ˜%š˜Kšœ œD˜SKšœœ˜Kšœ%˜%Kšœ ˜ K™&Kšœ#™#Kšœ™Kšœ˜Kšœ)˜)Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ˜$Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—K˜šžœœQ˜cš˜Kšœœ ˜Kšœœ ˜Kšœœ4˜=Kšœœœœ˜Kšœœ˜Kšœ+œ œ˜OKš œœœœœœ˜MKšœ)˜)Kšœ˜—Kšœ˜—Kšœ œ˜Kšœœ˜Kš žœœœœœœ˜7Kšžœœœœ˜+Kš žœœœœœœ ˜?šžœœœœ˜8K˜—š ž œœœœά˜œKšœ ˜ Kšœ œ˜Kšœœœ˜Kšœœ˜ Kšœœ˜Kšœœœ˜šœ‘!˜'š˜šœ˜š œœœœ˜"šœ#œ˜-Kšœœ˜%—Kšœœœœ˜!Kšœœ˜Kšœœœœ˜Kšœ˜Kšœ˜—Kšœ/œœ˜?—šœ˜Kš œ0œœœœ ™Tšœœœ˜'Kšœ œœ$˜:Kšœœœ˜BKšœ˜—K˜Kšœ ˜ Kš œ œœœœ˜7Kšœ˜ Kšœ˜—Kšœ œ˜3Kšœ ˜ šœ˜Kšœœ„˜‹—Kšœœ˜%Kšœœ˜Kšœœ%˜.š˜Kšœœ˜"Kšœ œ™Kšœ œ'˜6Kšœœ˜Kš œœœ;œœ™oKšœœ˜Kšœ%˜%Kšœ ˜ Kšœ(™(Kšœ™Kšœ&™&Kšœ˜šœœ™"Kšœ+™+Kšœ™KšœV™VKšœG™GK™šœ™Kšœ:™<—Kšœ™—Kšœ"˜"Kšœ˜KšœE˜EKšœ˜šœ ˜ Kšœ:˜<—Kšœœ'™CKšœ˜Kšœ˜Kšœœ˜$Kšœœ˜Kš œœœœœ˜#Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—K˜šžœœœœœœœ˜mKšœœœ œ'˜CKšœœ˜!Kšœœ˜"K˜šœœœ˜(Kšœœœ ˜Kšœœœ˜Kšœœ ˜Kšœ œ ˜Kšœ˜—Kšœ˜—K˜š Ÿ œœœœœœ ™>Kš œœœœœ™)Kšœœœ)™7Kšœœ™1Kšœœ™3Kšœœ™6Kšœ™K™šœœœ™-Kšœ œœ™0Kšœ œœ ™5šœœœ™(Kš œœ œœœ™*K™%Kšœ œ™K™%Kšœœ™Kšœ™—Kšœ™—K™ Kš œœœœœœ™7š œœ œœ ™*šœœœ™(K™,Kšœ™—Kšœ™—šœœœ™(K™Kšœ™—Kšœœ7™=šœœœ™(Kšœœœ™;Kšœ™—Kšœœ ™šœœœ ™šœœœ™(Kšœœœ6™TKšœ™—Kšœ™Kšœ™Kšœ™Kšœ™Kšœ™Kšœ™Kšœ™šœœœ™2Kšœœœ™;Kšœ™—Kšœ ™ Kšœ™—Kšœœ™$Kšœ ™ Kšœ™—K˜Kšœ˜——…—"Eΐ