1

I have a script that produces a text file. The name of the text file it creates is determined by the input parameters chosen by the user. The user chooses what Layer, Stress Period, and Time Step to query form a binary file of Head values, and the text file is named for that Layer, Stress Period, and Timestep, and contains the Heads for that Layer, Stress Period, and Timestep.

I have inserted the script into a model, and the model is supposed to take that output text file and Copy Rows over to another location for further processing.

I added the script to a Toolbox. I set the parameters as follows: enter image description here

The Script is here:


import sys
import struct
import numpy as np
import matplotlib.pyplot as plt
import os.path

INPUTFILE = sys.argv[1]
PPER = sys.argv[2]
PSTP = sys.argv[3]
PLAY = sys.argv[4]
TXTLOC = sys.argv[5]

fid = open(INPUTFILE,'rb')

# Get the correct Offset value for the seek command
for PER in range(1):
    for STP in range(1):
        for k in range(1):
            ITER = struct.unpack('i', fid.read(4))
            KPER = struct.unpack('i', fid.read(4))
            PERTIM = struct.unpack('f', fid.read(4))
            TOTIM = struct.unpack('f', fid.read(4))
            ITER = int(ITER[0])
            KPER = int(KPER[0])

            n = 0
            while(n < 16):
                TEXT = struct.unpack('s', fid.read(1))
                n = n + 1 

            COL = struct.unpack('i', fid.read(4))
            ROW = struct.unpack('i', fid.read(4))
            LAY = struct.unpack('i', fid.read(4))
            NCOL = COL[0]
            NROW = ROW[0]
            NLAY = LAY[0]

PPER = int(PPER)
PSTP = int(PSTP)
PLAY = int(PLAY)

# OFFSET assumes that the header data for each layer array has 44 bytes, and each HEAD value has 4 bytes
OFFSET = (44)+(4*NCOL*NROW*((((PPER-1)*2*NLAY))+((PSTP-1)*NLAY)+(PLAY-1)))
fid.seek(OFFSET)
from array import array
HEADS = array('f')
HEADS.fromfile(fid, NROW*NCOL)

# Get the number of cells to make the nodes list for the output file            
CELLS = (NCOL*NROW)
NODES = list(range(1, CELLS+1))

# Make the output file
OUTPUT = np.column_stack((HEADS, NODES))                
FILEOUT = os.path.join(TXTLOC,"\Heads_L"+str(PLAY)+"_SP"+str(PPER)+"_TS"+str(PSTP)+".txt")
np.savetxt(FILEOUT, OUTPUT, fmt='%12.4E',delimiter=' ')

fid.close()

The Model in which the Script is placed takes the output text file, which should be named by the variable FILEOUT that is created in the Script and named as an Output Parameter, and first runs the Copy Rows tool on it.

When I run the Model, it finishes the Script, but fails on the first next step (which is Copy Rows), as shown in the Model run report here:


Start Time: Tuesday, November 14, 2017 4:17:02 PM
Executing (Read Values From ModFlow Heads File): ReadHeads "X:\2015 Job Files\15-104 Westlands WD\GIS\HeadsProcessing\Output\HEADS.hds" 2 2 16 "X:\2015 Job Files\15-104 Westlands WD\GIS\HeadsProcessing\OutputProcessing\GIS" "X:\2015 Job Files\15-104 Westlands WD\GIS\HEADS_ReadHeads1.txt"
Start Time: Tuesday, November 14, 2017 4:17:09 PM
Running script ReadHeads...
Completed script ReadHeads...
Succeeded at Tuesday, November 14, 2017 4:17:10 PM (Elapsed Time: 0.46 seconds)
Executing (Copy Rows): CopyRows "X:\2015 Job Files\15-104 Westlands WD\GIS\HEADS_ReadHeads1.txt" "X:\2015 Job Files\15-104 Westlands WD\GIS\amk_processing.gdb\copiedvalues" #
Start Time: Tuesday, November 14, 2017 4:17:10 PM
 ERROR 999999: Error executing function.
