DBitsMainImpl.mesa
Copyright (C) 1984, 1985, Xerox Corporation. All rights reserved.
Michael Plass, October 18, 1985 1:24:10 pm PDT
DIRECTORY AIS, ImagerOps, Terminal, InterminalBackdoor, BasicTime, Convert, DynamicBits, FontEdit, FS, Imager, PixelMapOps, ImagerPixelMap, ImagerPixelSeq, ImagerTransformation, IO, CedarProcess, Process, Random, RasterFontIO, Real, Rope;
DBitsMainImpl: CEDAR PROGRAM
IMPORTS AIS, ImagerOps, Terminal, InterminalBackdoor, BasicTime, Convert, DynamicBits, FS, PixelMapOps, ImagerPixelMap, ImagerPixelSeq, ImagerTransformation, IO, CedarProcess, Process, Random, Real, Rope
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
PixelMap: TYPE ~ ImagerPixelMap.PixelMap;
PixelSeq: TYPE ~ ImagerPixelSeq.PixelSeq;
DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle;
InternalFont: TYPE ~ RasterFontIO.InternalFont;
printerModelNeighborhood: DeviceRectangle ← [-1, -1, 3, 3];
kernelNeighborhood: DeviceRectangle ← [-1, -1, 3, 3];
model: DynamicBits.Model ← NIL;
bitMapWhite: [0..1] ← 1;
LoadPetersModel: PROC [file: ROPE] ~ {
neighbors: DeviceRectangle ~ [-1, -1, 3, 3];
tableSize: INT ~ 90;
modelScale: REAL ← 25500; -- Scale factor applied to model
model90: ARRAY [0..tableSize) OF NAT;
printerModel: DynamicBits.PrinterModel ~ {
slow, fast: INTEGER ~ 0;
bit: PROC [s, f: INTEGER] RETURNS [[0..1]] ~ {
b: [0..1] ← ImagerPixelMap.GetBit[bitmap, s, f];
IF bitMapWhite = 1 THEN b ← 1-b;
RETURN [b]
};
diags: NAT ← bit[1, 1] + bit[-1, 1] + bit[ 1,-1] + bit[-1,-1];
slows: NAT ← bit[1, 0] + bit[-1, 0];
fasts: NAT ←  bit[0, 1] + bit[ 0,-1];
me: NAT ←  bit[0, 0];
index: NAT ← 45*me + 15*slows + 5*fasts + diags;
RETURN [model90[index], 0]
};
kernel: PixelMap ← ImagerPixelMap.Create[4, neighbors];
stream: IO.STREAMFS.StreamOpen[fileName: file];
FOR i: INT IN [0..tableSize) DO
model90[i] ← Real.RoundI[modelScale*IO.GetReal[stream]];
ENDLOOP;
FOR s: INT IN [neighbors.sMin..neighbors.sMin+neighbors.sSize) DO
FOR f: INT IN [neighbors.fMin..neighbors.fMin+neighbors.fSize) DO
pix: INTIO.GetInt[stream];
kernel.Fill[[s,f,1,1], pix];
ENDLOOP;
ENDLOOP;
IO.Close[stream];
model ← DynamicBits.CreatePrinterModel[neighbors, printerModel, kernel];
printerModelNeighborhood ← neighbors;
kernelNeighborhood ← neighbors;
};
KernelSpec: TYPE ~ ARRAY [0..9) OF NatLast;
NatLast: TYPE ~ NATNAT.LAST;
BadToken: SIGNAL [token: ROPE] ~ CODE;
LoadPrinterModel: PROC [file: ROPE, noiseWeight: REAL ← 0.0, kernelSpec: KernelSpec] ~ {
neighbors: DeviceRectangle ~ IF kernelSpec[1] = NAT.LAST THEN [0,0,1,1] ELSE [-1, -1, 3, 3];
meanIntensity: REF ARRAY [0..512) OF REALNEW[ARRAY [0..512) OF REAL];
stdDev: REF ARRAY [0..512) OF REALNEW[ARRAY [0..512) OF REAL];
minMeanIntensity: REAL ← 9999999999.9;
maxMeanIntensity: REAL ← 0;
ReadModel: PROC ~ {
stream: IO.STREAMFS.StreamOpen[fileName: file];
token: REF TEXTNEW[TEXT[20]];
Match: PROC [key: ROPE] RETURNS [BOOL] ~ TRUSTED {
RETURN [key.Equal[LOOPHOLE[token]]]
};
tokenKind: IO.TokenKind ← tokenERROR;
stackTop: [0..5] ← 0;
stack: ARRAY [0..5) OF REAL;
Push: PROC [real: REAL] ~ {stack[stackTop] ← real; stackTop ← stackTop + 1};
Pop: PROC RETURNS [real: REAL] ~ {stackTop ← stackTop - 1; real ← stack[stackTop]};
PopInt: PROC RETURNS [int: INT] ~ {stackTop ← stackTop - 1; int ← Real.RoundLI[stack[stackTop]]};
GetToken: PROC ~ {
[tokenKind: tokenKind, token: token] ← stream.GetCedarToken[buffer: token, flushComments: TRUE];
};
c: [0..512) ← 0;
GetToken[];
UNTIL tokenKind = tokenEOF DO
SELECT tokenKind FROM
tokenID => {
SELECT TRUE FROM
Match["minIntensity"] => [] ← Pop[];
Match["maxIntensity"] => [] ← Pop[];
Match["encoding"] => c ← PopInt[];
Match["aveIntensity"] => meanIntensity[c] ← Pop[];
Match["stdDev"] => stdDev[c] ← Pop[];
Match["occurrences"] => [] ← Pop[];
ENDCASE => SIGNAL BadToken[Rope.FromRefText[token]];
};
tokenDECIMAL, tokenOCTAL, tokenHEX => TRUSTED {Push[Convert.CardFromWholeNumberLiteral[LOOPHOLE[token]]]};
tokenREAL => TRUSTED {Push[Convert.RealFromRope[LOOPHOLE[token]]]};
ENDCASE => SIGNAL BadToken[Rope.FromRefText[token]];
GetToken[];
ENDLOOP;
IO.Close[stream];
FOR c: [0..512) IN [0..512) DO
minMeanIntensity ← MIN[minMeanIntensity, meanIntensity[c]];
maxMeanIntensity ← MAX[maxMeanIntensity, meanIntensity[c]];
ENDLOOP;
};
printerModel: DynamicBits.PrinterModel ~ {
intensity: REAL ← meanIntensity[encoding];
scaledIntensity: REAL
(intensity-minMeanIntensity) / (maxMeanIntensity-minMeanIntensity);
RETURN [Real.RoundLI[scaledIntensity*DynamicBits.Intensity.LAST], Real.RoundLI[noiseWeight*stdDev[encoding]]]
};
kernel: PixelMap ← ImagerPixelMap.Create[4, neighbors];
j: NAT ← 0;
FOR s: INT IN [neighbors.sMin..neighbors.sMin+neighbors.sSize) DO
FOR f: INT IN [neighbors.fMin..neighbors.fMin+neighbors.fSize) DO
intensity: DynamicBits.Intensity ← kernelSpec[j];
kernel.Fill[[s,f,1,1], intensity];
j ← j+1;
ENDLOOP;
ENDLOOP;
ReadModel[];
model ← DynamicBits.CreatePrinterModel[[-1, -1, 3, 3], printerModel, kernel];
printerModelNeighborhood ← [-1, -1, 3, 3];
kernelNeighborhood ← neighbors;
};
screenKernel: ARRAY [0..9) OF NAT ← [1*15, 2*15, 1*15, 2*15, 4*15, 2*15, 1*15, 2*15, 1*15];
LoadScreenModel: PROC ~ {
neighbors: DeviceRectangle ~ [-1, -1, 3, 3];
kernel: PixelMap ← ImagerPixelMap.Create[4, neighbors];
printerModel: DynamicBits.PrinterModel ~ {
RETURN [IF encoding = bitMapWhite THEN 255 ELSE 0, 0]
};
model ← DynamicBits.CreatePrinterModel[[0,0,1,1], printerModel, kernel];
printerModelNeighborhood ← [0,0,1,1];
kernelNeighborhood ← neighbors;
};
original: PixelMap;
gray: PixelMap;
bitmap: PixelMap;
initialBitmap: PixelMap;
fixedBits: PixelMap;
modeledBitmap: PixelMap;
SetUpTest: PROC [aisName: ROPE] RETURNS [error: INT, perPixelError: REAL] ~ {
[error, perPixelError] ← SetUpFromPixelMap[DynamicBits.AddBorder[PixelMapOps.LoadAIS[aisName].pixelMap, 2, 0]];
};
SetUpFromPixelMap: PROC [pixelMap: PixelMap] RETURNS [error: INT, perPixelError: REAL] ~ {
maxPixel: CARDINAL ← Basics.BITSHIFT[1,Basics.BITSHIFT[1,pixelMap.refRep.lgBitsPerPixel]]-1;
original ← ImagerPixelSeq.ChangeBitsPerPixel[pixelMap, 3];
ImagerPixelSeq.Renormalize[original, 0, maxPixel, 0, 255];
gray ← original.Copy;
DynamicBits.Convolve[gray, model.kernel, 255];
bitmap ← DynamicBits.RandomDither[original];
initialBitmap ← bitmap.Copy;
fixedBits ← DynamicBits.FindFixedBits[original, -model.neighborhood.sMin-model.kernel.sOrigin];
modeledBitmap ← DynamicBits.ApplyModel[bitmap, model];
error ← DynamicBits.AbsDiff[gray, modeledBitmap];
perPixelError ← error/(REAL[original.fSize]*original.sSize);
DoDisplay[];
};
DoDisplay: PROC ~ TRUSTED {
cd: PixelMap ← ImagerOps.PixelMapFromFrameBuffer[Terminal.GetColorFrameBufferA[InterminalBackdoor.terminal]];
w: DeviceRectangle ← original.Window;
sMinCenter: INT ← 4-(w.sMin-w.sSize);
fMinCenter: INT ← 8-(w.fMin-2*w.fSize);
sMaxCenter: INT ← cd.sSize-sMinCenter;
fMaxCenter: INT ← cd.fSize-fMinCenter;
random: Random.RandomStream ← NIL;
IF sMinCenter > sMaxCenter THEN sMinCenter ← sMaxCenter ← cd.sSize/2;
IF fMinCenter > fMaxCenter THEN fMinCenter ← fMaxCenter ← cd.fSize/2;
random ← Random.Create[seed: w.sMin*INT[12345]+w.fMin*INT[3141592]+w.fSize+w.sSize*1024];
cd ← cd.ShiftMap[-random.ChooseInt[sMinCenter, sMaxCenter], -random.ChooseInt[fMinCenter, fMaxCenter]];
cd.Transfer[original.ShiftMap[-1-w.sSize, -1-w.fSize]];
cd.Transfer[gray.ShiftMap[1, -1-w.fSize]];
ImagerPixelSeq.TransferSamples[cd, bitmap.ShiftMap[-1-w.sSize, 1], ImagerTransformation.Scale[1], FALSE, 255];
cd.Transfer[modeledBitmap.ShiftMap[1, 1]];
ImagerPixelSeq.TransferSamples[cd, initialBitmap.ShiftMap[-1-w.sSize, 3+w.fSize], ImagerTransformation.Scale[1], FALSE, 255];
ImagerPixelSeq.TransferSamples[cd, fixedBits.ShiftMap[-1-w.sSize, -3-2*w.fSize], ImagerTransformation.Scale[1], FALSE, 255];
};
DisplaySwath: PROC [swath: DeviceRectangle] ~ TRUSTED {
cd: PixelMap ← ImagerOps.PixelMapFromFrameBuffer[Terminal.GetColorFrameBufferA[InterminalBackdoor.terminal]];
w: DeviceRectangle ← original.Window;
cd ← cd.ShiftMap[-cd.sSize/2, -cd.fSize/2];
ImagerPixelSeq.TransferSamples[cd, bitmap.Clip[swath].ShiftMap[-1-w.sSize, 1], ImagerTransformation.Scale[1], FALSE, 255];
};
DoTestPass: PROC [swathSize: NAT ← 1] RETURNS [error: INT, perPixelError: REAL, msPerPixel: REAL] ~ {
scratch: REFNIL;
w: DeviceRectangle ~ original.Window;
swath: DeviceRectangle ← [w.sMin, w.fMin, w.sSize, swathSize];
pixels: REALREAL[original.fSize]*original.sSize;
startPulses: BasicTime.Pulses ~ BasicTime.GetClockPulses[];
CedarProcess.SetPriority[background];
FOR f: INTEGER IN [w.fMin..w.fMin+w.fSize-swathSize) DO
swath: DeviceRectangle ← [w.sMin, f, w.sSize, swathSize];
scratch ← DynamicBits.TuneSwath[gray, bitmap, fixedBits, swath, model, scratch];
DisplaySwath[w];
Process.CheckForAbort[];
ENDLOOP;
modeledBitmap ← DynamicBits.ApplyModel[bitmap, model];
error ← DynamicBits.AbsDiff[gray, modeledBitmap];
perPixelError ← error/pixels;
msPerPixel ← BasicTime.PulsesToMicroseconds[BasicTime.GetClockPulses[]-startPulses]/(1000*pixels);
DoDisplay[];
};
bc: CHAR ← ' ;
ec: CHAR ← '~;
DoFont: PROC [fontName: ROPE, outputName: ROPE, bitsPerEm: REAL, passes: NAT ← 4, swathSize: NAT ← 1, bitsPerInch: REAL ← 384] ~ {
nominalT: Imager.Transformation ← Imager.Scale[0.125];
tempMap: PixelMap ← [0,0,0,0,0,0,NIL];
font: Imager.FONT ← Imager.MakeFont[fontName, bitsPerEm*8];
bb: Font.Box ← Font.FontBoundingBox[font];
dbb: ImagerPixelMap.DeviceRectangle ← [Real.RoundLI[-bb.ymax], Real.RoundLI[+bb.xmin], Real.RoundLI[bb.ymax]-Real.RoundLI[bb.ymin], Real.RoundLI[bb.xmax]-Real.RoundLI[bb.xmin]];
pixelMap: PixelMap ← ImagerPixelMap.Create[0, [0, 0, dbb.sSize+4, dbb.fSize+4]];
context: Imager.Context ← Imager.Create[$LFDisplay, NEW[ImagerPixelMap.PixelMap ← pixelMap]];
internalFont: InternalFont ← RasterFontIO.Create[dbb, dbb.fSize];
pixelMap ← pixelMap.ShiftMap[dbb.sMin-2, dbb.fMin-2];
IF font.GetProp[$PressFont] = $PressFont THEN {
internalFont.family ← UFPressFontReader.Family[[font.graphicsKey, 0]];
internalFont.face ← UFPressFontReader.Face[[font.graphicsKey, 0]];
internalFont.bitsPerEmQuad ← font.actualTransformation.SingularValues.x;
};
context.state.T ← Imager.Translate[2-bb.xmin, 2+dbb.sMin+dbb.sSize];
context.SetFont[font];
FOR c: CHAR IN [MAX[font.bc, bc]..MIN[font.ec, ec]] DO
widthVector: Font.Pair ← Font.WidthVector[font, c];
pixelMap.Clear;
context.SetXY[[0,0]];
context.ShowChar[c];
tempMap ← ImagerPixelSeq.ChangeBitsPerPixel[DynamicBits.AddBorder[pixelMap.Trim, 4*8, 0], 3, tempMap.refRep];
ImagerPixelSeq.Renormalize[tempMap, 0, 1, 0, 255];
ImagerPixelSeq.BoxFilter[tempMap, 9, 9];
ImagerPixelSeq.BoxFilter[tempMap, 5, 5];
ImagerPixelSeq.Renormalize[tempMap, 0, 255, 255, 0];
[] ← SetUpFromPixelMap[ImagerPixelSeq.UnderSample[tempMap, nominalT, TRUE]];
THROUGH [0..passes) DO
[] ← DoTestPass[swathSize];
ENDLOOP;
bitmap.Fill[bitmap.Window, 1, [xor, null]];
internalFont.charRep[c] ← [
fWidth: widthVector.x/8,
sWidth: -widthVector.y/8,
pixels: bitmap.Trim[0].Copy
];
ENDLOOP;
FontEdit.WriteFormatDerivedFromName[internalFont, outputName, bitsPerInch];
};
MakePD: PROC [name: ROPE] ~ {
context: Imager.Context ← Imager.Create[$PD, ImagerPD.Hornet[name]];
bits: PixelMap ← DynamicBits.AddBorder[bitmap, 4, 255];
bits.Fill[bits.Window, 1, [xor, null]];
bits.sOrigin ← bits.fOrigin ← 0;
context.state.T ← Imager.Scale[1];
Imager.SetSampledBlack[context, ImagerMasks.PixelArrayFromPixelMap[bits], Imager.Scale[1]];
Imager.MaskRectangle[context, 0, 0, 30000, 30000];
[] ← context.SpecialOp[$Close, NIL];
};
MakeReplicatedAIS: PROC [name: ROPE, comment: ROPE] ~ {
bits: PixelMap ← DynamicBits.AddBorder[bitmap, 4, 255];
page: PixelMap ← ImagerPixelMap.Create[0, [0,0,16*bits.sSize, 16*bits.fSize]];
bits.Fill[bits.Window, 1, [xor, null]];
page.TransferTile[ImagerPixelMap.CreateTile[bits]];
StorePixelMap[name, page, TRUE, comment];
};
GreatestCommonDivisor: PROC [a, b: INT] RETURNS [INT] ~ {
a ← ABS[a];
b ← ABS[b];
IF a>b THEN {t: INT ← a; a ← b; b ← t};
WHILE a # 0 DO
t: INT ← b MOD a;
b ← a;
a ← t;
ENDLOOP;
RETURN [b]
};
LeastCommonMultiple: PROC [a, b: INT] RETURNS [INT] ~ {
RETURN [ABS[a*b]/GreatestCommonDivisor[a,b]]
};
MakePlatemakerPD: PROC [name: ROPE, pixelsPerInch: REAL] ~ {
pdFileDescription: ImagerPD.PDFileDescription ← NEW[ImagerPD.PDFileDescriptionRep ← [fileName: name, deviceCode: mig, sResolution: 1200, fResolution: 1200, imageSSize: 11*1200, imageFSize: 85*120, nColors: 1, bandSSize: 16, maxLoadWords: 60000, leftovers: TRUE, copies: 1]];
context: Imager.Context ← Imager.Create[$PD, pdFileDescription];
bits: PixelMap ← DynamicBits.AddBorder[bitmap, 4, 255];
bits.Fill[bits.Window, 1, [xor, null]];
bits.sOrigin ← bits.fOrigin ← 0;
context.state.T ← Imager.Scale[1];
Imager.SetSampledBlack[context, ImagerMasks.PixelArrayFromPixelMap[bits], Imager.Scale[1]];
Imager.MaskRectangle[context, 0, 0, 30000, 30000];
[] ← context.SpecialOp[$Close, NIL];
};
MakePrinterTestPattern: PROC [aisName: ROPE ← "TestPatternS.ais", sPixels: NAT ← 100, fPixels: NAT ← 150, seed: INT ← -1] ~ {
bits: PixelMap ← ImagerPixelMap.Create[0, [0, 0, sPixels+8, fPixels+8]];
random: Random.RandomStream ← Random.Create[seed: seed];
bits.Clear;
bits.Fill[[1, 1, sPixels+6, fPixels+6], 1];
bits.Fill[[3, 3, sPixels+2, fPixels+2], 0];
bits.Fill[[4, 4, sPixels, fPixels], 1];
bits.Fill[[1, 10, 2, 20], 0];
bits.Fill[[10, 1, 10, 2], 0];
FOR s: NAT IN [0..(sPixels+1)/2) DO
FOR f: NAT IN [0..(fPixels+1)/2) DO
bit: [0..1] ← random.ChooseInt[0, 1];
bits.Fill[[s+4, f+4, 1, 1], bit];
bits.Fill[[sPixels-1-s+4, f+4, 1, 1], bit];
bits.Fill[[s+4, fPixels-1-f+4, 1, 1], bit];
bits.Fill[[sPixels-1-s+4, fPixels-1-f+4, 1, 1], bit];
ENDLOOP;
ENDLOOP;
StorePixelMap[aisName, bits, FALSE, IO.PutFR["Symmetric printer calibration pattern sPixels: %g, fPixels: %g, seed: %g", IO.int[sPixels], IO.int[fPixels], IO.int[seed]]];
};
StorePixelMap: PROC [aisFileName: ROPE, source: ImagerPixelMap.PixelMap, bitmap: BOOLEANTRUE, comment: ROPE ← NIL] ~ TRUSTED {
output: AIS.FRef ← AIS.CreateFile[name: aisFileName, raster: NEW[AIS.RasterPart ← [
scanCount: source.sSize,
scanLength: source.fSize,
scanMode: rd,
bitsPerPixel: IF source.refRep.lgBitsPerPixel = 0 AND bitmap THEN 0 ELSE Basics.BITSHIFT[1, source.refRep.lgBitsPerPixel],
linesPerBlock: -1,
paddingPerBlock: 65535
]]];
outputWindow: AIS.WRef ← AIS.OpenWindow[output];
lineMap: ImagerPixelMap.PixelMap ← ImagerPixelMap.Create[source.refRep.lgBitsPerPixel, [source.sOrigin+source.sMin, source.fOrigin+source.fMin, 1, source.fSize]];
lineBufferDesc: AIS.Buffer ← [length: lineMap.refRep.words, addr: lineMap.refRep.pointer];
AIS.WriteComment[output, comment];
FOR i: NAT IN [0..source.sSize) DO
lineMap.Clear;
lineMap.Transfer[source];
lineMap.sOrigin ← lineMap.sOrigin + 1;
AIS.UnsafeWriteLine[outputWindow, lineBufferDesc, i];
ENDLOOP;
AIS.CloseFile[output];
};
ComputePrinterModel: PROC [testPatternName: ROPE, scannedPatternName: ROPE, outputFileName: ROPE] ~ {
testPatternName and scannedPatternName refer to intensity-encoded AIS files. Their sizes need not match exactly, but the will be matched up on centers. The test pattern is assumed to be black-and-white.
count: REF ARRAY [0..512) OF INTNEW[ARRAY [0..512) OF INT];
intensitySum: REF ARRAY [0..512) OF INTNEW[ARRAY [0..512) OF INT];
intensitySquaredSum: REF ARRAY [0..512) OF INTNEW[ARRAY [0..512) OF INT];
testPattern: PixelMap ← PixelMapOps.LoadAIS[testPatternName].pixelMap;
scannedPattern: PixelMap ← PixelMapOps.LoadAIS[scannedPatternName].pixelMap;
testPattern ← testPattern.ShiftMap[-testPattern.sSize/2, -testPattern.fSize/2];
scannedPattern ← scannedPattern.ShiftMap[-scannedPattern.sSize/2, -scannedPattern.fSize/2];
count^ ← ALL[0];
intensitySum^ ← ALL[0];
intensitySquaredSum^ ← ALL[0];
BEGIN
w: DeviceRectangle ← ImagerPixelMap.Intersect[testPattern.Window, scannedPattern.Window];
tm: PixelSeq ← ImagerPixelSeq.Create[w.fSize]; -- minus
tz: PixelSeq ← ImagerPixelSeq.Create[w.fSize]; -- zero
tp: PixelSeq ← ImagerPixelSeq.Create[w.fSize]; -- plus
sz: PixelSeq ← ImagerPixelSeq.Create[w.fSize];
out: IO.STREAMFS.StreamOpen[outputFileName, $create];
minIntensity: NATNAT.LAST;
maxIntensity: NAT ← 0;
FOR s: INTEGER IN [w.sMin+1..w.sMin+w.sSize-1) DO
tm.LoadF[s-1, w.fMin, w.fSize, testPattern];
tz.LoadF[s, w.fMin, w.fSize, testPattern];
tp.LoadF[s+1, w.fMin, w.fSize, testPattern];
sz.LoadF[s, w.fMin, w.fSize, scannedPattern];
FOR f: NAT IN [1..w.fSize-1) DO
c: [0..512) ← 0;
intensity: NAT ← sz[f];
Bit: PROC [pix: NAT] ~ {c ← 2*c+MIN[pix, 1]};
IF intensity < minIntensity THEN minIntensity ← intensity;
IF intensity > maxIntensity THEN maxIntensity ← intensity;
Bit[tm[f-1]]; Bit[tm[f]]; Bit[tm[f+1]];
Bit[tz[f-1]]; Bit[tz[f]]; Bit[tz[f+1]];
Bit[tp[f-1]]; Bit[tp[f]]; Bit[tp[f+1]];
count[c] ← count[c] + 1;
intensitySum[c] ← intensitySum[c] + intensity;
intensitySquaredSum[c] ← intensitySquaredSum[c] + Basics.LongMult[intensity, intensity];
ENDLOOP;
ENDLOOP;
out.PutF["%g minIntensity %g maxIntensity\n", IO.int[minIntensity], IO.int[maxIntensity]];
FOR c: [0..512) IN [0..512) DO
k: INT ← count[c];
IF k = 0 THEN {
out.PutF["%03bB NoData\n", IO.int[c]];
}
ELSE {
intensity: REAL ← intensitySum[c];
ave: REAL ← intensity/k;
var: REALREAL[intensitySquaredSum[c]]/k - ave*ave;
out.PutF["%03bB encoding %6g aveIntensity %6g stdDev %g occurrences\n", IO.int[c], IO.real[ave], IO.real[Real.SqRt[var]], IO.int[k]];
};
ENDLOOP;
IO.Close[out];
END;
};
LoadModel["retuned.tunerModel"];
END.