Monday, November 25, 2013

Drawing lines in Gimp using Python-fu

Today at work I needed to create a few test images for debugging some image processing software. I needed to draw a few dark lines on a light background to check if the software will detect them correctly. I found out that Gimp can do this quite nicely for me.

import math
from gimpfu import *

rows = 640
cols = 480

def draw_vertical_lines(drawable,pixel,rows,cols,width):
    for i in range(1,rows):
        for j in range(1,cols,width):
            pdb.gimp_drawable_set_pixel(drawable,i,j,3,pixel)
    return

img = gimp.Image(cols,rows,RGB)
layer_one = gimp.Layer(img,"Layer1",cols,rows,RGB_IMAGE,100,NORMAL_MODE)
pdb.gimp_edit_fill(layer_one,BACKGROUND_FILL)
img.add_layer(layer_one,0)
pdb.gimp_edit_fill(layer_one,BACKGROUND_FILL)
gimp.Display(img)
pixel = [0.0,0.0,0.0,0.0]

draw_vertical_lines(layer_one, pixel, rows, cols, 25)

Thursday, September 12, 2013

Today's script

Just another throw away script to get things done at work today:


#!/usr/bin/perl
use strict;
use warnings;

if ($#ARGV != 0) {
print "ARGV = ", $#ARGV, "\n";
print "Usage: FDC46CountLines.pl \n";
exit(1);
}

my $rootPath = $ARGV[0];
my @lotList = ();
my $dataFile = ();
my @dataLine = ();
my @X = ();
my @Y = ();
my @radius = ();
my $tempPath;
my $i;
my $j;
my $panel;
my $lot;
my $lineCount = 0;
my $outputFile = '';

# Generate list of subfolders
opendir DIR, $rootPath or die "Couldn't open dir $rootPath: $!\n";
my @folders = readdir DIR;
closedir DIR;

foreach (@folders) {
if (-d $rootPath . "\\" . $_) {
if ($_ eq ".") {}
elsif($_ eq "..") {}
else {
push(@lotList, $_);
}
}
}

my %lotHash = ();
my $currentLot;

#Generate list of lot folders
foreach (@lotList) {
$tempPath = $rootPath . "\\" . $_;
$currentLot = $_;
opendir DIR, $tempPath or die "Couldn't open dir $tempPath: $!\n";
@folders = readdir DIR;
closedir DIR;
# Generate list of process folders
foreach (@folders) {
if (-d $tempPath . "\\" . $_) {
if ($_ eq ".") {}
elsif($_ eq "..") {}
else {
push(@{$lotHash{$currentLot}}, $_);
}
}
}
}

@folders = ();
for my $key (keys %lotHash) {
for ($i=0; $i <= $#{$lotHash{$key}}; $i++) {
$tempPath = $rootPath . "\\" . $key . "\\" . $lotHash{$key}[$i];
$lot = $key;
$panel = $lotHash{$key}[$i];
print "tempPath = " . $tempPath . "\n";
print "lot = " . $lot . "\n";
print "panel = " . $panel . "\n";
$dataFile = $tempPath . "\\" . $lot . "_" . $panel . "_Notes.txt";
if (open(DATA, "<$dataFile")) {
while () {
@dataLine = split;
push(@X,$dataLine[3]);
push(@Y,$dataLine[4]);
push(@radius, sqrt($dataLine[3]**2+$dataLine[4]**2));
}
} else { print "dataFile does not exist"; }
@radius = sort(@radius);
$outputFile = $tempPath . "\\" . $lot . "_" . $panel . "_defectCount.txt";
open(OUTPUT, ">$outputFile") or die $!;
$lineCount = 0;
for ($j = 1; $j <= $#radius; $j++) {
if (($radius[$j] - $radius[$j-1]) > 100.0) {
print OUTPUT "$X[$j]\t$Y[$j]\n";
$lineCount += 1;
}
}
print OUTPUT "total unique defects were: $lineCount\n";
@dataLine = ();
@X = ();
@Y = ();
@radius = ();
close OUTPUT;

}
}