Failed to execute (Copy Rows).
Failed at Tuesday, November 14, 2017 4:17:10 PM (Elapsed Time: 0.65 seconds)
Failed to execute (ModFlowOutputHeadsContour).
Failed at Tuesday, November 14, 2017 4:17:11 PM (Elapsed Time: 8.42 seconds)

It completes the script, without errors, but then there are a couple problems. First, obviously, it failed to Copy Rows. But, more frustratingly, it also did not name the text file the right name or save it to the right location. It should have called it the result of this operation in the Script:

FILEOUT = os.path.join(TXTLOC,"\Heads_L"+str(PLAY)+"_SP"+str(PPER)+"_TS"+str(PSTP)+".txt"). 

But instead, it called it "X:\2015 Job Files\15-104 Westlands WD\GIS\HEADS_ReadHeads1.txt". That is just the generic default output file name and save location.

Furthermore, WHen i went to that location, no such file exists - nor is there a file in the location where I wanted it saved.

How do I make the Script save the text file in the manner I desired, and then pass it to the Model Tool as an input file?

  • Maybe add an output parameter and then arcpy.SetParameterAsText(n) where n is the index of the parameter, you should be able to recycle the parameter now as an input to another tool... or even better still take the text file full path as an input parameter (FILEOUT = sys.argv[2]) from a model variable rather than trying to set the name within the script itself. Please paste code as text, not as screenshots, it's easier to read text and users can copy/paste to test sections. – Michael Stimson Nov 15 '17 at 0:51
  • 2
    Use the "{}" button to format code, don't paste an image – user2856 Nov 15 '17 at 0:55
  • I tried to post the script as text, but it went crazy in there, ignoring hard returns, bolding a bunch of it, only insetting a snippet as if it were code and the rest was just poorly-formatted text. – user32907 Nov 15 '17 at 0:56
  • 1
    AH! {OK, i will edit the original post now.} – user32907 Nov 15 '17 at 0:58
  • I actually do have an Output parameter. Its in the list of Parameters for the Script, in an image in the original post. What I don't understand, is how to make THAT be the same thing as the FILEOUT that the Script actually creates? You suggested that I try arcpy.SetParameterAsText(6) (where the FILEOUT Parameter is the 6th in that list i showed.). I am trying that now, but its asking me for another argument, so i have to figure out what that is. – user32907 Nov 15 '17 at 1:20
1

I think I see the problem here, your index is out by one. Consider the following (GenOutMessage):

import os, sys, arcpy

OutMessage = sys.argv[1]
arcpy.SetParameterAsText(1,OutMessage) # 2nd parameter is 1

enter image description here

and then a simple consumer of parameter 2 (ConsumeMessage):

import os, sys, arcpy
mess = sys.argv[1]
arcpy.AddMessage(mess)

and put into a model: enter image description here

By some cruel twist input parameters start at 1, because 0 is the script that is being called, but output parameters start at 0 so in this example of GenOutMessage InMessage is input parameter 1 and outMessage is output parameter 1 - both are index 1. In your example the output parameter, assuming it immediately follows TXTLOC is index 5.

  • I tried it with the second argument set to FILEOUT, with no quotes. I moved the line FILEOUT = os.path.join(TXTLOC,"\Heads_L"+str(PLAY)+"_SP"+str(PPER)+"_TS"+str(PSTP)+".txt") to a spot between the several sys.argv statements and the setparameters statement. The script runs now, and the model gets the information and does the rest of the things I need it to do. However, the text file that should be created never shows up, not in the TXTLOC folder or anywhere else that i can find. – user32907 Nov 15 '17 at 19:27
  • If you run the script from CMD does the text file appear? (open a command window and drag in the script from explorer then drag/type in every input individually with a space in between). You are using numpy to write to the text file with, I haven't used numpy enough to give guidance with it. Perhaps you could put a few debug print statements in to prove that OUTPUT isn't empty NROWS, NCOLS aren't 0 etc.. – Michael Stimson Nov 15 '17 at 20:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.