예제 #1
0
def create_inp_build_instructions(inpA, inpB, path, filename, comments=''):
    """
    pass in two inp file paths and produce a spreadsheet showing the differences
    found in each of the INP sections. These differences should then be used
    whenever we need to rebuild this model from the baseline reference model.


    Note: this should be split into a func that creates a overall model "diff"
    that can then be written as a BI file or used programmatically
    """

    allsections_a = funcs.complete_inp_headers(inpA)
    modela = swmmio.Model(inpA)
    modelb = swmmio.Model(inpB)

    #create build insructions folder
    if not os.path.exists(path):
        os.makedirs(path)
    filepath = os.path.join(path, filename) + '.txt'
    # xlpath = os.path.join(path, filename) + '.xlsx'
    # excelwriter = pd.ExcelWriter(xlpath)
    # vc_utils.create_change_info_sheet(excelwriter, modela, modelb)

    problem_sections = [
        '[TITLE]', '[CURVES]', '[TIMESERIES]', '[RDII]', '[HYDROGRAPHS]'
    ]
    with open(filepath, 'w') as newf:

        #write meta data
        metadata = {
            #'Baseline Model':modela.inp.path,
            #'ID':filename,
            'Parent Models': {
                'Baseline': {
                    inpA: vc_utils.modification_date(inpA)
                },
                'Alternatives': {
                    inpB: vc_utils.modification_date(inpB)
                }
            },
            'Log': {
                filename: comments
            }
        }
        #print metadata
        vc_utils.write_meta_data(newf, metadata)
        for section in allsections_a['order']:
            if section not in problem_sections:
                #calculate the changes in the current section
                changes = INPDiff(modela, modelb, section)
                data = pd.concat(
                    [changes.removed, changes.added, changes.altered])
                #vc_utils.write_excel_inp_section(excelwriter, allsections_a, section, data)
                vc_utils.write_inp_section(
                    newf,
                    allsections_a,
                    section,
                    data,
                    pad_top=False,
                    na_fill='NaN')  #na fill fixes SNOWPACK blanks spaces issue
예제 #2
0
def search_for_duplicates(inp_path, verbose=False):
    """
    scan an inp file and determine if any element IDs are duplicated in
    any section. Method: count the uniques and compare to total length
    """
    headers = funcs.complete_inp_headers(inp_path)['headers']
    dups_found = False
    for header, cols, in headers.items():
        if cols != 'blob':

            df = dataframes.create_dataframeINP(inp_path, section=header)
            elements = df.index
            n_unique = len(elements.unique())  #number of unique elements
            n_total = len(elements)  #total number of elements
            if verbose:
                print('{} -> (uniques, total) -> ({}, {})'.format(
                    header, n_unique, n_total))

            if n_unique != n_total:
                dups = ', '.join(
                    df[df.index.duplicated()].index.unique().tolist())
                print('duplicate found in {}\nsection: {}\n{}'.format(
                    inp_path, header, dups))
                dups_found = True

    return dups_found
예제 #3
0
파일: inp.py 프로젝트: aerispaha/swmmio
    def build(self, baseline_dir, target_path):
        """
        build a complete INP file with the build instructions committed to a
        baseline model.
        """
        basemodel = swmmio.Model(baseline_dir)
        allheaders = funcs.complete_inp_headers(basemodel.inp.path)
        #new_inp = os.path.join(target_dir, 'model.inp')
        with open (target_path, 'w') as f:
            for section in allheaders['order']:

                #check if the section is not in problem_sections and there are changes
                #in self.instructions and commit changes to it from baseline accordingly
                if (section not in problem_sections
                    and allheaders['headers'][section] != 'blob'
                    and section in self.instructions):

                    #df of baseline model section
                    basedf = create_dataframeINP(basemodel.inp.path, section)

                    #grab the changes to
                    changes = self.instructions[section]

                    #remove elements that have alterations and or tagged for removal
                    remove_ids = changes.removed.index | changes.altered.index
                    new_section = basedf.drop(remove_ids)

                    #add elements
                    new_section = pd.concat([new_section, changes.altered, changes.added])
                else:
                    #section is not well understood or is problematic, just blindly copy
                    new_section = create_dataframeINP(basemodel.inp.path, section=section)

                #write the section
                vc_utils.write_inp_section(f, allheaders, section, new_section)
