3

Following on from How to use `layer.getFeatures()` in a standalone script?, I would like my script to do the following (includes illustration):

  1. Search for the first shapefile (Paris (O).shp) in Country_France > Original files and clip it onto Grid.shp.
  2. Search for the first shapefile (Paris (P).shp) in Country_France > Processed files and take the first value in the Rank field.
  3. Take Paris (O).shp and add a Rank field with the value from Paris (P).shp.
  4. Output results in Country_France > Processed files with new filename, Paris (P)x.shp.

  5. Search for second shapefile in Country_France > Original files (Toulon (O).shp) and repeat Step 1.

  6. When all shapefiles are found in Country_France, move on to Country_Germany and repeat Step 1.

File directory

Problem:

ALL output shapefiles are based on the last shapefile to be clipped from Step 1. In other words, Paris (P)x.shp) has the exact same geometry with Toulon (P)x.shp. The only difference is in the Attributes Table where the Rank value is correctly applied:

Paris (P)x.shp

Toulon (P)x.shp

I am expecting Paris (P)x to look like the image below (ie. Paris (O).shp clipped onto *Grid.shp, not Toulon (O).shp):

How Paris (P)x should look

I'm quite certain the problem lies with the loops, the problem is I am unsure how to create the loop(s) which resembles the Steps above. I obtained the results using the following script:

root_dir = home + "\Desktop\Test\\"
original_dir = "Original files"
processed_dir = "Processed files"
country_dir = "Country_*/"
grid_path = root_dir + "Grid.shp"

for f in glob.glob(root_dir + country_dir + original_dir + "\*.shp"):

    outputs_1=general.runalg("qgis:clip", grid_path, f, None)

for g in glob.glob(root_dir + country_dir + processed_dir + "\*(P).shp"):

    pieces = list(os.path.splitext(g))
    pieces[0] = pieces[0][:-3] + "(P)x"
    newFile = "".join(pieces)

    vLayer = QgsVectorLayer(g,"any name","ogr")
    idx = vLayer.fieldNameIndex('Rank')
    Rank_value = vLayer.uniqueValues(idx)[0]

    general.runalg("qgis:advancedpythonfieldcalculator", outputs_1['SAVENAME'], 'Rank', 1, 10, 0, False, "value=%f" % Rank_value, newFile)
6
  • 1
    I'm not sure it's fully clear of what behavior you are expecting the script to do. Your English version of your algorithm (the script does the following steps 1-5) doesn't match your python algorithm. Your script does step one for a single shapefile not shapefiles, then it does steps 2-4 before returning back to step 1 (assuming there are multiple shapefiles in the original files folder).
    – papadoo
    Apr 14, 2015 at 19:18
  • 1
    I also think it's not very clear what is the problem. Could you please try to clarify what do you get and what do you expect? Apr 15, 2015 at 2:24
  • @papadoo - Many thanks for your response buddy, I've edited the question in the hope that it's a little more clearer. But you are correct, I would like the script to match the steps described in English. Please let me know if it's still unclear.
    – Joseph
    Apr 16, 2015 at 11:20
  • 1
    @gcarrillo - Thank you, I have edited the question to include images of what I am getting and what I expect.
    – Joseph
    Apr 16, 2015 at 11:21
  • @Joseph Your second for loop and everything below it needs to be indented one more block.
    – papadoo
    Apr 16, 2015 at 15:12

1 Answer 1

4
+150

Assuming that you always want to match like files from Original and Processed folders (i.e. Paris(O).shp always matched with Paris(P).shp or New York City(O).shp always matched with New York City(P).shp), You need to add a conditional after your second for loop to filter out everything you are grabbing from the processed folder.

 for f in glob.glob(root_dir + country_dir + original_dir + "\*.shp"):

      outputs_1=general.runalg("qgis:clip", grid_path, f, None)

      for g in glob.glob(root_dir + country_dir + processed_dir + "\*(P).shp"):
           if os.path.basename(f).rstrip("(O).shp") == os.path.basename(g).rstrip("(P).shp"):

                pieces = list(os.path.splitext(g))
                pieces[0] = pieces[0][:-3] + "(P)x"
                newFile = "".join(pieces)

                vLayer = QgsVectorLayer(g,"any name","ogr")
                idx = vLayer.fieldNameIndex('Rank')
                Rank_value = vLayer.uniqueValues(idx)[0]

                general.runalg("qgis:advancedpythonfieldcalculator", outputs_1['SAVENAME'], 'Rank', 1, 10, 0, False, "value=%f" % Rank_value, newFile)
3
  • 1
    I think this solution makes sense. Just to add that you can avoid the name comparison by using a proper filter. For instance: for g in glob.glob(root_dir + country_dir + processed_dir + "\" + os.path.splitext(f)[0][:-3] +"(P).shp"):. Apr 17, 2015 at 2:02
  • Wonderful! Never knew about the rstrip() method, this works great. Thank you very much! Will award you the bounty but have to wait 5 hours =)
    – Joseph
    Apr 17, 2015 at 9:29
  • @gcarrillo - Ahh, that's a very nice tip. Thank you, I will test this out =)
    – Joseph
    Apr 17, 2015 at 9:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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