summaryrefslogtreecommitdiff
path: root/Data/Stdf/WaferMap.hs
blob: 2510438692dc8dcfba550e9474b798d2e50a8ba3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

{-# LANGUAGE OverloadedStrings #-}

-- TODO: factoring this interface
module Data.Stdf.WaferMap ( XyBin(..)
                          , stdfToXyBin
                          , xybsToGrid
                          , gridToString 
                          , stdfToWaferMapString 
                          ) 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
                   , bin :: Int }
           | Missing
    deriving Show

stdfToXyBin :: Stdf -> [XyBin]
stdfToXyBin (prr@(Prr { xCoord = Just xc
                      , yCoord = Just yc
                      , hardBin = hb }):prrs) =
    XyBin { x = fromIntegral xc
          , y = fromIntegral yc
          , bin = fromIntegral hb } : stdfToXyBin prrs
stdfToXyBin (_:prrs) = stdfToXyBin prrs
stdfToXyBin [] = []

-- Take a list of XyBin sorted by x,y and a list of all x,y in the wafer map
-- Make a list of XyBin with Missing inserted where there wasn't an XyBin for
-- a given x,y
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

-- sort by y,x
-- groupby y,x
-- take lowest bin # from groups
-- use min max x y to insert Missing dies
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 (bin a) (bin 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

-- take list of rows
-- convert to rows with columns of show bin
-- pad to maximum show bin width
-- print
gridToString :: [[XyBin]] -> String
gridToString xybs = unlines $ map unwords padded
    where
        pad w s = s ++ replicate (w - length s) ' '

        binOrNothing Missing = Nothing
        binOrNothing XyBin { bin = bin } = Just bin

        bins = map2d binOrNothing xybs -- start here
        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