예제 #4
0
def test_complete_headers(test_model):
    headers = functions.complete_inp_headers(test_model.inp.path)
    sections_in_inp = [
        '[TITLE]', '[OPTIONS]', '[EVAPORATION]', '[RAINGAGES]', '[SUBCATCHMENTS]', '[SUBAREAS]', '[INFILTRATION]',
        '[JUNCTIONS]', '[OUTFALLS]', '[STORAGE]', '[CONDUITS]', '[PUMPS]', '[WEIRS]', '[XSECTIONS]', '[INFLOWS]',
        '[CURVES]', '[TIMESERIES]', '[REPORT]', '[TAGS]', '[MAP]', '[COORDINATES]', '[VERTICES]', '[Polygons]',
        '[SYMBOLS]'
    ]
    assert (all(section in headers['headers'] for section in sections_in_inp))
예제 #5
0
파일: text.py 프로젝트: timebridge/swmmio
def inline_comments_in_inp(filepath, overwrite=False):
    """
    with an existing INP file, shift any comments that have been placed above the
    element (behavoir from saving in GUI) and place them to the right, inline with
    the element. To improve readability
    """
    newfilename = os.path.splitext(
        os.path.basename(filepath))[0] + '_unGUI.inp'
    newfilepath = os.path.join(os.path.dirname(filepath), newfilename)
    allheaders = complete_inp_headers(filepath)

    with open(filepath) as oldf:
        with open(newfilepath, 'w') as new:

            comment_concat = [
            ]  #to hold list of comments (handles multiline comments)
            current_section = allheaders['order'][0]
            for line in oldf:

                #determine what section we are in by noting when we pass double brackets
                if '[' and ']' in line:
                    current_section = line.strip()

                #if line.count(';') == 1 and line.strip()[0]==';':
                if len(line.strip()) > 1:
                    if line.strip()[0] == ';' and ''.join(
                            line.strip()[:2]) != ';;':
                        #print line.strip()[:2]
                        #this is a comment bc first char is ; and there
                        #seconf char is not (which would resember the header section)
                        words = line.split()
                        hdrs = allheaders['headers'][current_section].split(
                        )  #headerrow.split()
                        perc_match_to_header = float(
                            len([x for x in words if x in hdrs])) / float(
                                len(hdrs))
                        if perc_match_to_header <= 0.75:
                            comment_concat.append(line.strip())
                    else:
                        #print comment_concat
                        #this row has data, tack any comment to the line end
                        comment_string = ''
                        if len(comment_concat) > 0:
                            comment_string = r' '.join(comment_concat)
                        newlinestring = line.strip() + comment_string + '\n'
                        new.write(newlinestring)
                        comment_concat = []
                else:
                    #write the short line
                    new.write(line)

    #rename files and remove old if we should overwrite
    if overwrite:
        os.remove(filepath)
        os.rename(newfilepath, filepath)
def test_complete_headers(test_model):
    headers = functions.complete_inp_headers(test_model.inp.path)
    sections_in_inp = [
        '[TITLE]', '[OPTIONS]', '[EVAPORATION]', '[RAINGAGES]',
        '[SUBCATCHMENTS]', '[SUBAREAS]', '[INFILTRATION]', '[JUNCTIONS]',
        '[OUTFALLS]', '[STORAGE]', '[CONDUITS]', '[PUMPS]', '[WEIRS]',
        '[XSECTIONS]', '[INFLOWS]', '[CURVES]', '[TIMESERIES]', '[REPORT]',
        '[TAGS]', '[MAP]', '[COORDINATES]', '[VERTICES]', '[Polygons]',
        '[SYMBOLS]'
    ]
    assert (all(section in headers['headers'] for section in sections_in_inp))
