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 Files15円-104 Westlands WD\GIS\HeadsProcessing\Output\HEADS.hds" 2 2 16 "X:2015円 Job Files15円-104 Westlands WD\GIS\HeadsProcessing\OutputProcessing\GIS" "X:2015円 Job Files15円-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 Files15円-104 Westlands WD\GIS\HEADS_ReadHeads1.txt" "X:2015円 Job Files15円-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 Files15円-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?

PolyGeo
65.5k29 gold badges115 silver badges350 bronze badges
asked Nov 15, 2017 at 0:30
9
  • 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. Commented Nov 15, 2017 at 0:51
  • 2
    Use the "{}" button to format code, don't paste an image Commented Nov 15, 2017 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. Commented Nov 15, 2017 at 0:56
  • 1
    AH! {OK, i will edit the original post now.} Commented Nov 15, 2017 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. Commented Nov 15, 2017 at 1:20

1 Answer 1

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.

answered Nov 15, 2017 at 3:19
2
  • 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. Commented Nov 15, 2017 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.. Commented Nov 15, 2017 at 20:56

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.