Friday, August 9, 2013

Learning assembly in my spare moments

The system:
Sparcstation 10 with a single 36 MHz Supersparc CPU and 16 MB RAM. OpenBSD 4.5 on a 1 GB hard disk. 

With this meager system I am learning about being efficient with my resources and learning assembly in order to still do something useful with the machine. The default OpenBSD install comes with their custom gcc compiler and perl 5.10. Perl runs very slow on this machine making CPAN use impossible without an upgrade. But through SSH I can comfortably write small programs to assist with my solutions to Project Euler. After installing GMP I can really get into number theory with the little box.

But the real fun comes with learning Sparc V8 assembly language. I'm finally at the point in assembly where I can modify the examples I read to do other things. And I used gdb for the first time too.

I'm already dreaming up of a way to translate one set of assembly instructions to another using perl. :-)

So what have I learned so far? Well I learned that every Sparc assembly file starts with a stack initialization. So you start with:
save %sp,-96,%sp

Sunday, August 4, 2013

Fun times at Project Euler.

Felt like I needed to exercise my brain the other day so I went over to Project Euler to solve a few problems. It was problem #4. I tried to solve it on an old 3B2 computer running Unix System V with Perl 4.0. It didn't go too well. So I ran the same code on my MetaArpa account on SDF and solved the thing in less than a minute ha ha. I like the old system though because it forces me to realize just how bad my algorithms are when the site states that all problems should take less than a minute to solve with a normal computer. Fun day.

Sunday, July 21, 2013

Fun with OpenVMS

I've had some discretionary time this work so I worked on a few projects that have been lingering in my mind for a while. I took out the old rx1620 and installed OpenVMS ia64 edition. It took me a while to remember that the serial console is needed to install something on this machine. Nothing comes out of the VGA output when you power on. Also there are two connectors labeled "console" in the back of the machine. Connecting to the normal looking RS-232 connector did not work either. Finally I tries the other connector with the special adapter that came with the machine. With a straight through RS-232 cable and the RS-232 connector on my PC I finally started seeing something.

I connected to the rx1620 using a PC with Solaris 10 installed. I modified the /etc/remote file to point the hardwire variable to /dev/term/a instead of b. running "tip hardwire" worked and I could  see that the machine was ready to install OpenVMS. 

The install process was lengthy and there were multiple questions interrupting the flow regarding DECnet setup, clustering, Kerberos, and other things. I didn't check if it would output to the VGA plug yet. 

Overall it was a smooth first start. I still need to figure out if networking is set up correctly and why FTP is not running. I need to install the license PAK's and some useful programming languages too. One thing about this server though is that it is big and loud! I wish I could install it at work or something and run it 24x7 from there.

Thursday, April 25, 2013

My first Arduino project

At work we print identification characters on the circuits we fabricate using a microscope and a matrix of ultraviolet LEDs. To do the same thing for our scaled up Gen II panels we needed to build another ID printer. This printer would shine ultraviolet light through an optics train to expose a patch of photoresist on the device during production.

We decided to control the 9x5 LED matrix using 14 digital outputs on the Arduino Micro because it simplified the hardware design.

/*
  RS232_MATRIX_CONTROL_v2p0
  Single character driver for LED matrix display. Current code is hardcoded to display 46 characters on a 9 row by 5 column matrix. 
  Each character is sent through serial terminal followed by a carriage return. 
  
  Jovan Trujillo
  Arizona State University
  03/27/2013
*/  
 