예제 #7
0
def test_complete_inp_headers():

    headers = [
        '[TITLE]', '[OPTIONS]', '[EVAPORATION]', '[JUNCTIONS]', '[OUTFALLS]',
        '[CONDUITS]', '[XSECTIONS]', '[DWF]', '[REPORT]', '[TAGS]', '[MAP]',
        '[COORDINATES]', '[VERTICES]',
    ]

    h1 = funcs.complete_inp_headers(MODEL_XSECTION_BASELINE)

    assert(all(h in h1['headers'] for h in headers))
    assert(h1['order'] == headers)
예제 #8
0
파일: text.py 프로젝트: aerispaha/swmmio
def inline_comments_in_inp(filepath, overwrite=False):

    """
    with an existing INP file, shift any comments that have been placed above the
    element (behavoir from saving in GUI) and place them to the right, inline with
    the element. To improve readability
    """
    newfilename = os.path.splitext(os.path.basename(filepath))[0] + '_unGUI.inp'
    newfilepath = os.path.join(os.path.dirname(filepath), newfilename)
    allheaders = complete_inp_headers(filepath)

    with open(filepath) as oldf:
        with open(newfilepath, 'w') as new:

            comment_concat = [] #to hold list of comments (handles multiline comments)
            current_section = allheaders['order'][0]
            for line in oldf:

                #determine what section we are in by noting when we pass double brackets
                if '[' and ']' in line:
                    current_section = line.strip()


                #if line.count(';') == 1 and line.strip()[0]==';':
                if len(line.strip()) > 1:
                    if line.strip()[0]==';' and ''.join(line.strip()[:2]) != ';;':
                        #print line.strip()[:2]
                        #this is a comment bc first char is ; and there
                        #seconf char is not (which would resember the header section)
                        words = line.split()
                        hdrs = allheaders['headers'][current_section].split()#headerrow.split()
                        perc_match_to_header = float(len([x for x in words if x in hdrs])) / float(len(hdrs))
                        if perc_match_to_header <= 0.75:
                            comment_concat.append(line.strip())
                    else:
                        #print comment_concat
                        #this row has data, tack any comment to the line end
                        comment_string = ''
                        if len(comment_concat) > 0:
                            comment_string = r' '.join(comment_concat)
                        newlinestring = line.strip() + comment_string + '\n'
                        new.write(newlinestring)
                        comment_concat = []
                else:
                    #write the short line
                    new.write(line)

    #rename files and remove old if we should overwrite
    if overwrite:
        os.remove(filepath)
        os.rename(newfilepath, filepath)
예제 #9
0
def create_dataframeBI(bi_path, section='[CONDUITS]'):
    """
    given a path to a biuld instructions file, create a dataframe of data in a
    given section
    """
    headerdefs = funcs.complete_inp_headers(bi_path)
    headerlist = headerdefs['headers'][section].split() + [';', 'Comment', 'Origin']
    tempfilepath = txt.extract_section_from_inp(bi_path, section,
                                                headerdefs=headerdefs,
                                                skipheaders=True)
    df = pd.read_table(tempfilepath, header=None, delim_whitespace=True,
                       skiprows=[0], index_col=0, names=headerlist, comment=None)

    os.remove(tempfilepath)  # clean up

    return df
예제 #10
0
파일: inp.py 프로젝트: aerispaha/swmmio
    def __init__(self, build_instr_file=None):

        #create a change object for each section that is different from baseline
        self.instructions = {}
        self.metadata = {}
        if build_instr_file:
            #read the instructions and create a dictionary of Change objects
            allheaders = funcs.complete_inp_headers(build_instr_file)
            instructions = {}
            for section in allheaders['order']:
                change = INPDiff(build_instr_file=build_instr_file, section=section)
                instructions.update({section:change})

            self.instructions = instructions

            #read the meta data
            self.metadata = vc_utils.read_meta_data(build_instr_file)
