# -*- coding: utf-8 -*-
"""
Created on Tue Oct 18 10:53:19 2022

@author: s7970488
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2022 C. Ian Short
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
"""

import math
import numpy

#These file operations have to be in separate function to force 
#python to release the fileHandle each time
def getNumLines(lineListFile):
    
    numLines = 0
    with open(lineListFile, 'r', encoding='utf-8') as fHandle:

        #For VALD output we know 1st two lines are header:
        thisLine = fHandle.readline()
        print(thisLine)
        thisLine = fHandle.readline()
        print(thisLine)
    
        while (thisLine != ""):
            thisLine = fHandle.readline()
            numLines+=1
        
        numLines-=1
        
    #finally:
    fHandle.close()
    
    return numLines

#These file operations have to be in separate function to force 
#python to release the fileHandle each time
def getMasterLine(lineListFile, numRecords):
    
    masterLineString = ""
    thisLine = ""
    
    with open(lineListFile, 'r', encoding='utf-8') as fHandle:

        #For VALD output we know 1st two lines are header:
        thisLine = fHandle.readline()
        thisLine = fHandle.readline()
 
        #Loop over 4-line records:
        for i in range(numRecords):
            #1st line of record is our data line
            thisLine = fHandle.readline()
            masterLineString = masterLineString + thisLine
            #next three lines of each record are info we don't need
            thisLine = fHandle.readline()
            thisLine = fHandle.readline()
            thisLine = fHandle.readline()
        
        
    #finally:
    fHandle.close()
    
    return masterLineString
 
#// Argument 0: Name of ascii input line list
#// Argument 1: Name of byte data output line list
#asciiListStr = args[0]
#byteListStr = args[1]
asciiListStr = "atomLineListVALDOct2022"
byteListStr = "atomLineListVALDOct2022Bytes"

logE = math.log10(math.e) #// for debug output
logE10 = math.log(10.0) #//natural log of 10
#//
#//These atomic and molecular data are really just here for the human reader's
#// reference - they're not actually used by the code:
#////
#////Abundance table adapted from PHOENIX V. 15 input bash file
#////Solar abundances:
#//// c='abundances, Anders & Grevesse',
#//

nelemAbnd = 41
nome = [0 for i in range(nelemAbnd)]
cname = ["" for i in range(nelemAbnd)]
#//nome is the Kurucz code - in case it's ever useful
nome[0]=   100
nome[1]=   200
nome[2]=   300
nome[3]=   400
nome[4]=   500
nome[5]=   600
nome[6]=   700
nome[7]=   800
nome[8]=   900
nome[9]=  1000
nome[10]=  1100
nome[11]=  1200
nome[12]=  1300
nome[13]=  1400
nome[14]=  1500
nome[15]=  1600
nome[16]=  1700
nome[17]=  1800
nome[18]=  1900
nome[19]=  2000
nome[20]=  2100
nome[21]=  2200
nome[22]=  2300
nome[23]=  2400
nome[24]=  2500
nome[25]=  2600
nome[26]=  2700
nome[27]=  2800
nome[28]=  2900
nome[29]=  3000
nome[30]=  3100
nome[31]=  3600
nome[32]=  3700
nome[33]=  3800
nome[34]=  3900
nome[35]=  4000
nome[36]=  4100
nome[37]=  5600
nome[38]=  5700
nome[39]=  5500
nome[40]=  3200

cname[0]="H"
cname[1]="He"
cname[2]="Li"
cname[3]="Be"
cname[4]="B"
cname[5]="C"
cname[6]="N"
cname[7]="O"
cname[8]="F"
cname[9]="Ne"
cname[10]="Na"
cname[11]="Mg"
cname[12]="Al"
cname[13]="Si"
cname[14]="P"
cname[15]="S"
cname[16]="Cl"
cname[17]="Ar"
cname[18]="K"
cname[19]="Ca"
cname[20]="Sc"
cname[21]="Ti"
cname[22]="V"
cname[23]="Cr"
cname[24]="Mn"
cname[25]="Fe"
cname[26]="Co"
cname[27]="Ni"
cname[28]="Cu"
cname[29]="Zn"
cname[30]="Ga"
cname[31]="Kr"
cname[32]="Rb"
cname[33]="Sr"
cname[34]="Y"
cname[35]="Zr"
cname[36]="Nb"
cname[37]="Ba"
cname[38]="La"
cname[39]="Cs"
cname[40]="Ge"