byte RN[] = {4,5,6,7,8,9,10,11,12};
byte CN[] = {23,22,21,20,19};
byte LED = 13;
byte strobe = 2;  // strobe rate for each row of matrix in milliseconds.
byte inByte = 0; // Input character received from serial port.
byte idx = 0;  // Generic index counter.
byte i = 0;    // Generic index counter.
int exposure = 250;  // Number of times entire character is displayed.
// Exposure time is calculated to be: strobe x # rows x exposure
byte rowcnt = 9;     // Number of rows to display for matrix arrays that have fewer than 9 rows.
// Character database contains the column bit patterns for each row in an array.
// Character database is hardcoded for a 9x5 LED matrix. 
byte D_0[] = {17,14,14,12,10,6,14,14,17};         // 1
byte D_1[] = {3,27,27,27,27,26,26,26,0};          // 2
byte D_2[] = {17,14,30,30,30,17,15,15,16};        // 3
byte D_3[] = {1,30,30,30,17,30,30,30,1};          // 4
byte D_4[] = {15,15,14,14,14,0,30,30,30};         // 5
byte D_5[] = {16,23,23,23,16,30,30,14,17};        // 6
byte D_6[] = {23,15,15,15,15,0,14,14,0};          // 7
byte D_7[] = {0,14,30,30,29,27,27,27,27};         // 8
byte D_8[] = {17,21,21,21,0,14,14,14,0};          // 9
byte D_9[] = {0,14,14,0,30,30,30,30,29};          // 10
byte D_A[] = {27,21,14,14,14,0,14,14,14};         // 11
byte D_B[] = {1,14,14,14,1,14,14,14,1};           // 12
byte D_C[] = {24,23,15,15,15,15,15,23,24};        // 13
byte D_D[] = {3,21,22,22,22,22,22,21,3};          // 14
byte D_E[] = {0,15,15,15,3,15,15,15,0};           // 15
byte D_F[] = {0,15,15,3,15,15,15,15,15};          // 16
byte D_G[] = {24,23,15,15,15,12,14,14,17};        // 17
byte D_H[] = {14,14,14,14,0,14,14,14,14};         // 18
byte D_I[] = {0,27,27,27,27,27,27,27,0};          // 19
byte D_J[] = {30,30,30,30,30,30,14,14,17};        // 20
byte D_K[] = {14,13,11,7,15,7,11,13,14};          // 21
byte D_L[] = {15,15,15,15,15,15,15,15,0};         // 22
byte D_M[] = {14,4,10,10,10,14,14,14,14};         // 23
byte D_N[] = {14,6,6,10,10,10,12,12,14};          // 24
byte D_O[] = {27,21,14,14,14,14,14,21,27};        // 25
byte D_P[] = {1,14,14,14,1,15,15,15,15};          // 26
byte D_Q[] = {30,26,22,14,14,14,10,9,22};         // 27
byte D_R[] = {1,14,14,1,15,7,11,13,14};           // 28
byte D_S[] = {17,14,15,23,27,29,30,14,17};        // 29
byte D_T[] = {0,10,27,27,27,27,27,27,27};         // 30
byte D_U[] = {14,14,14,14,14,14,14,14,0};         // 31
byte D_V[] = {14,14,14,14,14,14,14,21,27};        // 32
byte D_W[] = {14,14,14,10,10,10,10,10,21};        // 33
byte D_X[] = {14,14,14,21,27,21,14,14,14};        // 34
byte D_Y[] = {14,14,14,21,27,27,27,27,27};        // 35
byte D_Z[] = {0,30,30,21,27,21,15,15,0};          // 36
byte COLON[] = {31,17,17,17,31,17,17,17,31};      // 37
byte SEMICOLON[] = {17,17,17,31,17,17,17,25,23};  // 38
byte LESSTHAN[] = {30,29,27,23,15,23,27,29,30};   // 39
byte EQUAL[] = {31,31,0,31,31,31,0,31,31};        // 40
byte GRTRTHAN[] = {15,23,27,29,30,29,27,23,15};   // 41
byte QUESTION[] = {17,14,30,25,27,27,31,27,31};   // 42
byte D_AT[] = {31,0,14,8,10,8,15,0,31};           // 43
byte D_DASH[] = {31,31,31,0,0,0,31,31,31};        // 44
byte D_SPC[] = {31,31,31,31,31,31,31,31,31};      // 45
byte D_PER[] = {31,31,31,31,31,31,17,17,17};      // 46
byte D_BLK[] = {0,0,0,0,0,0,0,0,0};               // 47