예제 #11
0
파일: inp.py 프로젝트: aerispaha/swmmio
def create_inp_build_instructions(inpA, inpB, path, filename, comments=''):

    """
    pass in two inp file paths and produce a spreadsheet showing the differences
    found in each of the INP sections. These differences should then be used
    whenever we need to rebuild this model from the baseline reference model.


    Note: this should be split into a func that creates a overall model "diff"
    that can then be written as a BI file or used programmatically
    """

    allsections_a = funcs.complete_inp_headers(inpA)
    modela = swmmio.Model(inpA)
    modelb = swmmio.Model(inpB)

    #create build insructions folder
    if not os.path.exists(path):
        os.makedirs(path)
    filepath = os.path.join(path, filename) + '.txt'
    # xlpath = os.path.join(path, filename) + '.xlsx'
    # excelwriter = pd.ExcelWriter(xlpath)
    # vc_utils.create_change_info_sheet(excelwriter, modela, modelb)

    problem_sections = ['[TITLE]', '[CURVES]', '[TIMESERIES]', '[RDII]', '[HYDROGRAPHS]']
    with open (filepath, 'w') as newf:

        #write meta data
        metadata = {
            #'Baseline Model':modela.inp.path,
            #'ID':filename,
            'Parent Models':{
                            'Baseline':{inpA:vc_utils.modification_date(inpA)},
                            'Alternatives':{inpB:vc_utils.modification_date(inpB)}
                            },
            'Log':{filename:comments}
            }
        #print metadata
        vc_utils.write_meta_data(newf, metadata)
        for section in allsections_a['order']:
            if section not in problem_sections:
                #calculate the changes in the current section
                changes = INPDiff(modela, modelb, section)
                data = pd.concat([changes.removed, changes.added, changes.altered])
                #vc_utils.write_excel_inp_section(excelwriter, allsections_a, section, data)
                vc_utils.write_inp_section(newf, allsections_a, section, data, pad_top=False, na_fill='NaN') #na fill fixes SNOWPACK blanks spaces issue
예제 #12
0
def create_dataframeINP(inp_path, section='[CONDUITS]', ignore_comments=True,
                        comment_str=';', comment_cols=True):
    """
    given a path to an INP file, create a dataframe of data in the given
    section.
    """

    # find all the headers and their defs (section title with cleaned one-liner column headers)
    headerdefs = funcs.complete_inp_headers(inp_path)
    # create temp file with section isolated from inp file
    tempfilepath = txt.extract_section_from_inp(inp_path, section,
                                                headerdefs=headerdefs,
                                                ignore_comments=ignore_comments)
    if ignore_comments:
        comment_str = None
    if not tempfilepath:
        # if this head (section) was not found in the textfile, return a
        # blank dataframe with the appropriate schema
        print('header "{}" not found in "{}"'.format(section, inp_path))
        print('returning empty dataframe')
        headerlist = headerdefs['headers'].get(section, 'blob').split() + [';', 'Comment', 'Origin']
        blank_df = pd.DataFrame(data=None, columns=headerlist).set_index(headerlist[0])
        return blank_df

    if headerdefs['headers'][section] == 'blob':
        # return the whole row, without specifc col headers
        df = pd.read_table(tempfilepath, delim_whitespace=False, comment=comment_str)
    elif section == '[CURVES]' or section == '[TIMESERIES]':
        # return the whole row, without specifc col headers
        df = pd.read_table(tempfilepath, delim_whitespace=False)  # , index_col=0)#, skiprows=[0])
    else:
        # this section header is recognized and will be organized into known columns
        headerlist = headerdefs['headers'][section].split()
        if comment_cols:
            headerlist = headerlist + [';', 'Comment', 'Origin']
        df = pd.read_table(tempfilepath, header=None, delim_whitespace=True, skiprows=[0],
                           index_col=0, names=headerlist, comment=comment_str)

        if comment_cols:
            # add new blank comment column after a semicolon column
            df[';'] = ';'

    os.remove(tempfilepath)

    return df.rename(index=str)
예제 #13
0
파일: inp.py 프로젝트: joshnr13/swmmio
    def __init__(self, build_instr_file=None):

        #create a change object for each section that is different from baseline
        self.instructions = {}
        self.metadata = {}
        if build_instr_file:
            #read the instructions and create a dictionary of Change objects
            allheaders = funcs.complete_inp_headers(build_instr_file)
            instructions = {}
            for section in allheaders['order']:
                change = Change(build_instr_file=build_instr_file,
                                section=section)
                instructions.update({section: change})

            self.instructions = instructions

            #read the meta data
            self.metadata = vc_utils.read_meta_data(build_instr_file)
