module Data.Stdf.WaferMap ( XyBin(..)
, stdfToXyBin
, xybsToGrid
, gridToString
, stdfToWaferMapString
, map2d
) where
import Data.Stdf
import qualified Data.ByteString.Lazy as BL
import Data.Aeson
import Data.Maybe (fromJust)
import Data.List (sortBy, groupBy)
import Data.Function (on)
import Data.Ix (range)
import Data.List.Split (chunksOf)
data XyBin = XyBin { x :: Int
, y :: Int
, hbin :: Int }
| Missing
deriving (Show, Eq)
stdfToXyBin :: Stdf -> [XyBin]
stdfToXyBin (prr@(Prr { xCoord = Just xc
, yCoord = Just yc
, hardBin = hb }):prrs) =
XyBin { x = fromIntegral xc
, y = fromIntegral yc
, hbin = fromIntegral hb } : stdfToXyBin prrs
stdfToXyBin (_:prrs) = stdfToXyBin prrs
stdfToXyBin [] = []
addmissing :: [XyBin] -> [(Int, Int)] -> [XyBin]
addmissing [] [] = []
addmissing [] xys = replicate (length xys) Missing
addmissing (d:ds) (xy:xys)
| x d == fst xy && y d == snd xy = d : addmissing ds xys
| otherwise = Missing : addmissing (d:ds) xys
binToStr :: Maybe Int -> String
binToStr Nothing = "."
binToStr (Just bn) = show bn
xybsToGrid :: [XyBin] -> [[XyBin]]
xybsToGrid xybs = mkgrid cols gridlist
where ordXy a b = case compare (y a) (y b) of
EQ -> compare (x a) (x b)
ordy -> ordy
eqXy a b = x a == x b && y a == y b
ordBin a b = compare (hbin a) (hbin b)
waferxy = [(atx, aty) | aty <- range (miny, maxy)
, atx <- range (minx, maxx)]
sortedxy = sortBy ordXy xybs
groupedxy = groupBy eqXy sortedxy
sortedbin = map (sortBy ordBin) groupedxy
dropedextra = map head sortedbin
xs = map x dropedextra
ys = map y dropedextra
minx = minimum xs
maxx = maximum xs
miny = minimum ys
maxy = maximum ys
gridlist = addmissing dropedextra waferxy
cols = maxx minx + 1
mkgrid :: Int -> [a] -> [[a]]
mkgrid = chunksOf
gridToString :: [[XyBin]] -> String
gridToString xybs = unlines $ map unwords padded
where
pad w s = s ++ replicate (w length s) ' '
binOrNothing Missing = Nothing
binOrNothing XyBin { hbin = hbin } = Just hbin
bins = map2d binOrNothing xybs
binstrs :: [[String]]
binstrs = map2d binToStr bins
maxwidth :: Int
maxwidth = maximum $ (concatMap . map) length binstrs
padded = map2d (pad maxwidth) binstrs
cols = length $ head xybs
rows = length xybs
map2d :: (a -> b) -> [[a]] -> [[b]]
map2d = map . map
stdfToWaferMapString :: Stdf -> String
stdfToWaferMapString bodies = let xybs = stdfToXyBin bodies
grid = xybsToGrid xybs
in gridToString grid