file = [\
        #"VALD.H.4218470"]
        #"VALD.He",\
        #"VALD.Li",
        #"VALD.Be",\
        #"VALD.B",\
        "VALD.C"]
        #"VALD.N",\
        #"VALD.O",\
        #"VALD.F",\
        #"VALD.Ne",\
        #"VALD.Na",\
        #"VALD.Mg",\
        #"VALD.Al",\
        #"VALD.Si",\
        #"VALD.P",\
        #"VALD.S",\
        #"VALD.Cl",\
        #"VALD.Ar",\
        #"VALD.K",\
        #"VALD.Ca",\
        #"VALD.Sc",\
        #"VALD.Ti",\
        #"VALD.V",\
        #"VALD.Cr",\
        #"VALD.Mn",\
        #"VALD.Fe1",\
        #"VALD.Fe2",\
        #"VALD.Fe3",\
        #"VALD.Fe4",\
        #"VALD.Fe5",\
        #"VALD.Fe6",\
        #"VALD.Co",\
        #"VALD.Ni",\
        #"VALD.Cu",\
        #"VALD.Zn",\
        #"VALD.Ge",\
        #"VALD.Ga",\
        #"VALD.Rb",\
        #"VALD.Sr",\
        #"VALD.Y",\
        #"VALD.Zr",\
        #"VALD.Nb",\
        #"VALD.Ba",\
        #"VALD.La",\
        #"VALD.Cs"\
        #    ]
        
fileLen = len(file)

#String species;


#//
#//     FILE I/O Section
#//
#//External line list input file approach:

dataPath = "./InputData/VALD/"
#lineListFile = dataPath + asciiListStr + ".dat"


#//Put entire line list into one big string - we'll sort it out later
masterLineString = "" #//initialize
#thisLine = "Default"
newField = "|" #//output field separator - consistent with NIST ascii output 
newRecord = "%%" #//output record separator
masterStringOut = "" #//initialize master string for output 
numFields = 13 #//number of ","-separated INPUT fields in NIST ascii dump

thisRecord = ["" for i in range(numFields)]
subFields = ["" for i in range(2)]
ionStage = ""

#We need some logic for sorting the line list in order of increasing wavelength post-facto
masterNumLines = 0 #Total number of lines among all elements/files
list2_ptr = [] #//pointer into line list2 that we're populating
recordString = ""
recordStringArr = []
waveArr = []

myString = ""
myStringUp = ""
#elName = ""  //useful helper
giString = "";
gjString = "";
log10gf = 0.0;
Jlo = 0.0
Jup = 0.0;
one = 1.0;
two = 2.0;
g_i = 0;
g_j = 0;
blankFlag = False 
blankFlagUp = False


#int array_ptr; //pointer into array containing line list2 data file line-by-line Strings

#index of refraction of air
index = 1.00029 

#may not need splitChar is we can split string on end-of-line character, "\n"
#splitChar = "%%" #//character separating new lines

#System.out.println(" *********************************************** ");
#System.out.println("  ");
#System.out.println("  ");
#System.out.println("BEFORE FILE READ");
#System.out.println("  ");
#System.out.println("  ");
#System.out.println(" *********************************************** ");