char datalist[47];  // datalist holds an array of all available chracters to pattern match.
byte *decodelist[47]; // decodelist holds an array of memory references to the bit patterns for each character.
byte *refval = 0;  // refval contains a reference to the bit pattern for a specific character entered through the serial terminal.

// the setup routine runs once when you press reset:
void setup() {  
  // Initialize datalist with valid characters.  
  datalist[0] = '0';
  datalist[1] = '1';
  datalist[2] = '2';
  datalist[3] = '3';
  datalist[4] = '4';
  datalist[5] = '5';
  datalist[6] = '6';
  datalist[7] = '7';
  datalist[8] = '8';
  datalist[9] = '9';
  datalist[10] = 'A';
  datalist[11] = 'B';
  datalist[12] = 'C';
  datalist[13] = 'D';
  datalist[14] = 'E';
  datalist[15] = 'F';
  datalist[16] = 'G';
  datalist[17] = 'H';
  datalist[18] = 'I';
  datalist[19] = 'J';
  datalist[20] = 'K';
  datalist[21] = 'L';
  datalist[22] = 'M';
  datalist[23] = 'N';
  datalist[24] = 'O';
  datalist[25] = 'P';
  datalist[26] = 'Q';
  datalist[27] = 'R';
  datalist[28] = 'S';
  datalist[29] = 'T';
  datalist[30] = 'U';
  datalist[31] = 'V';
  datalist[32] = 'W';
  datalist[33] = 'X';
  datalist[34] = 'Y';
  datalist[35] = 'Z';
  datalist[36] = ':';
  datalist[37] = ';';
  datalist[38] = '<';
  datalist[39] = '=';
  datalist[40] = '>';
  datalist[41] = '?';
  datalist[42] = '@';
  datalist[43] = '-';
  datalist[44] = ' ';
  datalist[45] = '.';
  datalist[46] = '*';
  
  // Initialize decodelist with references to the bit patterns for valid characters.
  decodelist[0] = D_0;
  decodelist[1] = D_1;
  decodelist[2] = D_2;
  decodelist[3] = D_3;
  decodelist[4] = D_4;
  decodelist[5] = D_5;
  decodelist[6] = D_6;
  decodelist[7] = D_7;
  decodelist[8] = D_8;
  decodelist[9] = D_9;
  decodelist[10] = D_A;
  decodelist[11] = D_B;
  decodelist[12] = D_C;
  decodelist[13] = D_D;
  decodelist[14] = D_E;
  decodelist[15] = D_F;
  decodelist[16] = D_G;
  decodelist[17] = D_H;
  decodelist[18] = D_I;
  decodelist[19] = D_J;
  decodelist[20] = D_K;
  decodelist[21] = D_L;
  decodelist[22] = D_M;
  decodelist[23] = D_N;
  decodelist[24] = D_O;
  decodelist[25] = D_P;
  decodelist[26] = D_Q;
  decodelist[27] = D_R;
  decodelist[28] = D_S;
  decodelist[29] = D_T;
  decodelist[30] = D_U;
  decodelist[31] = D_V;
  decodelist[32] = D_W;
  decodelist[33] = D_X;
  decodelist[34] = D_Y;
  decodelist[35] = D_Z;
  decodelist[36] = COLON;
  decodelist[37] = SEMICOLON;
  decodelist[38] = LESSTHAN;
  decodelist[39] = EQUAL;
  decodelist[40] = GRTRTHAN;
  decodelist[41] = QUESTION;
  decodelist[42] = D_AT;
  decodelist[43] = D_DASH;
  decodelist[44] = D_SPC;
  decodelist[45] = D_PER;
  decodelist[46] = D_BLK;
  
  // Initialize serial and wait for port to open:
  Serial.begin(9600);

  Serial.println("Started...\n");
   
  // initialize the digital pin as an output.
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);     
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(19, OUTPUT);
  pinMode(20, OUTPUT);
  pinMode(21, OUTPUT);
  pinMode(22, OUTPUT);
  pinMode(23, OUTPUT);
  
  // Initialize LED matrix to OFF state. This will have to change for different array dimensions.
  for (i=0; i<=8; i++) {
    digitalWrite(RN[i], HIGH);
  }
  for (i=0; i<=4; i++) {
    digitalWrite(CN[i], LOW);
  }

}