예제 #14
0
def test_complete_inp_headers():

    headers = [
        '[TITLE]',
        '[OPTIONS]',
        '[EVAPORATION]',
        '[JUNCTIONS]',
        '[OUTFALLS]',
        '[CONDUITS]',
        '[XSECTIONS]',
        '[DWF]',
        '[REPORT]',
        '[TAGS]',
        '[MAP]',
        '[COORDINATES]',
        '[VERTICES]',
    ]

    h1 = funcs.complete_inp_headers(MODEL_XSECTION_BASELINE)

    assert (all(h in h1['headers'] for h in headers))
    assert (h1['order'] == headers)
예제 #15
0
def search_for_duplicates(inp_path, verbose = False):
    """
    scan an inp file and determine if any element IDs are duplicated in
    any section. Method: count the uniques and compare to total length
    """
    headers = funcs.complete_inp_headers(inp_path)['headers']
    dups_found = False
    for header, cols, in headers.items():
        if cols != 'blob':

            df = dataframes.create_dataframeINP(inp_path, section=header)
            elements = df.index
            n_unique = len(elements.unique()) #number of unique elements
            n_total = len(elements) #total number of elements
            if verbose:
                print('{} -> (uniques, total) -> ({}, {})'.format(header, n_unique , n_total))

            if n_unique != n_total:
                dups = ', '.join(df[df.index.duplicated()].index.unique().tolist())
                print('duplicate found in {}\nsection: {}\n{}'.format(inp_path, header, dups))
                dups_found = True

    return dups_found
예제 #16
0
파일: inp.py 프로젝트: joshnr13/swmmio
    def build(self, baseline_dir, target_path):
        """
        build a complete INP file with the build instructions committed to a
        baseline model.
        """
        basemodel = swmmio.Model(baseline_dir)
        allheaders = funcs.complete_inp_headers(basemodel.inp.filePath)
        #new_inp = os.path.join(target_dir, 'model.inp')
        with open(target_path, 'w') as f:
            for section in allheaders['order']:

                #check if the section is not in problem_sections and there are changes
                #in self.instructions and commit changes to it from baseline accordingly
                if (section not in problem_sections
                        and allheaders['headers'][section] != 'blob'
                        and section in self.instructions):

                    #df of baseline model section
                    basedf = create_dataframeINP(basemodel.inp, section)

                    #grab the changes to
                    changes = self.instructions[section]

                    #remove elements that have alterations and or tagged for removal
                    remove_ids = changes.removed.index | changes.altered.index
                    new_section = basedf.drop(remove_ids)

                    #add elements
                    new_section = pd.concat(
                        [new_section, changes.altered, changes.added])
                else:
                    #section is not well understood or is problematic, just blindly copy
                    new_section = create_dataframeINP(basemodel.inp,
                                                      section=section)

                #write the section
                vc_utils.write_inp_section(f, allheaders, section, new_section)