for thisFile in file:
    
    #print("\n thisFile ", thisFile)
    
    lineListFile = dataPath + '/' + thisFile # + ".dat"
    #rint("lineListFile ", lineListFile)
    numRecords = 0
    numLines = 0
    
    """
    #try:
    #fHandle = open(lineListFile, 'r', encoding='utf-8')
    with open(lineListFile, 'r', encoding='utf-8') as fHandle:

        #For VALD output we know 1st two lines are header:
        thisLine = fHandle.readline()
        print(thisLine)
        thisLine = fHandle.readline()
        print(thisLine)
    
        while (thisLine != ""):
            thisLine = fHandle.readline()
            numLines+=1
        
        
    #finally:
    fHandle.close()
    """
    #These file operations have to be in separate function to force 
    #python to release the fileHandle each time
    numLines = getNumLines(lineListFile)

    
    #VALD has 4 lines per record:
    numRecords = numLines / 4
    numRecords = int(numRecords)
    masterNumLines+=numRecords

    print("numLines ", numLines, " numRecords ", numRecords)

    #Reality check:
    if ( (numLines % 4) != 0 ):
            print("SOMETHING's WRONG, numLines % 4 = ", numLines%4)

    """
    #try:
    print("\n lineListFile 2 \n", lineListFile)
    #fHandle = open(lineListFile, 'r', encoding='utf-8')
    with open(lineListFile, 'r', encoding='utf-8') as fHandle:

        #For VALD output we know 1st two lines are header:
        thisLine = fHandle.readline()
        thisLine = fHandle.readline()
 
        #Loop over 4-line records:
        for i in range(numRecords):
            #1st line of record is our data line
            thisLine = fHandle.readline()
            masterLineString = masterLineString + thisLine
            #next three lines of each record are info we don't need
            thisLine = fHandle.readline()
            thisLine = fHandle.readline()
            thisLine = fHandle.readline()
        
        
    #finally:
    fHandle.close()
    """
    #These file operations have to be in separate function to force 
    #python to release the fileHandle each time
    masterLineString = getMasterLine(lineListFile, numRecords)
        
    #System.out.println(" *********************************************** ");
    #System.out.println("  ");
    #System.out.println("  ");
    #System.out.println("AFTER FILE READ");
    #System.out.println("  ");
    #System.out.println("  ");
    #System.out.println(" *********************************************** ");

    #Split string on new line character "\n":
    arrayLineString = masterLineString.split("\n") 
    #print("arrayLineString[0] ", arrayLineString[0])
    #print("arrayLineString[1] ", arrayLineString[1])
    #//Number of lines MUST be the ONLY entry on the first line

    #numLineList = len(arrayLineString)
    numLineList = numRecords
    #//System.out.println("arrayLineString[0] " + arrayLineString[0]);
    #list2Length = len(arrayLineString) - 1 #//useful for checking if something's wrong?
    #System.out.println("numLineList " + numLineList + " list2Length " + list2Length); 
    #//        for (int i = 0; i < 5; i++){
    #//           System.out.println(arrayLineString[i]);
    #//        }

    #// In general there will be header information.  The first block of six lines (blank separartor line
    #//followed by five data lines) must be immediately preceded by a line whose first six columns contain 
    #//the string "START:", followed by the correct pipe symbol ("|") separators  


    #//Okay, here we go:
    print("numLineList ", numLineList)
    #String list2Element; // = new String[numLineList]; //element
    #String list2LogGammaCol; // = new double[numLineList];
    #//Log of unitless oscillator strength, f 
    #double list2Logf; // = new double[numLineList];
    #//Einstein coefficinet for spontaneous de-excitation
    #double list2LogAij; // = new double[numLineList];
    #//Unitless statisital weight, lower E-level of b-b transition                 
    #double list2GwL; // = new double[numLineList];

    
    #//First line in block of six is always a blank separator line:
    #numBlocks = int((list2Length - (startLine+1))/6) - 1
    #// int rmndr = (list2Length - (startLine+1)) % 6
    #rmndr = 0 #//for now - something's wrong
    #System.out.println("numBlocks " + numBlocks + " rmndr " + rmndr); 
    #String myString, myStringUp, elName;  //useful helper
    #double log10gf, Jnumer, Jdenom, Jfinal;
    #int testLength, thisUpperBound;
    #boolean blankFlag;


    #Sample from VALD "log format" output:
    #Elm Ion       WL_air(A)  log gf* E_low(eV) J lo  E_up(eV) J up   lower   upper    mean   Rad.  Stark    Waals
    #'H 1',       3648.26000,  -4.272, 10.1988,  1.5, 13.5963,  2.5, 99.000, 99.000, 99.000, 8.800, 2.000,80.000,
    #    0,                1,       2,       3,    4,       5,    6,      7,      8,      9,    10,    11,    12


    for i in range(numLineList):

        recordString= ""
        #//System.out.println("i " + i + " array_ptr " + array_ptr);
        #//System.out.println("arrayLineString " + arrayLineString[array_ptr]); 
        #//"|" turns out to mean something in regexp, so we need to escape with '\\':
        #//Get the chemical element symbol - we don't know if it's one or two characters
        thisRecord = arrayLineString[i].split(",") 
        #print(thisRecord)

        #//
        #// ","-separated field [0] is the species - element AND ion. stage
        #//
        testField = thisRecord[0]
        #//Contains both chemical symbol and ionization stage, so have to "sub-split":
        testField = testField.strip()
        #strip off leading and trailing single quote marks
        fieldLength = len(testField)
        testField2 = testField[1:fieldLength-1]
        testField = testField2
        subFields = testField.split(" ")
        myString = subFields[0]
        #//System.out.println("element " + myString);
        list2Element = myString.strip()
        #print("list2Element ", list2Element)
        recordString = recordString + list2Element + newField
        
        myString = subFields[1]
        #We have to dress this up to look like NIST output - ie. Roman numeral ion. stage:
        if (myString == '1'):
            ionStage = "I"
        elif (myString == '2'):
            ionStage = "II"
        elif (myString == '3'):
            ionStage = "III"
        elif (myString == '4'):
            ionStage = "IV"
        elif (myString == '5'):
            ionStage = "V"
        elif (myString == '6'):
            ionStage = "VI"
        elif (myString == '7'):
            ionStage = "VII"
        elif (myString == '8'):
            ionStage = "VIII"
        elif (myString == '9'):
            ionStage = "IX"
        elif (myString == '10'):
            ionStage = "X"    
        #//System.out.println("ion " + myString.trim());
        #//list2StageRoman[list2_ptr] = myString.trim();
        #print("ionStage ", ionStage)
        recordString = recordString + ionStage.strip() + newField
        #//
        #// "|"-separated field [1] is wavelength in nm
        #//
        myString = thisRecord[1]
        #//We need to be ready for blank fields - checking for this in Java is hard!
        #//testLength = bounds[1] - bounds[0];
        blankFlag = True
        if (len(myString.strip()) > 0):
            blankFlag = False 
                 
        if (blankFlag):
            myString = " " 
        else:
            #Convert from A to nm for consistency with NIST linelist
            dumWav = float(myString)/10.0
            #Convert back to wavelength in vacuo
            dumWav = dumWav * index
            waveArr.append(dumWav)
            dumWav = round(dumWav, 4)
            myString = str(dumWav)
            
        #// else { 
        #//  myString.trim();
        #//  list2Lam0[list2_ptr] = Double.parseDouble(myString);
        #// }
        #//System.out.println("lambda " + myString.trim());
        #print("dumWav ", myString)
        recordString = recordString + myString.strip() + newField
        #//
        #// ","-separated field [2] in NIST output is Einstein A_ij coeffcient for spontaneous de-excitation: 
        #The closest we have in the VALD list is record [10], 'Rad.' damping param, which I assume is log_10()
        #//
        myString = thisRecord[10];
        #//We need to be ready for blank fields - checking for this in Java is hard!
        #//testLength = bounds[1] - bounds[0];
        blankFlag = True
        if (len(myString.strip()) > 0):
            blankFlag = False 
                 
        if (blankFlag):
            myString = "-19.0" 
        else: 
            myString.strip()
            #list2LogAij = math.log10(float(myString)) #//careful - base 10 log of A_ji
            #myString = str(list2LogAij)
             
        #//System.out.println("logAji " + myString.trim());
        #print("logAji ", myString)
        recordString = recordString + myString.strip() + newField;
    
        # We need to get 'J lo' - lower E-level J quantum number - next so we can create f_ij
        #from log(gf)
        #//
        #// ","-separated field [4] is J quantum number of lower E-level is *decimal* form 
        #//   
        #We have to save this to write to output string in correct order later:
        JloString = "1"
        JloString = thisRecord[4]  
        blankFlag = True
        if (len(JloString.strip()) > 0):
            blankFlag = False 
                 
        if (blankFlag == True):
            Jlo =  0.0 
            JloString = "0.0" 
        else: 
            JloString.strip()
            Jlo = float(JloString) 
            #stastical weight of lower level, g_i = 2*J_lo + 1 - RS-coupling?
            g_i = 2.0*Jlo + 1.0
            giString = str(int(g_i))
        
    
        #//
        #// ","-separated field [2] is log weighted oscillator strength log(g_i*f_ij): 
        #//
        myString = thisRecord[2] 
        #//We need to be ready for blank fields - checking for this in Java is hard!
        #//testLength = bounds[3] - bounds[2];
        blankFlag = True
        if (len(myString.strip()) > 0):
            blankFlag = False 
                 
        if (blankFlag == True):
            list2Logf =  -9.0 #//careful - base 10 log of f
            myString = "-9.0" 
        else: 
            myString.strip()
            list2gf = math.pow(10, float(myString))
            list2f = list2gf / g_i
            list2Logf = math.log10(list2f) #//careful - base 10 log of f
            list2Logf = round(list2Logf, 6)
            myString = str(list2Logf)
             
        #//System.out.println("log(f) " + myString.trim());
        #print("log(f) ", myString)
        recordString = recordString + myString.strip() + newField