// the loop routine runs over and over again forever:
void loop() {
  // read from port 3
  // TODO: Need to shut off serial port if using pins 0 and 1 for digital I/O

  while (Serial.available() > 0) {
    inByte = Serial.read();
  
  // Find serial input character in datalist and set refval to bit pattern reference based on datalist index.
  if (Serial.read() == '\r') {
  idx = exposure;
  for (i=0; i<=46; i++) {
    if (datalist[i] == inByte) {
       idx = i;
    }
  }
  refval = decodelist[idx];
  if (idx != exposure) {
    idx = 0;
  }
  
// Write bit pattern to LED matrix. 

  while (idx < exposure) {
    for (i=0; i<rowcnt; i++) {
        digitalWrite(RN[i], LOW);
        digitalWrite(CN[4], !bitRead(refval[i],4));
        digitalWrite(CN[3], !bitRead(refval[i],3));
        digitalWrite(CN[2], !bitRead(refval[i],2));
        digitalWrite(CN[1], !bitRead(refval[i],1));
        digitalWrite(CN[0], !bitRead(refval[i],0));
        delay(strobe);
        digitalWrite(RN[i],HIGH);
      }
    digitalWrite(RN[i], HIGH);
    digitalWrite(CN[0], LOW);
    digitalWrite(CN[1], LOW);
    digitalWrite(CN[2], LOW);
    digitalWrite(CN[3], LOW);
    digitalWrite(CN[4], LOW);    
  idx = idx + 1;
  }
  Serial.println(inByte, DEC);
  }
  }
}

Friday, January 4, 2013

Data file conversion script

It's been a while since I have posted anything to this blog. In my memory the last use of Perl for work was a file parser that did a coordinate transform on one of the fields. I think it's some of the more complicated regular expression applications I have made so far.

The file takes defectivity data generated by an Orbotech display circuit scanner and converts it to a format that is compatible with a TNP laser tool. With the TNP laser we can move to the defective coordinates found by the Orbotech and attempt to salvage the circuit using laser ablation.



# Orbotech_to_TNP_Converter_20111121.pl
#
# Jovan Trujillo
# Arizona State University
# 11/21/2011
#
# This script formats an Orbotech file for use with the TNP Laser system.
#

use strict;

if ($#ARGV != 0) {
print "ARGV = ", $#ARGV, "\n";
print "Usage: Orbotech_to_TNP_Converter_20111121.pl \n";
exit(1);
}

my $rootPath = $ARGV[0];
my @lotList;
my @dataFile;
my $dataLine;
my $tempPath;

# Generate list of subfolders
opendir DIR, $rootPath or die "Couldn't open dir $rootPath: $!\n";
my @folders = readdir DIR;
closedir DIR;

foreach (@folders) {
if (-d $rootPath . "\\" . $_) {
if ($_ eq ".") {}
elsif($_ eq "..") {}
else {
push(@lotList, $_);
}
}
}

my %lotHash = ();
my $currentLot;

#Generate list of lot folders
foreach (@lotList) {
$tempPath = $rootPath . "\\" . $_;
$currentLot = $_;
opendir DIR, $tempPath or die "Couldn't open dir $tempPath: $!\n";
@folders = readdir DIR;
closedir DIR;
# Generate list of process folders
foreach (@folders) {
if (-d $tempPath . "\\" . $_) {
if ($_ eq ".") {}
elsif($_ eq "..") {}
else {
push(@{$lotHash{$currentLot}}, $_);
}
}
}
}