예제 #17
0
파일: text.py 프로젝트: aerispaha/swmmio
def extract_section_from_inp(filepath, sectionheader, cleanheaders=True,
                            startfile=False, headerdefs=None, ignore_comments=False,
                            return_string=False, skiprows=0, skipheaders=False):
    """
    INPUT path to text file (inp, rpt, etc) and a text string
    matchig the section header of the to be extracted

    creates a new text file in the same directory as the filepath
    and returns the path to the new file.

    optionally inserts row at begining of file with one-line headers that are
    defined in swmmio.defs.sectionheaders (useful for creating dataframes)
    """

    #headers = she.complete_inp_headers(inp)['headers']
    if not headerdefs:
        allheaders = complete_inp_headers(filepath)['headers']
    else:
        allheaders = headerdefs['headers']

    with open(filepath) as f:
        startfound = False
        endfound = False
        #outFilePath = inp.dir + "\\" + inp.name + "_" + section + ".txt"
        wd = os.path.dirname(filepath)
        newfname = sectionheader + '_' + random_alphanumeric(6)
        outfilepath = os.path.join(wd, newfname + txt)
        out_string = '' #populate if we only want a string returned
        line_count = 0
        with open(outfilepath, 'w') as newf:

            for line in f:

                if startfound and line.strip() in allheaders:
                    endfound = True
                    #print 'end found: {}'.format(line.strip())
                    break
                elif not startfound and sectionheader in line:
                    startfound = True
                    #replace line with usable headers
                    if cleanheaders:
                        if allheaders[sectionheader] != 'blob':
                            line = allheaders[sectionheader] + '\n'
                        else:
                            line = sectionheader + '\n'

                if startfound:
                    if ignore_comments:
                        #ignore anything after a comment
                        #THIS IS HACK GARBAGE
                        if ';' in line:
                            s = line.split(';')[0] + '\n'
                            out_string += s #build the overall out string (optional use)
                            newf.write(s)
                        else:
                            newf.write(line)
                            out_string += line
                    elif skipheaders:
                        #check if we're at a inp header row with ';;' or the section
                        #header e.g. [XSECTIONS]. If so, skip the row bc skipheader = True
                        if line.strip()[:2] != ";;" and line.strip() != sectionheader:
                            newf.write(line)
                            out_string += line
                    elif line_count >= skiprows:
                        newf.write(line)
                        out_string += line

                    line_count += 1

    if not startfound:
        #input section header was not found in the file
        os.remove(outfilepath)
        return None
    if return_string:
        #return a string rep of the extracted section
        os.remove(outfilepath) #not needed so delete (maybe wasteful to make in 1st place)
        return out_string

    if startfile:
        os.startfile(outfilepath)

    return outfilepath
예제 #18
0
파일: inp.py 프로젝트: joshnr13/swmmio
def generate_inp_from_diffs(basemodel, inpdiffs, target_dir):
    """
    create a new inp with respect to a baseline inp and changes instructed
    with a list of inp diff files (build instructions). This saves having to
    recalculate the differences of each model from the baseline whenever we want
    to combine versions.
    """

    #step 1 --> combine the diff/build instructions
    allheaders = funcs.complete_inp_headers(basemodel.inp.filePath)
    combi_build_instr_file = os.path.join(target_dir, 'build_instructions.txt')
    newinp = os.path.join(target_dir, 'new.inp')
    with open(combi_build_instr_file, 'w') as f:
        for header in allheaders['order']:
            s = ''
            section_header_written = False
            for inp in inpdiffs:
                sect_s = None
                if not section_header_written:
                    sect_s = text.extract_section_from_inp(inp,
                                                           header,
                                                           cleanheaders=False,
                                                           return_string=True,
                                                           skipheaders=False)
                    section_header_written = True

                else:
                    sect_s = text.extract_section_from_inp(inp,
                                                           header,
                                                           cleanheaders=False,
                                                           return_string=True,
                                                           skipheaders=True)

                if sect_s:
                    #remove the extra space between data in the same table
                    #coming from diffrent models.
                    if sect_s[-2:] == '\n\n':  #NOTE Check this section...
                        s += sect_s[:-1]
                    else:
                        s += sect_s

            f.write(s + '\n')

    #step 2 --> clean up the new combined diff instructions
    df_dict = clean_inp_diff_formatting(
        combi_build_instr_file)  #makes more human readable

    #step 3 --> create a new inp based on the baseline, with the inp_diff
    #instructions applied
    with open(newinp, 'w') as f:
        for section in allheaders['order']:
            print section
            if section not in problem_sections and allheaders['headers'][
                    section] != 'blob':
                #check if a changes from baseline spreadheet exists, and use this
                #information if available to create the changes array
                df = create_dataframeINP(basemodel.inp, section)
                df['Origin'] = ''  #add the origin column if not there
                if section in df_dict:
                    df_change = df_dict[section]
                    ids_to_drop = df_change.loc[df_change['Comment'].isin(
                        ['Removed', 'Altered'])].index
                    df = df.drop(ids_to_drop)
                    df = df.append(df_change.loc[df_change['Comment'].isin(
                        ['Added', 'Altered'])])
                new_section = df
            else:
                #blindly copy this section from the base model
                new_section = create_dataframeINP(basemodel.inp,
                                                  section=section)

            #write the section into the inp file and the excel file
            vc_utils.write_inp_section(f, allheaders, section, new_section)