#////
#//// "|"-separated field [4] is log_10 gf_ij ("log gf") - 
#////
#//// Originally needed to recover "g_i" from f_ij and log(gf)
#////  - We may not need this anymore - latest line list has "g_i" values
#////
#//           //process this so we can back out the statistical weight, g_l of the lower E-level (heh-heh!)
#//           myString = thisRecord[4]; 
#//           //We need to be ready for blank fields - checking for this in Java is hard!
#//           //testLength = bounds[4] - bounds[3];
#//           blankFlag = true;
#//               if (myString.trim().length() > 0){
#//                  blankFlag = false; 
#//                 }
#//           if (blankFlag){
#//               list2GwL = 1.0; 
#//               myString = "1.0"; 
#//             } else { 
#//               myString.trim();
#//               log10gf = Double.parseDouble(myString); // log_10 of gf
#//               //Lower E level statistical weight
#//               list2GwL = 2.0 * ( Math.exp(log10gf - list2Logf) ); 
#//               list2GwL = (double) ( (int) list2GwL );
#//               myString = Double.toString(list2GwL);
#//             }
#//           //System.out.println("g_i " + myString.trim());
#//           masterStringOut = masterStringOut + myString.trim() + newField;
#//
#//
#//
#// In NIST: ","-separated field [6] is BOTH the Lower & Upper E-level excitation energy in eV
# In VALD long format:  Record [3] is Lower E-level and record [5] is Upper E-level
#//
        testField = thisRecord[3]
        testFieldUp = thisRecord[5]
        #//System.out.println("list2Element " + list2Element + " testField " + testField + " testField.trim().length() " + testField.trim().length());
        #//testLength = bounds[6] - bounds[5];
        blankFlag = True
        blankFlagUp = True
        #//for (int kk = 0; kk < testLength-2; kk++){
        #//testChar = testField.substring(kk, kk+2);
        testField = testField.strip()
        testFieldUp = testFieldUp.strip()
        if (len(testField) > 0):
            blankFlag = False 
        if (len(testFieldUp) > 0):
            blankFlagUp = False     
                 
            #//   }  
        if (blankFlag):
            myString = "0.0"
            #//System.out.println("blankFlag triggered, myString = " + myString); 
        else:
            #subFields = testField.split("-")
            myString = testField #//lower E level 


        if (blankFlagUp):
            myStringUp = "0.0" 
        else:
            #subFields = testField.split("-")
            myStringUp = testFieldUp #//upper E level 
                
            #//myString.trim();
            #//list2ChiL[list2_ptr] = Double.parseDouble(myString);
             
        #//System.out.println("final myString = " + myString); 
        #//System.out.println("loggf " + myString.trim());
        #//System.out.println("chi_i " + myString.trim() + " chi_j " + myStringUp.trim());
        #print("E-lower ", myString, " E-upper ", myStringUp)
        recordString = recordString + myString.strip() + newField + myStringUp.strip() + newField

        #//
        #// ","-separated field [4] is Lower E-level J quantum number in *decimal* form
        # We already processed it earlier and stored it in JloString
        #//
             

        #//System.out.println("J_i " + myString.trim());
        #print("JLo ", JloString)
        recordString = recordString + JloString.strip() + newField;
 
        #//
        #// ","-separated field [6] is Upper E-level J quantum number in *decimal* form
        #//
        #//Upper J quantum number 
        testField = thisRecord[6] 
        #//System.out.println("list2Element " + list2Element + " testField " + testField + " testField.trim().length() " + testField.trim().length());
        #//testLength = bounds[6] - bounds[5];
        blankFlag = True
        #//for (int kk = 0; kk < testLength-2; kk++){
        #//testChar = testField.substring(kk, kk+2);
        JupString = "1"
        testField = testField.strip()
        if (len(testField) > 0):
            blankFlag = False 
                 
        if (blankFlag):
            JupString = "1"
            #//System.out.println("blankFlag triggered, myString = " + myString); 
        else:
            JupString = testField
            Jup = float(JupString) #//careful - base 10 log of f
            #stastical weight of uppwer level, g_j = 2*J_up + 1 - RS-coupling?
            g_j = 2.0*Jup + 1.0
            gjString = str(int(g_j))
             

        #//System.out.println("J_j " + myString.trim());
        #print("Jup ", JupString)
        recordString = recordString + JupString.strip() + newField
        #//
        #// In NIST: "|"-separated field [11] is the statistical weight, g_i of BOTH the lower and upper level 
        # For VALD - we already calculated g_i and g_j earlier and stored them in giString
        # and gjString
        #//

        #print("giString ", giString, " gjString ", gjString)
        recordString = recordString + giString.strip() + newField + gjString.strip() + newRecord
        #//

        #//We've gotten everything we need from the closed blocks of the NIST line list:
        recordStringArr.append(recordString)
        #list2_ptr+=1
        #fHandle.close()
        
    #} //i loop