my $lot = "NULL";
my $process_step = "NULL";
my $data_file = "NULL";
my $panel_type = "";
my $panel_id = "";
my $operator_id = "";
my $scan_status = "";
my $queue = "";
my $go_repeats = "";
my $nogo_repeats = "";
my $num_repeats = "";
my $image_file_prefix = "";
my $slot_no = "";
my $glass_size_X = "";
my $glass_size_Y = "";
my $board_center_X = "";
my $board_center_Y = "";
my $panel_status = "NOT CLASSIFIED";
my $align_targets = "";
my $num_defects = "";
my $rep_no = "NULL";
my $X_coord = "NULL";
my $Y_coord = "NULL";
my $size = "NULL";
my $retype = "NULL";
my $type = "NULL";
my $cell_zone = "NULL";
my $size_X = "NULL";
my $size_Y = "NULL";
my $class = "NULL";
my $imagesuffix = "NULL";
my $row_cell_num = "NULL";
my $col_cell_num = "NULL";
my $i = 0;
my $output_file;
my @defect_list;
my $defect_string;

@folders = ();
for my $key (keys %lotHash) {
for ($i=0; $i <= $#{$lotHash{$key}}; $i++) {
$tempPath = $rootPath . "\\" . $key . "\\" . $lotHash{$key}[$i];
$lot = $key;
$process_step = $lotHash{$key}[$i];
opendir DIR, $tempPath or die "Couldn't open dir $tempPath: $!\n";
@folders = readdir DIR;
closedir DIR;
# Open each data file and parse for valid Orbotech Data
foreach (@folders) {
$tempPath = $rootPath . "\\" . $key . "\\" . $lotHash{$key}[$i] . "\\" . $_;
$data_file = $_;
open(DATA, "<$tempPath");

# Open report output file
$output_file = "TNP_" . $data_file;
$tempPath = $rootPath . "\\" . $key . "\\" . $lotHash{$key}[$i] . "\\" . $output_file;
open (REPORT, ">$tempPath") or die "Could not open $tempPath: $!\n";

@dataFile = ;
foreach $dataLine (@dataFile) {
# print "dataLine: $dataLine\n";
if ($dataLine =~ /panel_type\s*=\s*"([\w\s]*)"/) {
$panel_type = $1;
}
if ($dataLine =~ /panel_id\s*=\s*"([\w\s]*)"/) {
$panel_id = $1;
}
if ($dataLine =~ /operator_id\s*=\s*"([\w\s]*)"/) {
$operator_id = $1;
}
if ($dataLine =~ /queue\s*=\s*"([\w\s]*)"/) {
$queue = $1;
}
if ($dataLine =~ /scan_status\s*=\s*"([\w\s]*)"/) {
$scan_status = $1;
}
if ($dataLine =~ /go_repeats\s*=\s*"([\w\s]*)"/) {
$go_repeats = $1;
}
if ($dataLine =~ /nogo_repeats\s*=\s*"([\w\s]*)"/) {
$nogo_repeats = $1;
}
if ($dataLine =~ /image_file_prefix\s*=\s*"([\w\s\.]*)"/) {
$image_file_prefix = $1;
}
if ($dataLine =~ /slot_no\s*=\s*([\d\.\-]*)/) {
$slot_no = $1;
}
if ($dataLine =~ /num_repeats\s*=\s*([\d\.\-]*)/) {
$num_repeats = $1;
}
if ($dataLine =~ /glass_size.x\s*=\s*([\d\.\-]*)/) {
$glass_size_X = $1;
}
if ($dataLine =~ /glass_size.y\s*=\s*([\d\.\-]*)/) {
$glass_size_Y = $1;
}
if ($dataLine =~ /board_center.x\s*=\s*([\d\.\-]*)/) {
$board_center_X = $1;
}
if ($dataLine =~ /board_center.y\s*=\s*([\d\.\-]*)/) {
$board_center_Y = $1;
}
if ($dataLine =~ /panel_status\s*=\s*"([\w\s]*)"/) {
$panel_status = $1;
}
if ($dataLine =~ /align_targets\s*=\s*\(([\d\.\-]*)\s*([\d\.\-]*)\)\s*\(([\d\.\-]*)\s*([\d\.\-]*)\)\s*\(([\d\.\-]*)\s*([\d\.\-]*)\)\s*\(([\d\.\-]*)\s*([\d\.\-]*)\)/ ) {
$align_targets = "(" . $2 . " " . -$1 . ")(" . $4 . " " . -$3 . ")(" . $6 . " " . -$5 . ")(" . $8 . " " . -$7 . ")";
}
if ($dataLine =~ /num_defects\s*=\s*([\d\.\-]*)/) {
$num_defects = $1;
}
if ($dataLine =~ /([\d\.\-]*)\s*,\s*([\d\.\-]*)\s*,\s*([\d\.\-]*)\s*,\s*"*([\w\+\-\.]*)"*\s*,\s*"*([\w\+\-\[\]\.]*)"*\s*,\s*"*([\w\+\-\.]*)"*\s*,\s*"*([\w\+\-\.]*)"*\s*,\s*"*([\w\+\-\.]*)"*\s*,\s*"*([\w\+\-\.]*)"*\s*,\s*"*([\w\+\-\.]*)"*\s*,\s*"*([\w\+\-\.]*)"*\s*,\s*([\d\.]*)\s*,\s*([\d\.]*),?/) {
$rep_no = $1;
$X_coord = $3;
$Y_coord = -$2;
$size = $4;
$retype = $5;
$type = $6;
$cell_zone = $7;
$size_X = $8;
$size_Y = $9;
$class = $10;
$imagesuffix = $11;
$row_cell_num = $12;
$col_cell_num = $13;
$defect_string = $rep_no . ", " . $X_coord . ", " . $Y_coord . ", \"" . $size . "\", \"" . $retype . "\", \"" . $type . "\", \"" . $cell_zone . "\", \"" . $size_X . "\", \"" . $size_Y . "\", \"" . $class . "\", \"" . $imagesuffix . "\", " . $row_cell_num . ", " . $col_cell_num . ", \n";
push(@defect_list, $defect_string);
}
}
print REPORT "panel_type =\"$panel_type\"\n";
print REPORT "panel_id =\"$panel_id\"\n";
print REPORT "operator_id =\"$operator_id\"\n";
print REPORT "queue =\"$queue\"\n";
print REPORT "scan_status =\"$scan_status\"\n";
print REPORT "go_repeats =\"$go_repeats\"\n";
print REPORT "nogo_repeats =\"$nogo_repeats\"\n";
print REPORT "image_file_prefix =\"$image_file_prefix\"\n";
print REPORT "slot_no =$slot_no\n";
print REPORT "num_repeats =$num_repeats\n";
print REPORT "glass_size.x =$glass_size_X\n";
print REPORT "glass_size.y =$glass_size_Y\n";
print REPORT "board_center.x =$board_center_X\n";
print REPORT "board_center.y =$board_center_Y\n";
print REPORT "panel_status =\"$panel_status\"\n";
print REPORT "align_targets =$align_targets\n";
print REPORT "num_defects =$num_defects\n";
print REPORT "defect_list =\"#Rep no. X coord. Y coord. Size-X Size-Y Class ImageSuffix Row_Cell_Num Col_Cell_Num\"\n";
foreach (@defect_list) {
print REPORT $_;
}
$panel_type = "";
$panel_id = "";
$operator_id = "";
$queue = "";
$scan_status = "";
$go_repeats = "";
$nogo_repeats = "";
$image_file_prefix = "";
$slot_no = "";
$num_repeats = "";
$glass_size_X = "";
$glass_size_Y = "";
$board_center_X = "";
$board_center_Y = "";
$panel_status = "NOT CLASSIFIED";
$align_targets = "";
$num_defects = "";
@defect_list = ();
close(DATA);
close(REPORT);
}
@folders = ();
}
}
print "Data conversion complete!\n";