예제 #19
0
파일: inp.py 프로젝트: aerispaha/swmmio
def generate_inp_from_diffs(basemodel, inpdiffs, target_dir):
    """
    create a new inp with respect to a baseline inp and changes instructed
    with a list of inp diff files (build instructions). This saves having to
    recalculate the differences of each model from the baseline whenever we want
    to combine versions.

    NOTE THIS ISN'T USED ANYWHERE. DELETE ????
    """

    #step 1 --> combine the diff/build instructions
    allheaders = funcs.complete_inp_headers(basemodel.inp.path)
    combi_build_instr_file = os.path.join(target_dir, 'build_instructions.txt')
    newinp = os.path.join(target_dir, 'new.inp')
    with open (combi_build_instr_file, 'w') as f:
        for header in allheaders['order']:
            s = ''
            section_header_written = False
            for inp in inpdiffs:
                sect_s = None
                if not section_header_written:
                    sect_s = text.extract_section_from_inp(inp, header,
                                                           cleanheaders=False,
                                                           return_string=True,
                                                           skipheaders=False)
                    section_header_written = True

                else:
                    sect_s = text.extract_section_from_inp(inp, header,
                                                           cleanheaders=False,
                                                           return_string=True,
                                                           skipheaders=True)

                if sect_s:
                    #remove the extra space between data in the same table
                    #coming from diffrent models.
                    if sect_s[-2:] == '\n\n':   #NOTE Check this section...
                        s += sect_s[:-1]
                    else:
                        s += sect_s

            f.write(s + '\n')

    #step 2 --> clean up the new combined diff instructions
    # df_dict = clean_inp_diff_formatting(combi_build_instr_file) #makes more human readable

    #step 3 --> create a new inp based on the baseline, with the inp_diff
    #instructions applied
    with open (newinp, 'w') as f:
        for section in allheaders['order']:
            print(section)
            if section not in problem_sections and allheaders['headers'][section] != 'blob':
                #check if a changes from baseline spreadheet exists, and use this
                #information if available to create the changes array
                df = create_dataframeINP(basemodel.inp.path, section)
                df['Origin'] = '' #add the origin column if not there
                if section in df_dict:
                    df_change = df_dict[section]
                    ids_to_drop = df_change.loc[df_change['Comment'].isin(['Removed', 'Altered'])].index
                    df = df.drop(ids_to_drop)
                    df = df.append(df_change.loc[df_change['Comment'].isin(['Added', 'Altered'])])
                new_section = df
            else:
                #blindly copy this section from the base model
                new_section = create_dataframeINP(basemodel.inp.path, section=section)

            #write the section into the inp file and the excel file
            vc_utils.write_inp_section(f, allheaders, section, new_section)