#file loop

#Now we have to sort the record array by wavelength and then write masterStringOut
"""From https://stackoverflow.com/questions/6618515/sorting-list-based-on-values-from-another-list
a = [3,2,1]
b=['C', 'N', 'O']
z = [x for _,x in sorted(zip(a,b))]
OR
z2 = [x for _,x in sorted(zip(a,b), key = lambda pair: pair[0])]

OR:  SImpler?
From https://stackoverflow.com/questions/6422700/how-to-get-indices-of-a-sorted-array-in-python
numpy.argsort(myList)
array([0, 1, 2, 4, 3])
"""

#Indices of record array in ascending wavelength order:
list2_ptr = numpy.argsort(numpy.array(waveArr))

#Concatenated string with whole line list for encode() method
for i in list2_ptr:
    
    print("i ", i, " recordStringArr[i] ", recordStringArr[i])
    masterStringOut+=recordStringArr[i]

####


#Java: byte[] barray = masterStringOut.getBytes();
barray = masterStringOut.encode('utf-8')
#//byte[] barray = masterStringOut.getBytes("UTF-8")
#// what do I do with this??   throws UnsupportedEncodingException; 
#System.out.println(" ");
#System.out.println("*************************");
#System.out.println(" ");
#System.out.println("This needs to be detected by GrayStar3Server.java: ");
#System.out.println(" ");
#System.out.println("size of barray " + barray.length);
#System.out.println(" ");
#System.out.println("*************************");
#System.out.println(" ");
# // System.out.println("barray " + barray);
# //
#Java: ByteFileWrite.writeFileBytes(byteListStr, barray); 
with open(byteListStr, 'wb') as fHandle:
    fHandle.write(barray)

#fHandle closed automatically upon exit from with:
#//
#    } // end main()