예제 #20
0
def replace_inp_section(inp_path,
                        modified_section_header,
                        new_data,
                        overwrite=True):
    """
    modify an existing model by passing in new data (Pandas Dataframe)
    and the section header that should be modified. This funciton will overwrite
    all data in the old section with the passed data
    """

    tmpfilename = os.path.splitext(os.path.basename(inp_path))[0] + '_mod.inp'
    wd = os.path.dirname(inp_path)
    tmpfilepath = os.path.join(os.path.dirname(inp_path), tmpfilename)
    allheaders = complete_inp_headers(inp_path)
    basemodel = swmmio.Model(inp_path)

    with open(inp_path) as oldf:
        with open(tmpfilepath, 'w') as new:
            #create the companion excel file
            #create the MS Excel writer object
            # xlpath = os.path.join(wd, basemodel.inp.name + '_modified.xlsx')
            # excelwriter = pd.ExcelWriter(xlpath)
            # vc_utils.create_info_sheet(excelwriter, basemodel)

            #write each line as is from the original model until we find the
            #header of the section we wish to overwrite
            found_section = False
            found_next_section = False
            for line in oldf:
                if modified_section_header in line:
                    #write the replacement data in the new file now
                    vc_utils.write_inp_section(new,
                                               allheaders,
                                               modified_section_header,
                                               new_data,
                                               pad_top=False)

                    found_section = True

                if (found_section and not found_next_section
                        and line.strip() in allheaders['headers']
                        and modified_section_header != line.strip()):

                    found_next_section = True
                    new.write('\n\n')  #add some space before the next section

                if found_next_section or not found_section:
                    #write the lines from the original file
                    #if we haven't found the section to modify.
                    #if we have found the section and we've found the NEXT section
                    #continue writing original file's lines

                    new.write(line)

            if not found_section:
                #the header doesn't exist in the old model
                #so we should append it to the bottom of file
                vc_utils.write_inp_section(new, allheaders,
                                           modified_section_header, new_data)

    # excelwriter.save()
    #rename files and remove old if we should overwrite
    if overwrite:
        os.remove(inp_path)
        os.rename(tmpfilepath, inp_path)

    return swmmio.Model(inp_path)
예제 #21
0
파일: text.py 프로젝트: timebridge/swmmio
def extract_section_from_inp(filepath,
                             sectionheader,
                             cleanheaders=True,
                             startfile=False,
                             headerdefs=None,
                             ignore_comments=False,
                             return_string=False,
                             skiprows=0,
                             skipheaders=False):
    """
    INPUT path to text file (inp, rpt, etc) and a text string
    matchig the section header of the to be extracted

    creates a new text file in the same directory as the filepath
    and returns the path to the new file.

    optionally inserts row at begining of file with one-line headers that are
    defined in swmmio.defs.sectionheaders (useful for creating dataframes)
    """

    #headers = she.complete_inp_headers(inp)['headers']
    if not headerdefs:
        allheaders = complete_inp_headers(filepath)['headers']
    else:
        allheaders = headerdefs['headers']

    with open(filepath) as f:
        startfound = False
        endfound = False
        #outFilePath = inp.dir + "\\" + inp.name + "_" + section + ".txt"
        wd = os.path.dirname(filepath)
        newfname = sectionheader + '_' + random_alphanumeric(6)
        outfilepath = os.path.join(wd, newfname + txt)
        out_string = ''  #populate if we only want a string returned
        line_count = 0
        with open(outfilepath, 'w') as newf:

            for line in f:

                if startfound and line.strip() in allheaders:
                    endfound = True
                    #print 'end found: {}'.format(line.strip())
                    break
                elif not startfound and sectionheader in line:
                    startfound = True
                    #replace line with usable headers
                    if cleanheaders:
                        if allheaders[sectionheader] != 'blob':
                            line = allheaders[sectionheader] + '\n'
                        else:
                            line = sectionheader + '\n'

                if startfound:
                    if ignore_comments:
                        #ignore anything after a comment
                        #THIS IS HACK GARBAGE
                        if ';' in line:
                            s = line.split(';')[0] + '\n'
                            out_string += s  #build the overall out string (optional use)
                            newf.write(s)
                        else:
                            newf.write(line)
                            out_string += line
                    elif skipheaders:
                        #check if we're at a inp header row with ';;' or the section
                        #header e.g. [XSECTIONS]. If so, skip the row bc skipheader = True
                        if line.strip()[:2] != ";;" and line.strip(
                        ) != sectionheader:
                            newf.write(line)
                            out_string += line
                    elif line_count >= skiprows:
                        newf.write(line)
                        out_string += line

                    line_count += 1

    if not startfound:
        #input section header was not found in the file
        os.remove(outfilepath)
        return None
    if return_string:
        #return a string rep of the extracted section
        os.remove(
            outfilepath
        )  #not needed so delete (maybe wasteful to make in 1st place)
        return out_string

    if startfile:
        os.startfile(outfilepath)

    return outfilepath