Skip to content

Workers

The Worker class is the base object to work with files and vector layers. It contains two subclasses - File for working with the filesystem and Vector for working with vector data.

Worker

Base class for transforming data.

Source code in python\engine\workers.py
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
class Worker:
    '''
    Base class for transforming data.
    '''

    ## Method that draws the progress bar
    def printProgressBar(value,label):
        n_bar = 40 #size of progress bar
        max = 100
        j= value/max
        sys.stdout.write('\r')
        bar = '█' * int(n_bar * j)
        bar = bar + '-' * int(n_bar * (1-j))
        sys.stdout.write(f"{label.ljust(10)} | [{bar:{n_bar}s}] {int(100 * j)}% ")
        sys.stdout.flush()
        sys.stdout.write('')        

    ## The progress bar function
    def progress_changed(progress):
        Worker.printProgressBar(progress, '%')

    ## The shared element for progress across all workers
    progress = QgsProcessingFeedback()
    progress.progressChanged.connect(progress_changed)

    ## The shared element for logging across all workers
    logger = get_logger() 

    class Generic:
        '''
        A Worker subclass that contains method for generic execution of QGIS processing functions.
        '''
        def ProcessingRunner(algName: str, parameters: dict):
            """
            A generic method to run QGIS processing algorithms. Supply the algorithm name and the parameters as a dictionary.
            The method will run the algorithm and return the outputs.

            Args:
                algName (str): The name of the QGIS processing algorithm to run.
                parameters (dict): the parameters for the algorithm as a dictionary.

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info(f'Running {algName}')
            try:

                result = processing.run(algName, parameters, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameters)}')
                logger.info("ProcessingRunner  finished")
                return result
            except Exception as error:
                logger.error("An error occured in ProcessingRunner")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

    class Vector:
        '''
        A Worker subclass that contains methods to transform vector data or their attributes.
        '''

        def attributeindex(layer: QgsVectorLayer, field: str):
            """
            Creates an index to speed up queries made against a field in a table.
            Support for index creation is dependent on the layer's data provider and the field type.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                field (string): The field to base the index on

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Crating attribute index on " + layer + " on filed " + field)
            try:
                parameter = {
                    'INPUT': field,
                    'FIELD': field,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:createattributeindex', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("createattributeindex  finished")
                return result
            except Exception as error:
                logger.error("An error occured in createattributeindex")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def addxyfieldstolayer(layer: QgsVectorLayer, crs: str):
            """
            Adds X and Y (or latitude/longitude) fields to a point layer. The X/Y fields can be calculated in a different CRS to the layer (e.g. creating latitude/longitude fields for a layer in a projected CRS).

            Args:
                layer (QgsVectorLayer): The input layer.
                crs (string): Coordinate reference system to use for the generated x and y fields.

            Returns:
                layer (QgsVectorLayer): Specify the output layer.
            """

            logger.info(f"Adding X/Y fields to {layer}" )
            try:
                parameter = {
                    'INPUT': layer,
                    'CRS': crs,
                    'OUTPUT': 'memory:output_from_addxyfieldstolayer'
                }
                result = processing.run('native:addxyfieldstolayer', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("addxyfieldstolayer  finished")
                return result
            except Exception as error:
                logger.error("An error occured in addxyfieldstolayer")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def convexhull(layer: QgsVectorLayer):
            """
            Calculates the convex hull for each feature in an input layer.

            Args:
                layer (QgsVectorLayer): Input vector layer

            Returns:
                layer (QgsVectorLayer): Specify the output vector layer.
            """

            logger.info(f" Calculating convexhull for layer {layer}")
            try:
                parameter = {
                    'INPUT': layer,
                    'OUTPUT': 'memory:output_from_convexhull'
                }
                result = processing.run('native:convexhull', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("convexhull  finished")
                return result
            except Exception as error:
                logger.error("An error occured in convexhull")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def concavehull(inputlayer:QgsVectorLayer, alpha: float, holes: bool, multigeom: bool ):
            """
            Computes the concave hull of the features from an input point layer.

            Args:
                inputlayer (QgsVectorLayer): Input point vector layer
                alpha (float): Number from 0 (maximum concave hull) to 1 (convex hull).
                holes (boolean): Choose whether to allow holes in the final concave hull
                multigeom (boolean): Check if you want to have singlepart geometries instead of multipart ones.

            Returns:
                layer (QgsVectorLayer): Specify the output vector layer
            """

            logger.info('calcualting concavehull')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'ALPHA' : alpha,
                    'HOLES' : holes,
                    'NO_MULTIGEOMETRY' : multigeom,
                    'OUTPUT': 'memory:output_from_concavehull'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:concavehull', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('concavehull finished')
                return result
            except Exception as error:
                logger.error("An error occured in concavehull")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()            

        def extractvertices(inputlayer:QgsVectorLayer):
            """
            Takes a vector layer and generates a point layer with points representing the vertices in the input geometries.
            The attributes associated to each point are the same ones associated to the feature that the vertex belongs to.
            Additional fields are added to the vertices indicating the vertex index (beginning at 0), the feature’s part and its index within the part
            (as well as its ring for polygons), distance along original geometry and bisector angle of vertex for original geometry.

            Args:
                inputlayer (QgsVectorLayer): Input vector layer

            Returns:
                layer (QgsVectorLayer): Specify the output vector layer
            """

            logger.info('Extracting vertices')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'OUTPUT': 'memory:output_from_extractvertices'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:extractvertices', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('extractvertices finished')
                return result
            except Exception as error:
                logger.error("An error occured in extractvertices")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()    

        def multiringconstantbuffer(inputlayer:QgsVectorLayer, rings: int, distance : str):
            """
            Computes multi-ring (donut) buffer for the features of the input layer, using a fixed or dynamic distance and number of rings.

            Args:
                inputlayer (QgsVectorLayer): Input vector layer
                rings (integer): The number of rings. It can be a unique value (same number of rings for all the features) or it can be taken from features data (the number of rings depends on feature values).
                distance (string): Distance between the rings. It can be a unique value (same distance for all the features) or it can be taken from features data (a field in the input data layer).

            Returns:
                layer (QgsVectorLayer): Specify the output polygon vector layer
            """

            logger.info('Creating multiringconstantbuffer')
            try:
                dist = float(distance)
                logger.info('Using distance value')
            except:
                dist = QgsProperty.fromExpression(f'"{distance}"')
                logger.info('Using distance from field')

            try:
                parameters = {
                    'INPUT': inputlayer,
                    'RINGS': rings,
                    'DISTANCE': distance,
                    'OUTPUT': 'memory:output_from_multiringconstantbuffer'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:multiringconstantbuffer', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('multiringconstantbuffer finished')
                return result
            except Exception as error:
                logger.error("An error occured in multiringconstantbuffer")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed() 

        def poleofinaccessibility(inputlayer:QgsVectorLayer, tolerance: int):
            """
            Calculates the pole of inaccessibility for a polygon layer, which is the most distant internal point from the boundary of the surface. 
            This algorithm uses the ‘polylabel’ algorithm (Vladimir Agafonkin, 2016), which is an iterative approach guaranteed to find the true pole of inaccessibility within
            a specified tolerance. A more precise tolerance (lower value) requires more iterations and will take longer to calculate. 
            The distance from the calculated pole to the polygon boundary will be stored as a new attribute in the output layer.

            Args:
                inputlayer (QgsVectorLayer): Input vector layer
                tolerance (integer): Set the tolerance for the calculation. Default 1

            Returns:
                layer (QgsVectorLayer): Specify the output polygon vector layer.
            """

            logger.info('calcualting poleofinaccessibility')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'TOLERANCE' : tolerance,
                    'OUTPUT': 'memory:output_from_poleofinaccessibility'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:poleofinaccessibility', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('poleofinaccessibility finished')
                return result
            except Exception as error:
                logger.error("An error occured in poleofinaccessibility")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()


        def symmetricaldifference(inputlayer: QgsVectorLayer, overlay_layer: QgsVectorLayer):
            """
            Creates a layer containing features from both the input and overlay layers but with the overlapping areas between the two layers removed.
            The attribute table of the symmetrical difference layer contains attributes and fields from both the input and overlay layers.

            Args:
                inputlayer (QgsVectorLayer): First layer to extract (parts of) features from.
                overlay_layer (QgsVectorLayer): Second layer to extract (parts of) features from. Ideally the geometry type should be the same as input layer.

            Returns:
                layer (QgsVectorLayer): Specify the layer to contain (the parts of) the features from the input and overlay layers that do not overlap features from the other layer
            """

            logger.info('calcualting symetrical difference')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'OVERLAY' : overlay_layer,
                    'OUTPUT': 'memory:output_from_symmetricaldifference'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:symmetricaldifference', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Symmetricaldifference finished')
                return result
            except Exception as error:
                logger.error("An error occured in symmetricaldifference")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def lineintersections(inputlayer: QgsVectorLayer, split_layer: QgsVectorLayer, input_fields: list, intersect_fields: list):
            """
            Splits the lines or polygons in one layer using the lines or polygon rings in another layer to define the breaking points. Intersection between geometries in both layers are considered as split points.
            Output will contain multi geometries for split features.

            Args:
                inputlayer (QgsVectorLayer): Input line layer.
                split_layer (QgsVectorLayer): Layer to use to find line intersections.
                input_fields (list of strings): Field(s) of the input layer to keep in the output. If no fields are chosen all fields are taken.
                intersect_fields (list of strings): Field(s) of the intersect layer to keep in the output. If no fields are chosen all fields are taken. Duplicate field names will be appended a count suffix to avoid collision

            Returns:
                layer (QgsVectorLayer): Specify the layer to contain the intersection points of the lines from the input and overlay layers.
            """

            logger.info('Performing line intersections')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'INTERSECT': split_layer,
                    'INPUT_FIELDS' : input_fields, 
                    'INTERSECT_FIELDS' : intersect_fields,
                    'OUTPUT': 'memory:output_from_lineintersections'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:lineintersections', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Lineintersections finished')
                return result
            except Exception as error:
                logger.error("An error occured in Lineintersections")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def kmeansclustering(inputlayer: QgsVectorLayer, clusters: int):
            """
            Calculates the 2D distance based k-means cluster number for each input feature.
            K-means clustering aims to partition the features into k clusters in which each feature belongs to the cluster with the nearest mean. The mean point is represented by the barycenter of the clustered features.
            If input geometries are lines or polygons, the clustering is based on the centroid of the feature.

            Args:
                inputlayer (QgsVectorLayer): Layer to analyze
                clusters (integer): Number of clusters to create with the features

            Returns:
                layer (QgsVectorLayer): Specify the output vector layer for generated the clusters.
            """

            logger.info('Calculating clusters')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'CLUSTERS' : clusters,
                    'OUTPUT': 'memory:output_from_kmeansclustering'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:kmeansclustering', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Kmeansclustering finished')
                return result
            except Exception as error:
                logger.error("An error occured in Kmeansclustering")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def dbscanclustering(inputlayer: QgsVectorLayer, min_clusters: int, max_dist: int ):
            """
            Clusters point features based on a 2D implementation of Density-based spatial clustering of applications with noise (DBSCAN) algorithm.
            The algorithm requires two parameters, a minimum cluster size, and the maximum distance allowed between clustered points.

            Args:
                inputlayer (QgsVectorLayer): Layer to analyze
                min_clusters (integer): Minimum number of features to generate a cluster
                max_dist (integer): Distance beyond which two features can not belong to the same cluster (eps)

            Returns:
                layer (QgsVectorLayer): Specify the vector layer for the result of the clustering.
            """

            logger.info('Performing DBScan clustering')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'MIN_SIZE' : min_clusters,
                    'EPS': max_dist,
                    'OUTPUT': 'memory:output_from_dbscanclustering'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:dbscanclustering', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Dbscanclustering finished')
                return result
            except Exception as error:
                logger.error("An error occured in Dbscanclustering")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def countpointsinpolygon(polygons: QgsVectorLayer, points: QgsVectorLayer, weight : str, fieldname: str):
            """
            Takes a point and a polygon layer and counts the number of points from the point layer in each of the polygons of the polygon layer.
            A new polygon layer is generated, with the exact same content as the input polygon layer, but containing an additional field with the points count corresponding to each polygon.

            Args:
                polygons (QgsVectorLayer): Polygon layer whose features are associated with the count of points they contain
                points (QgsVectorLayer): Point layer with features to count
                weight (string): A field from the point layer. The count generated will be the sum of the weight field of the points contained by the polygon. If the weight field is not numeric, the count will be 0.
                fieldname (string): The name of the field to store the count of points

            Returns:
                layer (QgsVectorLayer): Specification of the output layer.
            """

            logger.info('Conducting point in polygon')
            try:
                if isinstance(weight, int):
                    value = weight
                else:
                    value = 0

                parameters = {
                    'POLYGONS': polygons,
                    'POINTS': points,
                    'WEIGHT': value,
                    'FIELD' : fieldname,
                    'OUTPUT': 'memory:output_from_countpointsinpolygon'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:Countpointsinpolygon', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Promote to multipart finished')
                return result
            except Exception as error:
                logger.error("An error occured in Countpointsinpolygon")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()  

        def promoteToMultipart(layer: QgsVectorLayer):
            """
            Generates a vectorlayer in which all geometries are multipart.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer that is used as input.

            Returns:
                layer (QgsVectorLayer): The QgsVectorLayer containing multi geometries.
            """

            logger.info('Collecting geometries')
            try:
                parameters = {
                    'INPUT': layer,
                    'OUTPUT': 'memory:multipart'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:promotetomulti', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Promote to multipart finished')
                return result
            except Exception as error:
                logger.error("An error occured in promoteToMultipart")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def extractByExpression(layer: QgsVectorLayer, expression: str):
            """
            Creates a vector layer from an input layer, containing only matching features.
            The criteria for adding features to the resulting layer is based on a QGIS expression.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
                expression (string): Expression to filter the vector layer

            Returns:
                layer (QgsVectorLayer): The QgsVectorLayer output layer.
            """

            logger.info("Extracting by expression")
            try:
                parameter = {
                    'INPUT': layer,
                    'EXPRESSION': expression,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:extractbyexpression', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Extractbyexpression  finished")
                return result
            except Exception as error:
                logger.error("An error occured in extractByExpression")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def renameTableField (layer: QgsVectorLayer, field: str, newname: str):
            """
            Renames an existing field from a vector layer.  
            The original layer is not modified. A new layer is generated where the attribute table contains the renamed field.
            QGIS processing algorithem: native:renametablefield

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                field (string): The field that is to be renamed
                newname (string): New name for the field

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Renaming field")
            try:
                parameter = {
                    'INPUT': layer,
                    'FIELD': field,
                    'NEW_NAME': newname,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:renametablefield', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("renameTableField  finished")
                return result
            except Exception as error:
                logger.error("An error occured in renameTableField")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def timeStamper(layer: QgsVectorLayer, ts_fieldname: str):
            """
            Create an attribute woth current timestamp on features.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                ts_fieldname (string): The name of the new timestamp field

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info(f'Creating timestamp {ts_fieldname} using fieldCalculator')
            newLayer = Worker.Vector.fieldCalculator(layer, ts_fieldname, 5, 0, 0, ' now() ')
            return newLayer

        def fieldCalculator (layer: QgsVectorLayer, fieldname: str, fieldtype: int, fieldlength: int, fieldprecision: int, formula: str):
            """
            Scripting the field calcualtor
            You can use all the supported expressions and functions.
            The original layer is not modified. A new layer is generated where the attribute table contains the calucalted field
            QGIS processing algorithem: native:fieldcalculator

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                fieldname (string): The name of the new calcualted field
                fieldtype (integer): Type of the field,  Default: 0  (0 — Float, 1 — Integer, 2 — String, 3 — Date)
                fieldlength (integer): Lenght of the field, Default: 10.
                fieldprecision (integer): Precision of the field, Default: 3.
                formula (string): The expression that populates the values of the field.

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Calculating field")
            try:
                parameter = {
                    'INPUT': layer,
                    'FIELD_NAME': fieldname,
                    'FIELD_TYPE': fieldtype,
                    'FIELD_LENGTH': fieldlength,
                    'FIELD_PRECISION': fieldprecision,
                    'FORMULA': formula,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:fieldcalculator', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("fieldCalculator  finished")
                return result
            except Exception as error:
                logger.error("An error occured in fieldCalculator")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def deleteColumns (layer: QgsVectorLayer, columns: list):
            """
            Takes a vector layer and generates a new one that has the same features but without the selected columns.

            Args:
                layer (QgsVectorLayer): Input vector layer to drop field(s) from
                columns (list of strings): The field(s) to drop

            Returns:
                layer (QgsVectorLayer): The QgsVectorLayer output layer.
            """

            logger.info("deleting fields")

            try:
                parameter = {
                    'INPUT': layer,
                    'COLUMN':columns,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:deletecolumn', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("deleteColumns  finished")
                return result
            except Exception as error:
                logger.error("An error occured in deleteColumns")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def addAutoIncrementalField(layer: QgsVectorLayer, fieldname: str, start: int):
            """
            Adds a new integer field to a vector layer, with a sequential value for each feature.
            This field can be used as a unique ID for features in the layer. The new attribute is not added to the input layer but a new layer is generated instead.
            The initial starting value for the incremental series can be specified. Optionally, the incremental series can be based on grouping 
            fields and a sort order for features can also be specified.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
                fieldname (string): Name of the field with autoincremental values.
                start (integer): Choose the initial number of the incremental count, Default: 0.

            Returns
                layer (QgsVectorLayer): The QgsVectorLayer output layer.
            """

            logger.info("Adding incremental field")
            try:
                parameter = {
                    'INPUT': layer,
                    'FIELD_NAME': fieldname,
                    'START':start,
                    'MODULUS':0,
                    'GROUP_FIELDS':[],
                    'SORT_EXPRESSION':'',
                    'SORT_ASCENDING':True,
                    'SORT_NULLS_FIRST':False,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:addautoincrementalfield', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("addAutoIncrementalField  finished")
                return result
            except Exception as error:
                logger.error("An error occured in addAutoIncrementalField")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def spatialindex(layer: QgsVectorLayer):
            """
            Creates an index to speed up access to the features in a layer based on their spatial location.
            Support for spatial index creation is dependent on the layer's data provider.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Crating spatial index on " + layer)
            try:
                parameter = {
                    'INPUT': layer,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:createspatialindex', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("createspatialindex  finished")
                return result
            except Exception as error:
                logger.error("An error occured in createspatialindex")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def clip(layer: QgsVectorLayer, overlay: str):
            """
            Clips a vector layer using the features of an additional polygon layer.
            Only the parts of the features in the input layer that fall within the polygons of 
            the overlay layer will be added to the resulting layer.

            Args:
                layer (QgsVectorLayer): Layer containing the features to be clipped
                overlay (QgsVectorLayer): Layer containing the clipping features

            Returns:
                layer (QgsVectorLayer): Layer to contain the features from the input layer that are inside the overlay (clipping) layer
            """

            logger.info("Clipping layers")
            try:
                parameter = {
                    'INPUT': layer,
                    'OVERLAY': overlay,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:clip', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Clip  finished")
                return result
            except Exception as error:
                logger.error("An error occured in Clip")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def joinByLocation(layer: QgsVectorLayer, predicate: int, join: str, join_fields: list, method: int, discard_nomatching: bool, prefix: str):
            """
            Takes an input vector layer and creates a new vector layer that is an extended version of
            the input one, with additional attributes in its attribute table.
            The additional attributes and their values are taken from a second vector layer.
            A spatial criteria is applied to select the values from the second layer that are added to each 
            feature from the first layer.

            Args:
                layer (QgsVectorLayer): Input vector layer. The output layer will consist of the features of this layer with attributes from matching features in the second layer.
                predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
                join (QgsVectorLayer): The join layer. Features of this vector layer will add their attributes to the source layer attribute table if they satisfy the spatial relationship.
                join_fields (list of strings): Select the specific fields you want to add from the join layer. By default all the fields are added.
                method (integer): The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one) 2 — Take attributes of the feature with largest overlap only (one-to-one)
                discard_nomatching (boolean): Remove from the output the input layer’s features which could not be joined
                prefix (string): Add a prefix to joined fields in order to easily identify them and avoid field name collision

            Returns:
                layer (QgsVectorLayer): the output vector layer for the join.
            """

            logger.info("Clipping layers")
            try:
                parameter = {
                    'INPUT': layer,
                    'PREDICATE':predicate,
                    'JOIN':join,
                    'JOIN_FIELDS':join_fields,
                    'METHOD':method,
                    'DISCARD_NONMATCHING':discard_nomatching,
                    'PREFIX':prefix,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:joinattributesbylocation', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("joinByLocation finished")
                return result
            except Exception as error:
                logger.error("An error occured in joinByLocation")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def extractByLocation(layer: QgsVectorLayer, predicate: int, intersect: str):
            """_summary_

            Args:
                layer (QgsVectorLayer): Input vector layer. 
                predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
                intersect (QgsVectorLayer): Intersection vector layer

            Returns:
                layer (QgsVectorLayer): the output vector layer for the join.
            """

            logger.info("Extracting by location")
            try:
                parameter = {
                    'INPUT': layer,
                    'PREDICATE':predicate,
                    'INTERSECT':intersect,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:extractbylocation', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("extractByLocation finished")
                return result
            except Exception as error:
                logger.error("An error occured in extractByLocation")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def randomExtract(layer: QgsVectorLayer, method: int, number: int):
            """
            Takes a vector layer and generates a new one that contains only a subset of the features in the input layer.
            The subset is defined randomly, based on feature IDs, using a percentage or count value to define 
            the total number of features in the subset.

            Args:
                layer (QgsVectorLayer): Input vector layer. 
                method (integer): Random selection method. One of: 0 — Number of selected features 1 — Percentage of selected features
                number (integer): Number or percentage of features to select

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Extracting random features")
            try:
                parameter = {
                    'INPUT': layer,
                    'METHOD':method,
                    'NUMBER':number,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:randomextract', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("randomExtract finished")
                return result
            except Exception as error:
                logger.error("An error occured in randomExtract")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def difference(layer: QgsVectorLayer, overlay: QgsVectorLayer):
            """
            Extracts features from the input layer that don’t fall within the boundaries of the overlay layer.
            Input layer features that partially overlap the overlay layer feature(s) are split along the 
            boundary of those feature(s.

            Args:
                layer (QgsVectorLayer): Layer to extract (parts of) features from.
                overlay (QgsVectorLayer): Layer containing the geometries that will be subtracted from the iniput layer geometries

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Finding differences")
            try:
                parameter = {
                    'INPUT': layer,
                    'OVERLAY': overlay,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:difference', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Difference  finished")
                return result
            except Exception as error:
                logger.error("An error occured in Difference")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def reproject(layer: QgsVectorLayer, targetEPSG: int):
            """
            Reprojects a vector layer in a different CRS.
            The reprojected layer will have the same features and attributes of the input layer.
            QGIS processing algorithem: native:reprojectlayer.

    class Vector:
        '''
        A Worker subclass that contains methods to transform vector data or their attributes.
        '''

        def attributeindex(layer: QgsVectorLayer, field: str):

            Creates an index to speed up queries made against a field in a table.
            Support for index creation is dependent on the layers data provider and the field type.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                field (string): The field to base the index on

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Crating attribute index on " + layer + " on filed " + field)
            try:
                parameter = {
                    'INPUT': field,
                    'FIELD': field,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:createattributeindex', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("createattributeindex  finished")
                return result
            except Exception as error:
                logger.error("An error occured in createattributeindex")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def addxyfieldstolayer(layer: QgsVectorLayer, crs: str):
            """
            Adds X and Y (or latitude/longitude) fields to a point layer. The X/Y fields can be calculated in a different CRS to the layer (e.g. creating latitude/longitude fields for a layer in a projected CRS).

            Args:
                layer (QgsVectorLayer): The input layer.
                crs (string): Coordinate reference system to use for the generated x and y fields.

            Returns:
                layer (QgsVectorLayer): Specify the output layer.
            """

            logger.info(f"Adding X/Y fields to {layer}" )
            try:
                parameter = {
                    'INPUT': layer,
                    'CRS': crs,
                    'OUTPUT': 'memory:output_from_addxyfieldstolayer'
                }
                result = processing.run('native:addxyfieldstolayer', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("addxyfieldstolayer  finished")
                return result
            except Exception as error:
                logger.error("An error occured in addxyfieldstolayer")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def convexhull(layer: QgsVectorLayer):
            """
            Calculates the convex hull for each feature in an input layer.

            Args:
                layer (QgsVectorLayer): Input vector layer

            Returns:
                layer (QgsVectorLayer): Specify the output vector layer.
            """

            logger.info(f" Calculating convexhull for layer {layer}")
            try:
                parameter = {
                    'INPUT': layer,
                    'OUTPUT': 'memory:output_from_convexhull'
                }
                result = processing.run('native:convexhull', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("convexhull  finished")
                return result
            except Exception as error:
                logger.error("An error occured in convexhull")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def concavehull(inputlayer:QgsVectorLayer, alpha: float, holes: bool, multigeom: bool ):
            """
            Computes the concave hull of the features from an input point layer.

            Args:
                inputlayer (QgsVectorLayer): Input point vector layer
                alpha (float): Number from 0 (maximum concave hull) to 1 (convex hull).
                holes (boolean): Choose whether to allow holes in the final concave hull
                multigeom (boolean): Check if you want to have singlepart geometries instead of multipart ones.

            Returns:
                layer (QgsVectorLayer): Specify the output vector layer
            """

            logger.info('calcualting concavehull')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'ALPHA' : alpha,
                    'HOLES' : holes,
                    'NO_MULTIGEOMETRY' : multigeom,
                    'OUTPUT': 'memory:output_from_concavehull'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:concavehull', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('concavehull finished')
                return result
            except Exception as error:
                logger.error("An error occured in concavehull")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()            

        def extractvertices(inputlayer:QgsVectorLayer):
            """
            Takes a vector layer and generates a point layer with points representing the vertices in the input geometries.
            The attributes associated to each point are the same ones associated to the feature that the vertex belongs to.
            Additional fields are added to the vertices indicating the vertex index (beginning at 0), the feature’s part and its index within the part
            (as well as its ring for polygons), distance along original geometry and bisector angle of vertex for original geometry.

            Args:
                inputlayer (QgsVectorLayer): Input vector layer

            Returns:
                layer (QgsVectorLayer): Specify the output vector layer
            """

            logger.info('Extracting vertices')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'OUTPUT': 'memory:output_from_extractvertices'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:extractvertices', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('extractvertices finished')
                return result
            except Exception as error:
                logger.error("An error occured in extractvertices")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()    

        def multiringconstantbuffer(inputlayer:QgsVectorLayer, rings: int, distance : str):
            """
            Computes multi-ring (donut) buffer for the features of the input layer, using a fixed or dynamic distance and number of rings.

            Args:
                inputlayer (QgsVectorLayer): Input vector layer
                rings (integer): The number of rings. It can be a unique value (same number of rings for all the features) or it can be taken from features data (the number of rings depends on feature values).
                distance (string): Distance between the rings. It can be a unique value (same distance for all the features) or it can be taken from features data (a field in the input data layer).

            Returns:
                layer (QgsVectorLayer): Specify the output polygon vector layer
            """

            logger.info('Creating multiringconstantbuffer')
            try:
                dist = float(distance)
                logger.info('Using distance value')
            except:
                dist = QgsProperty.fromExpression(f'"{distance}"')
                logger.info('Using distance from field')

            try:
                parameters = {
                    'INPUT': inputlayer,
                    'RINGS': rings,
                    'DISTANCE': distance,
                    'OUTPUT': 'memory:output_from_multiringconstantbuffer'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:multiringconstantbuffer', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('multiringconstantbuffer finished')
                return result
            except Exception as error:
                logger.error("An error occured in multiringconstantbuffer")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed() 

        def poleofinaccessibility(inputlayer:QgsVectorLayer, tolerance: int):
            """
            Calculates the pole of inaccessibility for a polygon layer, which is the most distant internal point from the boundary of the surface. 
            This algorithm uses the ‘polylabel’ algorithm (Vladimir Agafonkin, 2016), which is an iterative approach guaranteed to find the true pole of inaccessibility within
            a specified tolerance. A more precise tolerance (lower value) requires more iterations and will take longer to calculate. 
            The distance from the calculated pole to the polygon boundary will be stored as a new attribute in the output layer.

            Args:
                inputlayer (QgsVectorLayer): Input vector layer
                tolerance (integer): Set the tolerance for the calculation. Default 1

            Returns:
                layer (QgsVectorLayer): Specify the output polygon vector layer.
            """

            logger.info('calcualting poleofinaccessibility')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'TOLERANCE' : tolerance,
                    'OUTPUT': 'memory:output_from_poleofinaccessibility'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:poleofinaccessibility', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('poleofinaccessibility finished')
                return result
            except Exception as error:
                logger.error("An error occured in poleofinaccessibility")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()


        def symmetricaldifference(inputlayer: QgsVectorLayer, overlay_layer: QgsVectorLayer):
            """
            Creates a layer containing features from both the input and overlay layers but with the overlapping areas between the two layers removed.
            The attribute table of the symmetrical difference layer contains attributes and fields from both the input and overlay layers.

            Args:
                inputlayer (QgsVectorLayer): First layer to extract (parts of) features from.
                overlay_layer (QgsVectorLayer): Second layer to extract (parts of) features from. Ideally the geometry type should be the same as input layer.

            Returns:
                layer (QgsVectorLayer): Specify the layer to contain (the parts of) the features from the input and overlay layers that do not overlap features from the other layer
            """

            logger.info('calcualting symetrical difference')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'OVERLAY' : overlay_layer,
                    'OUTPUT': 'memory:output_from_symmetricaldifference'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:symmetricaldifference', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Symmetricaldifference finished')
                return result
            except Exception as error:
                logger.error("An error occured in symmetricaldifference")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def lineintersections(inputlayer: QgsVectorLayer, split_layer: QgsVectorLayer, input_fields: list, intersect_fields: list):
            """
            Splits the lines or polygons in one layer using the lines or polygon rings in another layer to define the breaking points. Intersection between geometries in both layers are considered as split points.
            Output will contain multi geometries for split features.

            Args:
                inputlayer (QgsVectorLayer): Input line layer.
                split_layer (QgsVectorLayer): Layer to use to find line intersections.
                input_fields (list of strings): Field(s) of the input layer to keep in the output. If no fields are chosen all fields are taken.
                intersect_fields (list of strings): Field(s) of the intersect layer to keep in the output. If no fields are chosen all fields are taken. Duplicate field names will be appended a count suffix to avoid collision

            Returns:
                layer (QgsVectorLayer): Specify the layer to contain the intersection points of the lines from the input and overlay layers.
            """

            logger.info('Performing line intersections')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'INTERSECT': split_layer,
                    'INPUT_FIELDS' : input_fields, 
                    'INTERSECT_FIELDS' : intersect_fields,
                    'OUTPUT': 'memory:output_from_lineintersections'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:lineintersections', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Lineintersections finished')
                return result
            except Exception as error:
                logger.error("An error occured in Lineintersections")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def kmeansclustering(inputlayer: QgsVectorLayer, clusters: int):
            """
            Calculates the 2D distance based k-means cluster number for each input feature.
            K-means clustering aims to partition the features into k clusters in which each feature belongs to the cluster with the nearest mean. The mean point is represented by the barycenter of the clustered features.
            If input geometries are lines or polygons, the clustering is based on the centroid of the feature.

            Args:
                inputlayer (QgsVectorLayer): Layer to analyze
                clusters (integer): Number of clusters to create with the features

            Returns:
                layer (QgsVectorLayer): Specify the output vector layer for generated the clusters.
            """

            logger.info('Calculating clusters')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'CLUSTERS' : clusters,
                    'OUTPUT': 'memory:output_from_kmeansclustering'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:kmeansclustering', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Kmeansclustering finished')
                return result
            except Exception as error:
                logger.error("An error occured in Kmeansclustering")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def dbscanclustering(inputlayer: QgsVectorLayer, min_clusters: int, max_dist: int ):
            """
            Clusters point features based on a 2D implementation of Density-based spatial clustering of applications with noise (DBSCAN) algorithm.
            The algorithm requires two parameters, a minimum cluster size, and the maximum distance allowed between clustered points.

            Args:
                inputlayer (QgsVectorLayer): Layer to analyze
                min_clusters (integer): Minimum number of features to generate a cluster
                max_dist (integer): Distance beyond which two features can not belong to the same cluster (eps)

            Returns:
                layer (QgsVectorLayer): Specify the vector layer for the result of the clustering.
            """

            logger.info('Performing DBScan clustering')
            try:
                parameters = {
                    'INPUT': inputlayer,
                    'MIN_SIZE' : min_clusters,
                    'EPS': max_dist,
                    'OUTPUT': 'memory:output_from_dbscanclustering'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:dbscanclustering', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Dbscanclustering finished')
                return result
            except Exception as error:
                logger.error("An error occured in Dbscanclustering")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def countpointsinpolygon(polygons: QgsVectorLayer, points: QgsVectorLayer, weight : str, fieldname: str):
            """
            Takes a point and a polygon layer and counts the number of points from the point layer in each of the polygons of the polygon layer.
            A new polygon layer is generated, with the exact same content as the input polygon layer, but containing an additional field with the points count corresponding to each polygon.

            Args:
                polygons (QgsVectorLayer): Polygon layer whose features are associated with the count of points they contain
                points (QgsVectorLayer): Point layer with features to count
                weight (string): A field from the point layer. The count generated will be the sum of the weight field of the points contained by the polygon. If the weight field is not numeric, the count will be 0.
                fieldname (string): The name of the field to store the count of points

            Returns:
                layer (QgsVectorLayer): Specification of the output layer.
            """

            logger.info('Conducting point in polygon')
            try:
                if isinstance(weight, int):
                    value = weight
                else:
                    value = 0

                parameters = {
                    'POLYGONS': polygons,
                    'POINTS': points,
                    'WEIGHT': value,
                    'FIELD' : fieldname,
                    'OUTPUT': 'memory:output_from_countpointsinpolygon'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:Countpointsinpolygon', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Promote to multipart finished')
                return result
            except Exception as error:
                logger.error("An error occured in Countpointsinpolygon")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()  

        def promoteToMultipart(layer: QgsVectorLayer):
            """
            Generates a vectorlayer in which all geometries are multipart.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer that is used as input.

            Returns:
                layer (QgsVectorLayer): The QgsVectorLayer containing multi geometries.
            """

            logger.info('Collecting geometries')
            try:
                parameters = {
                    'INPUT': layer,
                    'OUTPUT': 'memory:multipart'
                }
                logger.info(f'Parameters: {str(parameters)}')
                result = processing.run('native:promotetomulti', parameters, feedback=Worker.progress)['OUTPUT']
                logger.info('Promote to multipart finished')
                return result
            except Exception as error:
                logger.error("An error occured in promoteToMultipart")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def extractByExpression(layer: QgsVectorLayer, expression: str):
            """
            Creates a vector layer from an input layer, containing only matching features.
            The criteria for adding features to the resulting layer is based on a QGIS expression.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
                expression (string): Expression to filter the vector layer

            Returns:
                layer (QgsVectorLayer): The QgsVectorLayer output layer.
            """

            logger.info("Extracting by expression")
            try:
                parameter = {
                    'INPUT': layer,
                    'EXPRESSION': expression,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:extractbyexpression', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Extractbyexpression  finished")
                return result
            except Exception as error:
                logger.error("An error occured in extractByExpression")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def renameTableField (layer: QgsVectorLayer, field: str, newname: str):
            """
            Renames an existing field from a vector layer.  
            The original layer is not modified. A new layer is generated where the attribute table contains the renamed field.
            QGIS processing algorithem: native:renametablefield

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                field (string): The field that is to be renamed
                newname (string): New name for the field

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Renaming field")
            try:
                parameter = {
                    'INPUT': layer,
                    'FIELD': field,
                    'NEW_NAME': newname,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:renametablefield', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("renameTableField  finished")
                return result
            except Exception as error:
                logger.error("An error occured in renameTableField")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def timeStamper(layer: QgsVectorLayer, ts_fieldname: str):
            """
            Create an attribute woth current timestamp on features.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                ts_fieldname (string): The name of the new timestamp field

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info(f'Creating timestamp {ts_fieldname} using fieldCalculator')
            newLayer = Worker.fieldCalculator(layer, ts_fieldname, 5, 0, 0, ' now() ')
            return newLayer

        def fieldCalculator (layer: QgsVectorLayer, fieldname: str, fieldtype: int, fieldlength: int, fieldprecision: int, formula: str):
            """
            Scripting the field calcualtor
            You can use all the supported expressions and functions.
            The original layer is not modified. A new layer is generated where the attribute table contains the calucalted field
            QGIS processing algorithem: native:fieldcalculator

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                fieldname (string): The name of the new calcualted field
                fieldtype (integer): Type of the field,  Default: 0  (0 — Float, 1 — Integer, 2 — String, 3 — Date)
                fieldlength (integer): Lenght of the field, Default: 10.
                fieldprecision (integer): Precision of the field, Default: 3.
                formula (string): The expression that populates the values of the field.

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Calculating field")
            try:
                parameter = {
                    'INPUT': layer,
                    'FIELD_NAME': fieldname,
                    'FIELD_TYPE': fieldtype,
                    'FIELD_LENGTH': fieldlength,
                    'FIELD_PRECISION': fieldprecision,
                    'FORMULA': formula,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:fieldcalculator', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("fieldCalculator  finished")
                return result
            except Exception as error:
                logger.error("An error occured in fieldCalculator")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def deleteColumns (layer: QgsVectorLayer, columns: list):
            """
            Takes a vector layer and generates a new one that has the same features but without the selected columns.

            Args:
                layer (QgsVectorLayer): Input vector layer to drop field(s) from
                columns (list of strings): The field(s) to drop

            Returns:
                layer (QgsVectorLayer): The QgsVectorLayer output layer.
            """

            logger.info("deleting fields")

            try:
                parameter = {
                    'INPUT': layer,
                    'COLUMN':columns,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:deletecolumn', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("deleteColumns  finished")
                return result
            except Exception as error:
                logger.error("An error occured in deleteColumns")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def addAutoIncrementalField(layer: QgsVectorLayer, fieldname: str, start: int):
            """
            Adds a new integer field to a vector layer, with a sequential value for each feature.
            This field can be used as a unique ID for features in the layer. The new attribute is not added to the input layer but a new layer is generated instead.
            The initial starting value for the incremental series can be specified. Optionally, the incremental series can be based on grouping 
            fields and a sort order for features can also be specified.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
                fieldname (string): Name of the field with autoincremental values.
                start (integer): Choose the initial number of the incremental count, Default: 0.

            Returns
                layer (QgsVectorLayer): The QgsVectorLayer output layer.
            """

            logger.info("Adding incremental field")
            try:
                parameter = {
                    'INPUT': layer,
                    'FIELD_NAME': fieldname,
                    'START':start,
                    'MODULUS':0,
                    'GROUP_FIELDS':[],
                    'SORT_EXPRESSION':'',
                    'SORT_ASCENDING':True,
                    'SORT_NULLS_FIRST':False,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:addautoincrementalfield', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("addAutoIncrementalField  finished")
                return result
            except Exception as error:
                logger.error("An error occured in addAutoIncrementalField")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def spatialindex(layer: QgsVectorLayer):
            """
            Creates an index to speed up access to the features in a layer based on their spatial location.
            Support for spatial index creation is dependent on the layer's data provider.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Crating spatial index on " + layer)
            try:
                parameter = {
                    'INPUT': layer,
                    'OUTPUT': 'memory:extracted'
                }
                result = processing.run('native:createspatialindex', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info(f'Parameters: {str(parameter)}')
                logger.info("createspatialindex  finished")
                return result
            except Exception as error:
                logger.error("An error occured in createspatialindex")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def clip(layer: QgsVectorLayer, overlay: str):
            """
            Clips a vector layer using the features of an additional polygon layer.
            Only the parts of the features in the input layer that fall within the polygons of 
            the overlay layer will be added to the resulting layer.

            Args:
                layer (QgsVectorLayer): Layer containing the features to be clipped
                overlay (QgsVectorLayer): Layer containing the clipping features

            Returns:
                layer (QgsVectorLayer): Layer to contain the features from the input layer that are inside the overlay (clipping) layer
            """

            logger.info("Clipping layers")
            try:
                parameter = {
                    'INPUT': layer,
                    'OVERLAY': overlay,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:clip', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Clip  finished")
                return result
            except Exception as error:
                logger.error("An error occured in Clip")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def joinByLocation(layer: QgsVectorLayer, predicate: int, join: str, join_fields: list, method: int, discard_nomatching: bool, prefix: str):
            """
            Takes an input vector layer and creates a new vector layer that is an extended version of
            the input one, with additional attributes in its attribute table.
            The additional attributes and their values are taken from a second vector layer.
            A spatial criteria is applied to select the values from the second layer that are added to each 
            feature from the first layer.

            Args:
                layer (QgsVectorLayer): Input vector layer. The output layer will consist of the features of this layer with attributes from matching features in the second layer.
                predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
                join (QgsVectorLayer): The join layer. Features of this vector layer will add their attributes to the source layer attribute table if they satisfy the spatial relationship.
                join_fields (list of strings): Select the specific fields you want to add from the join layer. By default all the fields are added.
                method (integer): The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one) 2 — Take attributes of the feature with largest overlap only (one-to-one)
                discard_nomatching (boolean): Remove from the output the input layer’s features which could not be joined
                prefix (string): Add a prefix to joined fields in order to easily identify them and avoid field name collision

            Returns:
                layer (QgsVectorLayer): the output vector layer for the join.
            """

            logger.info("Clipping layers")
            try:
                parameter = {
                    'INPUT': layer,
                    'PREDICATE':predicate,
                    'JOIN':join,
                    'JOIN_FIELDS':join_fields,
                    'METHOD':method,
                    'DISCARD_NONMATCHING':discard_nomatching,
                    'PREFIX':prefix,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:joinattributesbylocation', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("joinByLocation finished")
                return result
            except Exception as error:
                logger.error("An error occured in joinByLocation")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def extractByLocation(layer: QgsVectorLayer, predicate: int, intersect: str):
            """_summary_

            Args:
                layer (QgsVectorLayer): Input vector layer. 
                predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
                intersect (QgsVectorLayer): Intersection vector layer

            Returns:
                layer (QgsVectorLayer): the output vector layer for the join.
            """

            logger.info("Extracting by location")
            try:
                parameter = {
                    'INPUT': layer,
                    'PREDICATE':predicate,
                    'INTERSECT':intersect,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:extractbylocation', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("extractByLocation finished")
                return result
            except Exception as error:
                logger.error("An error occured in extractByLocation")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def randomExtract(layer: QgsVectorLayer, method: int, number: int):
            """
            Takes a vector layer and generates a new one that contains only a subset of the features in the input layer.
            The subset is defined randomly, based on feature IDs, using a percentage or count value to define 
            the total number of features in the subset.

            Args:
                layer (QgsVectorLayer): Input vector layer. 
                method (integer): Random selection method. One of: 0 — Number of selected features 1 — Percentage of selected features
                number (integer): Number or percentage of features to select

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Extracting random features")
            try:
                parameter = {
                    'INPUT': layer,
                    'METHOD':method,
                    'NUMBER':number,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:randomextract', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("randomExtract finished")
                return result
            except Exception as error:
                logger.error("An error occured in randomExtract")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def difference(layer: QgsVectorLayer, overlay: QgsVectorLayer):
            """
            Extracts features from the input layer that don’t fall within the boundaries of the overlay layer.
            Input layer features that partially overlap the overlay layer feature(s) are split along the 
            boundary of those feature(s.

            Args:
                layer (QgsVectorLayer): Layer to extract (parts of) features from.
                overlay (QgsVectorLayer): Layer containing the geometries that will be subtracted from the iniput layer geometries

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Finding differences")
            try:
                parameter = {
                    'INPUT': layer,
                    'OVERLAY': overlay,
                    'OUTPUT': 'memory:extracted'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:difference', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Difference  finished")
                return result
            except Exception as error:
                logger.error("An error occured in Difference")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def reproject(layer: QgsVectorLayer, targetEPSG: int):
            """
            Reprojects a vector layer in a different CRS.
            The reprojected layer will have the same features and attributes of the input layer.
            QGIS processing algorithem: native:reprojectlayer.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                targetEPSG (integer): The EPSG code og the target coordinate system.

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Running reporjector V2")
            if layerHasFeatures(layer):
                logger.info("Processing " + str(layer.featureCount()) +" features")
            try:
                parameter = {
                    'INPUT': layer,
                    'TARGET_CRS': QgsCoordinateReferenceSystem(targetEPSG),
                    'OUTPUT': 'memory:Reprojected'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:reprojectlayer', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Reproject finished")
                return result
            except Exception as error:
                logger.error("An error occured reprojectiong layer")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def simplify(layer: QgsVectorLayer, method: int, tolerance:int):
                """
                Simplifies the geometries in a line or polygon layer. 
                It creates a new layer with the same features as the ones in the input layer, but with geometries containing a lower number of vertices.
                QGIS processing algorithem: native:simplifygeometries.

                Args:
                    layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                    method (integer): Simplification method. One of: 0 — Distance (Douglas-Peucker), 1 — Snap to grid, 2 — Area (Visvalingam)
                    tolerance (integer): Threshold tolerance (in units of the layer): if the distance between two nodes is smaller than the tolerance value, the segment will be simplified and vertices will be removed.

                Returns:
                    layer (QgsVectorLayer): The result output from the algorithem
                """

                logger.info("Running simplify")
                if layerHasFeatures(layer):
                    logger.info("Processing " + str(layer.featureCount()) +" features")
                try:
                    parameter = {
                        'INPUT': layer,
                        'METHOD':method,
                        'TOLERANCE':tolerance,
                        'OUTPUT': 'memory:simplify'
                    }
                    logger.info(f'Parameters: {str(parameter)}')
                    result = processing.run('native:simplifygeometries', parameter, feedback=Worker.progress)['OUTPUT']
                    logger.info("Simplifygeometries finished")
                    return result
                except Exception as error:
                    logger.error("An error occured in simplifygeometries")
                    logger.error(f'{type(error).__name__}{str(error)}')
                    logger.critical("Program terminated" )
                    sys.exit()

        def forceRHR(layer: QgsVectorLayer):
            """
            Forces polygon geometries to respect the Right-Hand-Rule, in which the area that is bounded
            by a polygon is to the right of the boundary. 
            In particular, the exterior ring is oriented in a clockwise direction and any interior
            rings in a counter-clockwise direction.
            QGIS processing algorithem: native:forcerhr

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem

            Takes a vector layer and selects a subset of its features. No new layer is generated by this algorithm.
            The subset is defined randomly, based on feature IDs, using a percentage or count value to define the 
            total number of features in the subset.

            """

            logger.info("Running force right-hand rule")
            if layerHasFeatures(layer):
                logger.info("Processing " + str(layer.featureCount()) +" features")
            try:
                parameter = {
                    'INPUT': layer,
                    'OUTPUT': 'memory:forced'
                }
                result = processing.run('native:forcerhr', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("forceRHR finished")
                return result
            except Exception as error:
                logger.error("An error occured in forceRHR")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def join_by_attribute(layer1: QgsVectorLayer, layer1_field:str, layer2: QgsVectorLayer, layer2_field: str, fields_to_copy: list, method:int, discard: bool, prefix:str):
            """
            Takes an input vector layer and creates a new vector layer that is an extended version of the input one, 
            with additional attributes in its attribute table.
            The additional attributes and their values are taken from a second vector layer. An attribute is selected in each of them 
            to define the join criteria.
            QGIS processing algorithem: native:joinattributestable.

            Args:
                layer1 (QgsVectorLayer): The 1. QgsVectorLayer input for the algorithem
                layer1_field (string): Field of the source layer to use for the join
                layer2 (QgsVectorLayer): The 2. QgsVectorLayer input for the algorithem
                layer2_field (string): Field of the source layer to use for the join
                fields_to_copy (list of strings): Select the specific fields you want to add. By default all the fields are added. Default []
                method (integer): The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one)
                discard (boolean): Check if you don’t want to keep the features that could not be joined
                prefix (string): Add a prefix to joined fields in order to easily identify them and avoid field name collision

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Joining features features")
            if layerHasFeatures(layer1):
                logger.info("Processing " + str(layer1.featureCount()) +" features")
            try:
                parameter = {
                    'INPUT':layer1,
                    'FIELD':layer1_field,
                    'INPUT_2':layer2,
                    'FIELD_2':layer2_field,
                    'FIELDS_TO_COPY':fields_to_copy,
                    'METHOD':method,
                    'DISCARD_NONMATCHING':discard,
                    'PREFIX':prefix,
                    'OUTPUT': 'memory:joined'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:joinattributestable', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Joinattributestable finished")
                if layerHasFeatures(result):
                    logger.info("Returning " + str(result.featureCount()) +" features")
                return result
            except Exception as error:
                logger.error("An error occured in joinattributestable")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def dissolveFeatures(layer: QgsVectorLayer, fieldList: list, disjoined: bool):
            """
            Takes a vector layer and combines its features into new features. 
            One or more attributes can be specified to dissolve features belonging to the same class 
            (having the same value for the specified attributes), alternatively all features can be dissolved to a single feature.
            All output geometries will be converted to multi geometries. 
            QGIS processing algorithem: native:dissolve.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                fieldList (list of strings): List of fields to dissolve on. Default []
                disjoined (boolean): Keep disjoint features separate ? Default: False

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem

            """
            logger.info("Dissolving features")
            if layerHasFeatures(layer):
                logger.info("Processing " + str(layer.featureCount()) +" features")
            try:
                parameter = {
                    'INPUT': layer,
                    'FIELD' : fieldList,
                    'SEPARATE_DISJOINT' : False,
                    'OUTPUT': 'memory:dissolved'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:dissolve', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("DissolveFeatures finished")
                if layerHasFeatures(result):
                    logger.info("Returning " + str(result.featureCount()) +" features")
                return result
            except Exception as error:
                logger.error("An error occured in dissolveFeatures")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def bufferLayer(layer: QgsVectorLayer, distance: int, segements: int, endcapStyle: int, joinStyle: int, miterLimit: int, dissolve: bool):
            """
            Computes a buffer area for all the features in an input layer, using a fixed or data defined distance.
            It is possible to use a negative distance for polygon input layers.
            In this case the buffer will result in a smaller polygon (setback).
            QGIS processing algorithem: native:buffer

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                distance (integer): The buffer distance. Default: 10.0
                segements (integer): Number og segments. Default: 5
                endcapStyle (integer): Controls how line endings are handled in the buffer. Default: 0 (One of: 0 — Round, 1 — Flat, 2 — Square)
                joinStyle (integer): Specifies whether round, miter or beveled joins should be used when offsetting corners in a line. Default: 0 (Options are: 0 — Round, 1 — Miter, 2 — Bevel)
                miterLimit (integer): Sets the maximum distance from the offset geometry to use when creating a mitered join as a factor of the offset distance Default: 0, Minimum: 1
                dissolve (boolean): Dissolve the final buffer. Default: false.

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Creating buffer layer")
            if layerHasFeatures(layer):
                logger.info("Processing " + str(layer.featureCount()) +" features")
            try:
                parameter = {
                    'INPUT': layer,
                    'DISTANCE': distance,
                    'SEGMENTS': segements,
                    'END_CAP_STYLE': endcapStyle,
                    'JOIN_STYLE': joinStyle,
                    'MITER_LIMIT': miterLimit,
                    'DISSOLVE': dissolve,
                    'OUTPUT': 'memory:buffer'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:buffer', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("BufferLayer finished")
                return result
            except Exception as error:
                logger.error("An error occured in BufferLayer")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def fixGeometry(layer: QgsVectorLayer):
            """
            Attempts to create a valid representation of a given invalid geometry without losing any of the input vertices.
            Already valid geometries are returned without further intervention. Always outputs multi-geometry layer.
            QGIS processing algorithem: native:fixgeometries

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Fixing geometries")
            if layerHasFeatures(layer):
                logger.info("Processing " + str(layer.featureCount()) +" features")
            try:
                parameter = {
                    'INPUT': layer,
                    'OUTPUT': 'memory:buffer'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:fixgeometries', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("FixGeometry finished")
                return result
            except Exception as error:
                logger.error("An error occured in FixGeometry")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def createCentroids(layer: str):
            """
            Creates a new point layer, with points representing the centroids of the geometries of the input layer.
            The centroid is a single point representing the barycenter (of all parts) of the feature, so it can be outside the feature borders. But can also be a point on each part of the feature.
            The attributes of the points in the output layer are the same as for the original features.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Creating centroids")
            if layerHasFeatures(layer):
                logger.info("Processing " + str(layer.featureCount()) +" features")
            try:
                parameter = {
                    'INPUT': layer,
                    'ALL_PARTS':False,
                    'OUTPUT': 'memory:buffer'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:centroids', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Centroids finished")
                return result
            except Exception as error:
                logger.error("An error occured in createCentroids")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def randomselection(layer: QgsVectorLayer, method: int, number: int):
            """
            Takes a vector layer and selects a subset of its features. No new layer is generated by this algorithm.
            The subset is defined randomly, based on feature IDs, using a percentage or count value to define the 
            total number of features in the subset.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                method (integer): Random selection method. One of: 0 — Number of selected features, 1 — Percentage of selected features
                number (integer): Number or percentage of features to select

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Performing random selection")
            if layerHasFeatures(layer):
                logger.info("Processing " + str(layer.featureCount()) +" features")
            try:
                parameter = {
                    'INPUT': layer,
                    'METHOD':method,
                    'NUMBER':number,
                    'OUTPUT': 'memory:buffer'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:randomextract', parameter, feedback=Worker.progress)['OUTPUT']
                if layerHasFeatures(result):
                    logger.info("Returning " + str(result.featureCount()) +" features")
                logger.info("randomextract finished")
                return result
            except Exception as error:
                logger.error("An error occured in FixGeometry")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def execute_sql(connection, databasetype, sql_expression, pgdb_name=None, driver=None):
            """
            Execute an SQL query against a database. 
            This can be used to create tables, truncate, build indexes etc.
            The database type must be specified in the 'database' parameter (one of 'Mssql' or 'Postgres')
            The default Mssql driver is 'SQL Server' - if this needs to be overwritten, specify the parameter driver, else leave it empty.
            SQL statments must be trippel double-quoted - prepare the statement in the QGIS sql executor tool for testing. 

            Args:
                connection (string): Name of a database connection from settings.json
                databasetype (string): The database type, one of 'Mssql' or 'Postgres'.
                sql_expression (string): The SQL expression to be executed. Use trippel double-quotes arraound the expression
                pgdb_name (string): Name of postgres database if databasetype is  Postgres. Defaults to None.
                driver (string): Defaults to None. The name of the Mssql driver, if 'SQL Server' is not working.

            Returns:
                Errorcode (integer): Returns 0 if the SQL is executed without errors.

            """

            config = get_config()
            if databasetype in ('Postgres', 'Mssql'):
                logger.info(f'Running SQL executor on {databasetype}' )
            else :
                logger.info(f'Unsupported database: {databasetype}, use one of "Mssql" or "Postgres"' )
                logger.critical("Program terminated" )
                sys.exit()
            try:
                dbconnection = config['DatabaseConnections'][connection]
                if databasetype == 'Mssql':
                    import pyodbc 
                    if driver == "":
                        mssqldriver = 'SQL Server'
                    else :
                        mssqldriver = 'driver'
                    cnxn = pyodbc.connect('DRIVER={'+mssqldriver+'};Server='+dbconnection['host']+';Database='+dbconnection['databasename']+';User ID='+dbconnection['user']+';Password='+dbconnection['password'])
                    logger.info("Using connection :" + 'DRIVER={'+mssqldriver+'};Server='+dbconnection['host']+';Database='+dbconnection['databasename']+';User ID='+dbconnection['user']+';Password=xxxxxxxx')
                    cursor = cnxn.cursor()
                    logger.info(f'Query: {sql_expression}' )
                    cursor.execute(sql_expression) 
                    logger.info("SQL executor finished")
                    return 0

                if databasetype == 'Postgres':
                    import psycopg2
                    connection = psycopg2.connect(user=dbconnection['user'], password=dbconnection['password'], host=dbconnection['host'], port=dbconnection['port'], database=pgdb_name)
                    logger.info("Using connection : user="+ dbconnection['user']+", password=xxxxxx, host="+dbconnection['host']+", port="+dbconnection['port']+", database="+pgdb_name )
                    cursor = connection.cursor()
                    logger.info(f'Query: {sql_expression}' )
                    cursor.execute(sql_expression)
                    connection.commit()
                    cursor.close()
                    connection.close()
                    logger.info("SQL executor finished")
                    return 0

            except Exception as error:
                logger.error("An error occured running SQL executor")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def mergeVectorLayers(layers: list, crs: str ):
            """
            Combines multiple vector layers of the same geometry type into a single one.
            The attribute table of the resulting layer will contain the fields from all input layers. 
            If fields with the same name but different types are found then the exported field will be automatically 
            converted into a string type field. New fields storing the original layer name and source are also added.

            Optionally, the destination coordinate reference system (CRS) for the merged layer can be set. If it is 
            not set, the CRS will be taken from the first input layer. All layers will be reprojected to match this CRS.

            Args:
                layer (QgsVectorLayer): The layers that are to be merged into a single layer. Layers should be of the same geometry type.
                CRS (Crs): Choose the CRS for the output layer. If not specified, the CRS of the first input layer is used.

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Performing mergeVectorLayers")
            logger.info(f'Processing {str(len(layers))} layers')
            try:
                parameter = {
                    'LAYERS': layers,
                    'CRS':crs,
                    'OUTPUT': 'memory:buffer'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:mergevectorlayers', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Returning " + str(result.featureCount()) +" features")
                logger.info("mergeVectorLayers finished")
                return result
            except Exception as error:
                logger.error("An error occured in mergeVectorLayers")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def delete_geopacakge_layers(geopackage: str, layernames: list):
            """
            Deletes one or more tables from a geopackage

            Args:
                geopackage (string): The full path for the geopackage file
                layernames (list of strings): List of layernames to be deleted
            """

            logger.info("Performing delete_geopacakge_layer")
            logger.info(f"Deleting layers {layernames}")

            if os.path.isfile(geopackage):
                try:
                    for layer in layernames:
                        logger.info(f"Deleting layer {layer}")
                        parameter = {'DATABASE':'{0}|layername={1}'.format(geopackage, layer),
                        'SQL':'drop table {0}'.format(layer)}
                        logger.info(f'Parameters: {str(parameter)}')
                        processing.run("native:spatialiteexecutesql", parameter )
                        logger.info(f"Layer deleted")
                    logger.info(f"Finished deleting layers")


                except Exception as error:
                    logger.error("An error occured in delete_geopacakge_layer")
                    logger.error(f'{type(error).__name__}{str(error)}')
                    logger.critical("Program terminated" )
                    script_failed()
            else:    
                pass

        def assign_projection(layer: QgsVectorLayer, targetEPSG: int):
            """
            Assign a new projection on a layer. The returned layer is precisely the same layer but assigned a new CRS.

            Args:
            layer : (QgsVectorLayer)Q The layer to be assigned a new CRS.
            targetEPSG (integer): The EPSG code og the target coordinate system.

            Returns:
                layer (QgsVectorLayer): Layer with the new projection assigned
            """

            logger.info(f'Assigning CRS EPSG:{targetEPSG} to {layer.name()}')
            try:
                parameter = {
                    'INPUT': layer,
                    'CRS': QgsCoordinateReferenceSystem(targetEPSG),
                    'OUTPUT': 'TEMPORARY_OUTPUT'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:assignprojection', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info('Assigning projection finished')
                return result
            except Exception as error:
                logger.error("An error occured assigning a new crs to layer")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

    class File:
        '''
        A Worker subclass that contains methods to work with the filesystem.
        '''

        def download_file(url, local_filename):
            """
            Downloads a file from the given URL and saves it locally.

            Args:
                url (string): The URL of the file to download
                local_filename (string): The local path where the file should be saved.

            Returns:
                boolean (boolean): True if download is succesful, otherwise False.
            """

            logger.info(f'Downloading file from {url}')
            try:
                with requests.get(url, stream=True) as response:
                    response.raise_for_status()
                    with open(local_filename, 'wb') as file:
                        for chunk in response.iter_content(chunk_size=8192):
                            file.write(chunk)

                logger.info(f'Download completed: {local_filename}')
                return True

            except Exception as error:
                logger.error('An error occurred when downloading the file')
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

            return False

        def folderTruncator(folder: str):
            """
            Deletes all contents of a folder (files and directories), but not the folder it self.

            Args:
                folder (string): Full path to the folder to be truncated

            Returns:
                None
            """

            logger.info(f'Truncating folder {folder}')
            try:
                for root, dirs, files in os.walk(folder):
                    for f in files:
                        os.unlink(os.path.join(root, f))
                    for d in dirs:
                        shutil.rmtree(os.path.join(root, d))
                logger.info(f'Folder {folder} truncated')

                return None
            except Exception as error:
                logger.error("An error occured truncating folder")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()

        def deleter(filepath : str):
            """
            A worker that deletes a specific file.

            Args:
                filepath (string): The full path to the file to delete
            """

            logger.info(f'Deleting file {filepath}')
            try:
                if os.path.exists(filepath):
                    os.remove(filepath)
                    logger.info(f'File found and deleted')
                else:
                    logger.info(f'File does not exist, skipping delete.')

            except Exception as error:
                logger.error(f"An error occured deleting file {filepath}")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def mover(input_filepath : str, output_filepath : str):
            """
            Moves a file from one location to another.
            Can also be used for renaming.

            Args:
                input_filepath (string): The full path to the file to move 
                output_filepath (string): The full path to the target file
            """

            logger.info(f'Moving file {input_filepath} to {output_filepath}')
            try:
                if os.path.exists(input_filepath):
                    shutil.copyfile(input_filepath, output_filepath)
                    logger.info(f'File moved')
                else:
                    logger.info(f'Input file does not exist, skipping move.')

            except Exception as error:
                logger.error(f"An error occured moving file {input_filepath}")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def lister(input_folder : str, file_extension : str):
            """
            Creates a python list of files with a specific extension, from an input location.
            Returns the full path to the files. 

            Args:
                input_folder (string): The full path to teh input folder.
                file_extension (string): The file extension to search for.

            Returns:
                list (list of strings): A list of file paths derived from the input directory of the specified file type
            """

            filelist = []
            logger.info(f'Building filelist of {file_extension}-files from directory {input_folder}')
            try:
                for root, dirs, files in os.walk(input_folder):          
                    for file in files:
                        if file.endswith(file_extension):
                            filelist.append(os.path.join(root, file))
                if len(filelist) > 0:
                    logger.info(f'Filelist returning {len(filelist)} elements')
                    return filelist
                else:
                    logger.info(f'Returning empty filelist for destinateion {input_folder}')
                    return []
            except Exception as error:
                logger.error(f"An error occured listing files from folder {input_folder}")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

        def existence_checker(input_path : str):
            """
            Checks if a specific file exists. Returns True if file exists, False if not.

            Args:
                input_folder (string): The full path to the input folder.

            Returns:
                boolean (boolean): True/False if file exists.
            """

            logger.info(f'Checking if file {input_path} exists')
            try:
                if os.path.exists(input_path):
                    logger.info(f'File exists, returning True')
                    return True
                else:
                    logger.info(f'File does not exist, returning False')
                    return False
            except Exception as error:
                logger.error(f"An error occured checking if file {input_path} exists")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

File

A Worker subclass that contains methods to work with the filesystem.

Source code in python\engine\workers.py
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
class File:
    '''
    A Worker subclass that contains methods to work with the filesystem.
    '''

    def download_file(url, local_filename):
        """
        Downloads a file from the given URL and saves it locally.

        Args:
            url (string): The URL of the file to download
            local_filename (string): The local path where the file should be saved.

        Returns:
            boolean (boolean): True if download is succesful, otherwise False.
        """

        logger.info(f'Downloading file from {url}')
        try:
            with requests.get(url, stream=True) as response:
                response.raise_for_status()
                with open(local_filename, 'wb') as file:
                    for chunk in response.iter_content(chunk_size=8192):
                        file.write(chunk)

            logger.info(f'Download completed: {local_filename}')
            return True

        except Exception as error:
            logger.error('An error occurred when downloading the file')
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

        return False

    def folderTruncator(folder: str):
        """
        Deletes all contents of a folder (files and directories), but not the folder it self.

        Args:
            folder (string): Full path to the folder to be truncated

        Returns:
            None
        """

        logger.info(f'Truncating folder {folder}')
        try:
            for root, dirs, files in os.walk(folder):
                for f in files:
                    os.unlink(os.path.join(root, f))
                for d in dirs:
                    shutil.rmtree(os.path.join(root, d))
            logger.info(f'Folder {folder} truncated')

            return None
        except Exception as error:
            logger.error("An error occured truncating folder")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def deleter(filepath : str):
        """
        A worker that deletes a specific file.

        Args:
            filepath (string): The full path to the file to delete
        """

        logger.info(f'Deleting file {filepath}')
        try:
            if os.path.exists(filepath):
                os.remove(filepath)
                logger.info(f'File found and deleted')
            else:
                logger.info(f'File does not exist, skipping delete.')

        except Exception as error:
            logger.error(f"An error occured deleting file {filepath}")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def mover(input_filepath : str, output_filepath : str):
        """
        Moves a file from one location to another.
        Can also be used for renaming.

        Args:
            input_filepath (string): The full path to the file to move 
            output_filepath (string): The full path to the target file
        """

        logger.info(f'Moving file {input_filepath} to {output_filepath}')
        try:
            if os.path.exists(input_filepath):
                shutil.copyfile(input_filepath, output_filepath)
                logger.info(f'File moved')
            else:
                logger.info(f'Input file does not exist, skipping move.')

        except Exception as error:
            logger.error(f"An error occured moving file {input_filepath}")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def lister(input_folder : str, file_extension : str):
        """
        Creates a python list of files with a specific extension, from an input location.
        Returns the full path to the files. 

        Args:
            input_folder (string): The full path to teh input folder.
            file_extension (string): The file extension to search for.

        Returns:
            list (list of strings): A list of file paths derived from the input directory of the specified file type
        """

        filelist = []
        logger.info(f'Building filelist of {file_extension}-files from directory {input_folder}')
        try:
            for root, dirs, files in os.walk(input_folder):          
                for file in files:
                    if file.endswith(file_extension):
                        filelist.append(os.path.join(root, file))
            if len(filelist) > 0:
                logger.info(f'Filelist returning {len(filelist)} elements')
                return filelist
            else:
                logger.info(f'Returning empty filelist for destinateion {input_folder}')
                return []
        except Exception as error:
            logger.error(f"An error occured listing files from folder {input_folder}")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def existence_checker(input_path : str):
        """
        Checks if a specific file exists. Returns True if file exists, False if not.

        Args:
            input_folder (string): The full path to the input folder.

        Returns:
            boolean (boolean): True/False if file exists.
        """

        logger.info(f'Checking if file {input_path} exists')
        try:
            if os.path.exists(input_path):
                logger.info(f'File exists, returning True')
                return True
            else:
                logger.info(f'File does not exist, returning False')
                return False
        except Exception as error:
            logger.error(f"An error occured checking if file {input_path} exists")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

deleter(filepath)

A worker that deletes a specific file.

Parameters:

Name Type Description Default
filepath string

The full path to the file to delete

required
Source code in python\engine\workers.py
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
def deleter(filepath : str):
    """
    A worker that deletes a specific file.

    Args:
        filepath (string): The full path to the file to delete
    """

    logger.info(f'Deleting file {filepath}')
    try:
        if os.path.exists(filepath):
            os.remove(filepath)
            logger.info(f'File found and deleted')
        else:
            logger.info(f'File does not exist, skipping delete.')

    except Exception as error:
        logger.error(f"An error occured deleting file {filepath}")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

download_file(url, local_filename)

Downloads a file from the given URL and saves it locally.

Parameters:

Name Type Description Default
url string

The URL of the file to download

required
local_filename string

The local path where the file should be saved.

required

Returns:

Name Type Description
boolean boolean

True if download is succesful, otherwise False.

Source code in python\engine\workers.py
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
def download_file(url, local_filename):
    """
    Downloads a file from the given URL and saves it locally.

    Args:
        url (string): The URL of the file to download
        local_filename (string): The local path where the file should be saved.

    Returns:
        boolean (boolean): True if download is succesful, otherwise False.
    """

    logger.info(f'Downloading file from {url}')
    try:
        with requests.get(url, stream=True) as response:
            response.raise_for_status()
            with open(local_filename, 'wb') as file:
                for chunk in response.iter_content(chunk_size=8192):
                    file.write(chunk)

        logger.info(f'Download completed: {local_filename}')
        return True

    except Exception as error:
        logger.error('An error occurred when downloading the file')
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

    return False

existence_checker(input_path)

Checks if a specific file exists. Returns True if file exists, False if not.

Parameters:

Name Type Description Default
input_folder string

The full path to the input folder.

required

Returns:

Name Type Description
boolean boolean

True/False if file exists.

Source code in python\engine\workers.py
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
def existence_checker(input_path : str):
    """
    Checks if a specific file exists. Returns True if file exists, False if not.

    Args:
        input_folder (string): The full path to the input folder.

    Returns:
        boolean (boolean): True/False if file exists.
    """

    logger.info(f'Checking if file {input_path} exists')
    try:
        if os.path.exists(input_path):
            logger.info(f'File exists, returning True')
            return True
        else:
            logger.info(f'File does not exist, returning False')
            return False
    except Exception as error:
        logger.error(f"An error occured checking if file {input_path} exists")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

folderTruncator(folder)

Deletes all contents of a folder (files and directories), but not the folder it self.

Parameters:

Name Type Description Default
folder string

Full path to the folder to be truncated

required

Returns:

Type Description

None

Source code in python\engine\workers.py
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
def folderTruncator(folder: str):
    """
    Deletes all contents of a folder (files and directories), but not the folder it self.

    Args:
        folder (string): Full path to the folder to be truncated

    Returns:
        None
    """

    logger.info(f'Truncating folder {folder}')
    try:
        for root, dirs, files in os.walk(folder):
            for f in files:
                os.unlink(os.path.join(root, f))
            for d in dirs:
                shutil.rmtree(os.path.join(root, d))
        logger.info(f'Folder {folder} truncated')

        return None
    except Exception as error:
        logger.error("An error occured truncating folder")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

lister(input_folder, file_extension)

Creates a python list of files with a specific extension, from an input location. Returns the full path to the files.

Parameters:

Name Type Description Default
input_folder string

The full path to teh input folder.

required
file_extension string

The file extension to search for.

required

Returns:

Name Type Description
list list of strings

A list of file paths derived from the input directory of the specified file type

Source code in python\engine\workers.py
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
def lister(input_folder : str, file_extension : str):
    """
    Creates a python list of files with a specific extension, from an input location.
    Returns the full path to the files. 

    Args:
        input_folder (string): The full path to teh input folder.
        file_extension (string): The file extension to search for.

    Returns:
        list (list of strings): A list of file paths derived from the input directory of the specified file type
    """

    filelist = []
    logger.info(f'Building filelist of {file_extension}-files from directory {input_folder}')
    try:
        for root, dirs, files in os.walk(input_folder):          
            for file in files:
                if file.endswith(file_extension):
                    filelist.append(os.path.join(root, file))
        if len(filelist) > 0:
            logger.info(f'Filelist returning {len(filelist)} elements')
            return filelist
        else:
            logger.info(f'Returning empty filelist for destinateion {input_folder}')
            return []
    except Exception as error:
        logger.error(f"An error occured listing files from folder {input_folder}")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

mover(input_filepath, output_filepath)

Moves a file from one location to another. Can also be used for renaming.

Parameters:

Name Type Description Default
input_filepath string

The full path to the file to move

required
output_filepath string

The full path to the target file

required
Source code in python\engine\workers.py
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
def mover(input_filepath : str, output_filepath : str):
    """
    Moves a file from one location to another.
    Can also be used for renaming.

    Args:
        input_filepath (string): The full path to the file to move 
        output_filepath (string): The full path to the target file
    """

    logger.info(f'Moving file {input_filepath} to {output_filepath}')
    try:
        if os.path.exists(input_filepath):
            shutil.copyfile(input_filepath, output_filepath)
            logger.info(f'File moved')
        else:
            logger.info(f'Input file does not exist, skipping move.')

    except Exception as error:
        logger.error(f"An error occured moving file {input_filepath}")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

Generic

A Worker subclass that contains method for generic execution of QGIS processing functions.

Source code in python\engine\workers.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
class Generic:
    '''
    A Worker subclass that contains method for generic execution of QGIS processing functions.
    '''
    def ProcessingRunner(algName: str, parameters: dict):
        """
        A generic method to run QGIS processing algorithms. Supply the algorithm name and the parameters as a dictionary.
        The method will run the algorithm and return the outputs.

        Args:
            algName (str): The name of the QGIS processing algorithm to run.
            parameters (dict): the parameters for the algorithm as a dictionary.

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info(f'Running {algName}')
        try:

            result = processing.run(algName, parameters, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameters)}')
            logger.info("ProcessingRunner  finished")
            return result
        except Exception as error:
            logger.error("An error occured in ProcessingRunner")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

ProcessingRunner(algName, parameters)

A generic method to run QGIS processing algorithms. Supply the algorithm name and the parameters as a dictionary. The method will run the algorithm and return the outputs.

Parameters:

Name Type Description Default
algName str

The name of the QGIS processing algorithm to run.

required
parameters dict

the parameters for the algorithm as a dictionary.

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def ProcessingRunner(algName: str, parameters: dict):
    """
    A generic method to run QGIS processing algorithms. Supply the algorithm name and the parameters as a dictionary.
    The method will run the algorithm and return the outputs.

    Args:
        algName (str): The name of the QGIS processing algorithm to run.
        parameters (dict): the parameters for the algorithm as a dictionary.

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info(f'Running {algName}')
    try:

        result = processing.run(algName, parameters, feedback=Worker.progress)['OUTPUT']
        logger.info(f'Parameters: {str(parameters)}')
        logger.info("ProcessingRunner  finished")
        return result
    except Exception as error:
        logger.error("An error occured in ProcessingRunner")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

Vector

A Worker subclass that contains methods to transform vector data or their attributes.

Source code in python\engine\workers.py
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
class Vector:
    '''
    A Worker subclass that contains methods to transform vector data or their attributes.
    '''

    def attributeindex(layer: QgsVectorLayer, field: str):
        """
        Creates an index to speed up queries made against a field in a table.
        Support for index creation is dependent on the layer's data provider and the field type.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            field (string): The field to base the index on

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Crating attribute index on " + layer + " on filed " + field)
        try:
            parameter = {
                'INPUT': field,
                'FIELD': field,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:createattributeindex', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("createattributeindex  finished")
            return result
        except Exception as error:
            logger.error("An error occured in createattributeindex")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def addxyfieldstolayer(layer: QgsVectorLayer, crs: str):
        """
        Adds X and Y (or latitude/longitude) fields to a point layer. The X/Y fields can be calculated in a different CRS to the layer (e.g. creating latitude/longitude fields for a layer in a projected CRS).

        Args:
            layer (QgsVectorLayer): The input layer.
            crs (string): Coordinate reference system to use for the generated x and y fields.

        Returns:
            layer (QgsVectorLayer): Specify the output layer.
        """

        logger.info(f"Adding X/Y fields to {layer}" )
        try:
            parameter = {
                'INPUT': layer,
                'CRS': crs,
                'OUTPUT': 'memory:output_from_addxyfieldstolayer'
            }
            result = processing.run('native:addxyfieldstolayer', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("addxyfieldstolayer  finished")
            return result
        except Exception as error:
            logger.error("An error occured in addxyfieldstolayer")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def convexhull(layer: QgsVectorLayer):
        """
        Calculates the convex hull for each feature in an input layer.

        Args:
            layer (QgsVectorLayer): Input vector layer

        Returns:
            layer (QgsVectorLayer): Specify the output vector layer.
        """

        logger.info(f" Calculating convexhull for layer {layer}")
        try:
            parameter = {
                'INPUT': layer,
                'OUTPUT': 'memory:output_from_convexhull'
            }
            result = processing.run('native:convexhull', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("convexhull  finished")
            return result
        except Exception as error:
            logger.error("An error occured in convexhull")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def concavehull(inputlayer:QgsVectorLayer, alpha: float, holes: bool, multigeom: bool ):
        """
        Computes the concave hull of the features from an input point layer.

        Args:
            inputlayer (QgsVectorLayer): Input point vector layer
            alpha (float): Number from 0 (maximum concave hull) to 1 (convex hull).
            holes (boolean): Choose whether to allow holes in the final concave hull
            multigeom (boolean): Check if you want to have singlepart geometries instead of multipart ones.

        Returns:
            layer (QgsVectorLayer): Specify the output vector layer
        """

        logger.info('calcualting concavehull')
        try:
            parameters = {
                'INPUT': inputlayer,
                'ALPHA' : alpha,
                'HOLES' : holes,
                'NO_MULTIGEOMETRY' : multigeom,
                'OUTPUT': 'memory:output_from_concavehull'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:concavehull', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('concavehull finished')
            return result
        except Exception as error:
            logger.error("An error occured in concavehull")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()            

    def extractvertices(inputlayer:QgsVectorLayer):
        """
        Takes a vector layer and generates a point layer with points representing the vertices in the input geometries.
        The attributes associated to each point are the same ones associated to the feature that the vertex belongs to.
        Additional fields are added to the vertices indicating the vertex index (beginning at 0), the feature’s part and its index within the part
        (as well as its ring for polygons), distance along original geometry and bisector angle of vertex for original geometry.

        Args:
            inputlayer (QgsVectorLayer): Input vector layer

        Returns:
            layer (QgsVectorLayer): Specify the output vector layer
        """

        logger.info('Extracting vertices')
        try:
            parameters = {
                'INPUT': inputlayer,
                'OUTPUT': 'memory:output_from_extractvertices'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:extractvertices', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('extractvertices finished')
            return result
        except Exception as error:
            logger.error("An error occured in extractvertices")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()    

    def multiringconstantbuffer(inputlayer:QgsVectorLayer, rings: int, distance : str):
        """
        Computes multi-ring (donut) buffer for the features of the input layer, using a fixed or dynamic distance and number of rings.

        Args:
            inputlayer (QgsVectorLayer): Input vector layer
            rings (integer): The number of rings. It can be a unique value (same number of rings for all the features) or it can be taken from features data (the number of rings depends on feature values).
            distance (string): Distance between the rings. It can be a unique value (same distance for all the features) or it can be taken from features data (a field in the input data layer).

        Returns:
            layer (QgsVectorLayer): Specify the output polygon vector layer
        """

        logger.info('Creating multiringconstantbuffer')
        try:
            dist = float(distance)
            logger.info('Using distance value')
        except:
            dist = QgsProperty.fromExpression(f'"{distance}"')
            logger.info('Using distance from field')

        try:
            parameters = {
                'INPUT': inputlayer,
                'RINGS': rings,
                'DISTANCE': distance,
                'OUTPUT': 'memory:output_from_multiringconstantbuffer'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:multiringconstantbuffer', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('multiringconstantbuffer finished')
            return result
        except Exception as error:
            logger.error("An error occured in multiringconstantbuffer")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed() 

    def poleofinaccessibility(inputlayer:QgsVectorLayer, tolerance: int):
        """
        Calculates the pole of inaccessibility for a polygon layer, which is the most distant internal point from the boundary of the surface. 
        This algorithm uses the ‘polylabel’ algorithm (Vladimir Agafonkin, 2016), which is an iterative approach guaranteed to find the true pole of inaccessibility within
        a specified tolerance. A more precise tolerance (lower value) requires more iterations and will take longer to calculate. 
        The distance from the calculated pole to the polygon boundary will be stored as a new attribute in the output layer.

        Args:
            inputlayer (QgsVectorLayer): Input vector layer
            tolerance (integer): Set the tolerance for the calculation. Default 1

        Returns:
            layer (QgsVectorLayer): Specify the output polygon vector layer.
        """

        logger.info('calcualting poleofinaccessibility')
        try:
            parameters = {
                'INPUT': inputlayer,
                'TOLERANCE' : tolerance,
                'OUTPUT': 'memory:output_from_poleofinaccessibility'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:poleofinaccessibility', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('poleofinaccessibility finished')
            return result
        except Exception as error:
            logger.error("An error occured in poleofinaccessibility")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()


    def symmetricaldifference(inputlayer: QgsVectorLayer, overlay_layer: QgsVectorLayer):
        """
        Creates a layer containing features from both the input and overlay layers but with the overlapping areas between the two layers removed.
        The attribute table of the symmetrical difference layer contains attributes and fields from both the input and overlay layers.

        Args:
            inputlayer (QgsVectorLayer): First layer to extract (parts of) features from.
            overlay_layer (QgsVectorLayer): Second layer to extract (parts of) features from. Ideally the geometry type should be the same as input layer.

        Returns:
            layer (QgsVectorLayer): Specify the layer to contain (the parts of) the features from the input and overlay layers that do not overlap features from the other layer
        """

        logger.info('calcualting symetrical difference')
        try:
            parameters = {
                'INPUT': inputlayer,
                'OVERLAY' : overlay_layer,
                'OUTPUT': 'memory:output_from_symmetricaldifference'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:symmetricaldifference', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Symmetricaldifference finished')
            return result
        except Exception as error:
            logger.error("An error occured in symmetricaldifference")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def lineintersections(inputlayer: QgsVectorLayer, split_layer: QgsVectorLayer, input_fields: list, intersect_fields: list):
        """
        Splits the lines or polygons in one layer using the lines or polygon rings in another layer to define the breaking points. Intersection between geometries in both layers are considered as split points.
        Output will contain multi geometries for split features.

        Args:
            inputlayer (QgsVectorLayer): Input line layer.
            split_layer (QgsVectorLayer): Layer to use to find line intersections.
            input_fields (list of strings): Field(s) of the input layer to keep in the output. If no fields are chosen all fields are taken.
            intersect_fields (list of strings): Field(s) of the intersect layer to keep in the output. If no fields are chosen all fields are taken. Duplicate field names will be appended a count suffix to avoid collision

        Returns:
            layer (QgsVectorLayer): Specify the layer to contain the intersection points of the lines from the input and overlay layers.
        """

        logger.info('Performing line intersections')
        try:
            parameters = {
                'INPUT': inputlayer,
                'INTERSECT': split_layer,
                'INPUT_FIELDS' : input_fields, 
                'INTERSECT_FIELDS' : intersect_fields,
                'OUTPUT': 'memory:output_from_lineintersections'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:lineintersections', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Lineintersections finished')
            return result
        except Exception as error:
            logger.error("An error occured in Lineintersections")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def kmeansclustering(inputlayer: QgsVectorLayer, clusters: int):
        """
        Calculates the 2D distance based k-means cluster number for each input feature.
        K-means clustering aims to partition the features into k clusters in which each feature belongs to the cluster with the nearest mean. The mean point is represented by the barycenter of the clustered features.
        If input geometries are lines or polygons, the clustering is based on the centroid of the feature.

        Args:
            inputlayer (QgsVectorLayer): Layer to analyze
            clusters (integer): Number of clusters to create with the features

        Returns:
            layer (QgsVectorLayer): Specify the output vector layer for generated the clusters.
        """

        logger.info('Calculating clusters')
        try:
            parameters = {
                'INPUT': inputlayer,
                'CLUSTERS' : clusters,
                'OUTPUT': 'memory:output_from_kmeansclustering'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:kmeansclustering', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Kmeansclustering finished')
            return result
        except Exception as error:
            logger.error("An error occured in Kmeansclustering")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def dbscanclustering(inputlayer: QgsVectorLayer, min_clusters: int, max_dist: int ):
        """
        Clusters point features based on a 2D implementation of Density-based spatial clustering of applications with noise (DBSCAN) algorithm.
        The algorithm requires two parameters, a minimum cluster size, and the maximum distance allowed between clustered points.

        Args:
            inputlayer (QgsVectorLayer): Layer to analyze
            min_clusters (integer): Minimum number of features to generate a cluster
            max_dist (integer): Distance beyond which two features can not belong to the same cluster (eps)

        Returns:
            layer (QgsVectorLayer): Specify the vector layer for the result of the clustering.
        """

        logger.info('Performing DBScan clustering')
        try:
            parameters = {
                'INPUT': inputlayer,
                'MIN_SIZE' : min_clusters,
                'EPS': max_dist,
                'OUTPUT': 'memory:output_from_dbscanclustering'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:dbscanclustering', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Dbscanclustering finished')
            return result
        except Exception as error:
            logger.error("An error occured in Dbscanclustering")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def countpointsinpolygon(polygons: QgsVectorLayer, points: QgsVectorLayer, weight : str, fieldname: str):
        """
        Takes a point and a polygon layer and counts the number of points from the point layer in each of the polygons of the polygon layer.
        A new polygon layer is generated, with the exact same content as the input polygon layer, but containing an additional field with the points count corresponding to each polygon.

        Args:
            polygons (QgsVectorLayer): Polygon layer whose features are associated with the count of points they contain
            points (QgsVectorLayer): Point layer with features to count
            weight (string): A field from the point layer. The count generated will be the sum of the weight field of the points contained by the polygon. If the weight field is not numeric, the count will be 0.
            fieldname (string): The name of the field to store the count of points

        Returns:
            layer (QgsVectorLayer): Specification of the output layer.
        """

        logger.info('Conducting point in polygon')
        try:
            if isinstance(weight, int):
                value = weight
            else:
                value = 0

            parameters = {
                'POLYGONS': polygons,
                'POINTS': points,
                'WEIGHT': value,
                'FIELD' : fieldname,
                'OUTPUT': 'memory:output_from_countpointsinpolygon'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:Countpointsinpolygon', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Promote to multipart finished')
            return result
        except Exception as error:
            logger.error("An error occured in Countpointsinpolygon")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()  

    def promoteToMultipart(layer: QgsVectorLayer):
        """
        Generates a vectorlayer in which all geometries are multipart.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer that is used as input.

        Returns:
            layer (QgsVectorLayer): The QgsVectorLayer containing multi geometries.
        """

        logger.info('Collecting geometries')
        try:
            parameters = {
                'INPUT': layer,
                'OUTPUT': 'memory:multipart'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:promotetomulti', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Promote to multipart finished')
            return result
        except Exception as error:
            logger.error("An error occured in promoteToMultipart")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def extractByExpression(layer: QgsVectorLayer, expression: str):
        """
        Creates a vector layer from an input layer, containing only matching features.
        The criteria for adding features to the resulting layer is based on a QGIS expression.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
            expression (string): Expression to filter the vector layer

        Returns:
            layer (QgsVectorLayer): The QgsVectorLayer output layer.
        """

        logger.info("Extracting by expression")
        try:
            parameter = {
                'INPUT': layer,
                'EXPRESSION': expression,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:extractbyexpression', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Extractbyexpression  finished")
            return result
        except Exception as error:
            logger.error("An error occured in extractByExpression")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def renameTableField (layer: QgsVectorLayer, field: str, newname: str):
        """
        Renames an existing field from a vector layer.  
        The original layer is not modified. A new layer is generated where the attribute table contains the renamed field.
        QGIS processing algorithem: native:renametablefield

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            field (string): The field that is to be renamed
            newname (string): New name for the field

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Renaming field")
        try:
            parameter = {
                'INPUT': layer,
                'FIELD': field,
                'NEW_NAME': newname,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:renametablefield', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("renameTableField  finished")
            return result
        except Exception as error:
            logger.error("An error occured in renameTableField")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def timeStamper(layer: QgsVectorLayer, ts_fieldname: str):
        """
        Create an attribute woth current timestamp on features.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            ts_fieldname (string): The name of the new timestamp field

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info(f'Creating timestamp {ts_fieldname} using fieldCalculator')
        newLayer = Worker.Vector.fieldCalculator(layer, ts_fieldname, 5, 0, 0, ' now() ')
        return newLayer

    def fieldCalculator (layer: QgsVectorLayer, fieldname: str, fieldtype: int, fieldlength: int, fieldprecision: int, formula: str):
        """
        Scripting the field calcualtor
        You can use all the supported expressions and functions.
        The original layer is not modified. A new layer is generated where the attribute table contains the calucalted field
        QGIS processing algorithem: native:fieldcalculator

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            fieldname (string): The name of the new calcualted field
            fieldtype (integer): Type of the field,  Default: 0  (0 — Float, 1 — Integer, 2 — String, 3 — Date)
            fieldlength (integer): Lenght of the field, Default: 10.
            fieldprecision (integer): Precision of the field, Default: 3.
            formula (string): The expression that populates the values of the field.

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Calculating field")
        try:
            parameter = {
                'INPUT': layer,
                'FIELD_NAME': fieldname,
                'FIELD_TYPE': fieldtype,
                'FIELD_LENGTH': fieldlength,
                'FIELD_PRECISION': fieldprecision,
                'FORMULA': formula,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:fieldcalculator', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("fieldCalculator  finished")
            return result
        except Exception as error:
            logger.error("An error occured in fieldCalculator")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def deleteColumns (layer: QgsVectorLayer, columns: list):
        """
        Takes a vector layer and generates a new one that has the same features but without the selected columns.

        Args:
            layer (QgsVectorLayer): Input vector layer to drop field(s) from
            columns (list of strings): The field(s) to drop

        Returns:
            layer (QgsVectorLayer): The QgsVectorLayer output layer.
        """

        logger.info("deleting fields")

        try:
            parameter = {
                'INPUT': layer,
                'COLUMN':columns,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:deletecolumn', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("deleteColumns  finished")
            return result
        except Exception as error:
            logger.error("An error occured in deleteColumns")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def addAutoIncrementalField(layer: QgsVectorLayer, fieldname: str, start: int):
        """
        Adds a new integer field to a vector layer, with a sequential value for each feature.
        This field can be used as a unique ID for features in the layer. The new attribute is not added to the input layer but a new layer is generated instead.
        The initial starting value for the incremental series can be specified. Optionally, the incremental series can be based on grouping 
        fields and a sort order for features can also be specified.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
            fieldname (string): Name of the field with autoincremental values.
            start (integer): Choose the initial number of the incremental count, Default: 0.

        Returns
            layer (QgsVectorLayer): The QgsVectorLayer output layer.
        """

        logger.info("Adding incremental field")
        try:
            parameter = {
                'INPUT': layer,
                'FIELD_NAME': fieldname,
                'START':start,
                'MODULUS':0,
                'GROUP_FIELDS':[],
                'SORT_EXPRESSION':'',
                'SORT_ASCENDING':True,
                'SORT_NULLS_FIRST':False,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:addautoincrementalfield', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("addAutoIncrementalField  finished")
            return result
        except Exception as error:
            logger.error("An error occured in addAutoIncrementalField")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def spatialindex(layer: QgsVectorLayer):
        """
        Creates an index to speed up access to the features in a layer based on their spatial location.
        Support for spatial index creation is dependent on the layer's data provider.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Crating spatial index on " + layer)
        try:
            parameter = {
                'INPUT': layer,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:createspatialindex', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("createspatialindex  finished")
            return result
        except Exception as error:
            logger.error("An error occured in createspatialindex")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def clip(layer: QgsVectorLayer, overlay: str):
        """
        Clips a vector layer using the features of an additional polygon layer.
        Only the parts of the features in the input layer that fall within the polygons of 
        the overlay layer will be added to the resulting layer.

        Args:
            layer (QgsVectorLayer): Layer containing the features to be clipped
            overlay (QgsVectorLayer): Layer containing the clipping features

        Returns:
            layer (QgsVectorLayer): Layer to contain the features from the input layer that are inside the overlay (clipping) layer
        """

        logger.info("Clipping layers")
        try:
            parameter = {
                'INPUT': layer,
                'OVERLAY': overlay,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:clip', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Clip  finished")
            return result
        except Exception as error:
            logger.error("An error occured in Clip")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def joinByLocation(layer: QgsVectorLayer, predicate: int, join: str, join_fields: list, method: int, discard_nomatching: bool, prefix: str):
        """
        Takes an input vector layer and creates a new vector layer that is an extended version of
        the input one, with additional attributes in its attribute table.
        The additional attributes and their values are taken from a second vector layer.
        A spatial criteria is applied to select the values from the second layer that are added to each 
        feature from the first layer.

        Args:
            layer (QgsVectorLayer): Input vector layer. The output layer will consist of the features of this layer with attributes from matching features in the second layer.
            predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
            join (QgsVectorLayer): The join layer. Features of this vector layer will add their attributes to the source layer attribute table if they satisfy the spatial relationship.
            join_fields (list of strings): Select the specific fields you want to add from the join layer. By default all the fields are added.
            method (integer): The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one) 2 — Take attributes of the feature with largest overlap only (one-to-one)
            discard_nomatching (boolean): Remove from the output the input layer’s features which could not be joined
            prefix (string): Add a prefix to joined fields in order to easily identify them and avoid field name collision

        Returns:
            layer (QgsVectorLayer): the output vector layer for the join.
        """

        logger.info("Clipping layers")
        try:
            parameter = {
                'INPUT': layer,
                'PREDICATE':predicate,
                'JOIN':join,
                'JOIN_FIELDS':join_fields,
                'METHOD':method,
                'DISCARD_NONMATCHING':discard_nomatching,
                'PREFIX':prefix,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:joinattributesbylocation', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("joinByLocation finished")
            return result
        except Exception as error:
            logger.error("An error occured in joinByLocation")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def extractByLocation(layer: QgsVectorLayer, predicate: int, intersect: str):
        """_summary_

        Args:
            layer (QgsVectorLayer): Input vector layer. 
            predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
            intersect (QgsVectorLayer): Intersection vector layer

        Returns:
            layer (QgsVectorLayer): the output vector layer for the join.
        """

        logger.info("Extracting by location")
        try:
            parameter = {
                'INPUT': layer,
                'PREDICATE':predicate,
                'INTERSECT':intersect,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:extractbylocation', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("extractByLocation finished")
            return result
        except Exception as error:
            logger.error("An error occured in extractByLocation")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def randomExtract(layer: QgsVectorLayer, method: int, number: int):
        """
        Takes a vector layer and generates a new one that contains only a subset of the features in the input layer.
        The subset is defined randomly, based on feature IDs, using a percentage or count value to define 
        the total number of features in the subset.

        Args:
            layer (QgsVectorLayer): Input vector layer. 
            method (integer): Random selection method. One of: 0 — Number of selected features 1 — Percentage of selected features
            number (integer): Number or percentage of features to select

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Extracting random features")
        try:
            parameter = {
                'INPUT': layer,
                'METHOD':method,
                'NUMBER':number,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:randomextract', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("randomExtract finished")
            return result
        except Exception as error:
            logger.error("An error occured in randomExtract")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def difference(layer: QgsVectorLayer, overlay: QgsVectorLayer):
        """
        Extracts features from the input layer that don’t fall within the boundaries of the overlay layer.
        Input layer features that partially overlap the overlay layer feature(s) are split along the 
        boundary of those feature(s.

        Args:
            layer (QgsVectorLayer): Layer to extract (parts of) features from.
            overlay (QgsVectorLayer): Layer containing the geometries that will be subtracted from the iniput layer geometries

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Finding differences")
        try:
            parameter = {
                'INPUT': layer,
                'OVERLAY': overlay,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:difference', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Difference  finished")
            return result
        except Exception as error:
            logger.error("An error occured in Difference")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def reproject(layer: QgsVectorLayer, targetEPSG: int):
        """
        Reprojects a vector layer in a different CRS.
        The reprojected layer will have the same features and attributes of the input layer.
        QGIS processing algorithem: native:reprojectlayer.

class Vector:
    '''
    A Worker subclass that contains methods to transform vector data or their attributes.
    '''

    def attributeindex(layer: QgsVectorLayer, field: str):

        Creates an index to speed up queries made against a field in a table.
        Support for index creation is dependent on the layers data provider and the field type.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            field (string): The field to base the index on

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Crating attribute index on " + layer + " on filed " + field)
        try:
            parameter = {
                'INPUT': field,
                'FIELD': field,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:createattributeindex', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("createattributeindex  finished")
            return result
        except Exception as error:
            logger.error("An error occured in createattributeindex")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def addxyfieldstolayer(layer: QgsVectorLayer, crs: str):
        """
        Adds X and Y (or latitude/longitude) fields to a point layer. The X/Y fields can be calculated in a different CRS to the layer (e.g. creating latitude/longitude fields for a layer in a projected CRS).

        Args:
            layer (QgsVectorLayer): The input layer.
            crs (string): Coordinate reference system to use for the generated x and y fields.

        Returns:
            layer (QgsVectorLayer): Specify the output layer.
        """

        logger.info(f"Adding X/Y fields to {layer}" )
        try:
            parameter = {
                'INPUT': layer,
                'CRS': crs,
                'OUTPUT': 'memory:output_from_addxyfieldstolayer'
            }
            result = processing.run('native:addxyfieldstolayer', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("addxyfieldstolayer  finished")
            return result
        except Exception as error:
            logger.error("An error occured in addxyfieldstolayer")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def convexhull(layer: QgsVectorLayer):
        """
        Calculates the convex hull for each feature in an input layer.

        Args:
            layer (QgsVectorLayer): Input vector layer

        Returns:
            layer (QgsVectorLayer): Specify the output vector layer.
        """

        logger.info(f" Calculating convexhull for layer {layer}")
        try:
            parameter = {
                'INPUT': layer,
                'OUTPUT': 'memory:output_from_convexhull'
            }
            result = processing.run('native:convexhull', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("convexhull  finished")
            return result
        except Exception as error:
            logger.error("An error occured in convexhull")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def concavehull(inputlayer:QgsVectorLayer, alpha: float, holes: bool, multigeom: bool ):
        """
        Computes the concave hull of the features from an input point layer.

        Args:
            inputlayer (QgsVectorLayer): Input point vector layer
            alpha (float): Number from 0 (maximum concave hull) to 1 (convex hull).
            holes (boolean): Choose whether to allow holes in the final concave hull
            multigeom (boolean): Check if you want to have singlepart geometries instead of multipart ones.

        Returns:
            layer (QgsVectorLayer): Specify the output vector layer
        """

        logger.info('calcualting concavehull')
        try:
            parameters = {
                'INPUT': inputlayer,
                'ALPHA' : alpha,
                'HOLES' : holes,
                'NO_MULTIGEOMETRY' : multigeom,
                'OUTPUT': 'memory:output_from_concavehull'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:concavehull', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('concavehull finished')
            return result
        except Exception as error:
            logger.error("An error occured in concavehull")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()            

    def extractvertices(inputlayer:QgsVectorLayer):
        """
        Takes a vector layer and generates a point layer with points representing the vertices in the input geometries.
        The attributes associated to each point are the same ones associated to the feature that the vertex belongs to.
        Additional fields are added to the vertices indicating the vertex index (beginning at 0), the feature’s part and its index within the part
        (as well as its ring for polygons), distance along original geometry and bisector angle of vertex for original geometry.

        Args:
            inputlayer (QgsVectorLayer): Input vector layer

        Returns:
            layer (QgsVectorLayer): Specify the output vector layer
        """

        logger.info('Extracting vertices')
        try:
            parameters = {
                'INPUT': inputlayer,
                'OUTPUT': 'memory:output_from_extractvertices'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:extractvertices', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('extractvertices finished')
            return result
        except Exception as error:
            logger.error("An error occured in extractvertices")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()    

    def multiringconstantbuffer(inputlayer:QgsVectorLayer, rings: int, distance : str):
        """
        Computes multi-ring (donut) buffer for the features of the input layer, using a fixed or dynamic distance and number of rings.

        Args:
            inputlayer (QgsVectorLayer): Input vector layer
            rings (integer): The number of rings. It can be a unique value (same number of rings for all the features) or it can be taken from features data (the number of rings depends on feature values).
            distance (string): Distance between the rings. It can be a unique value (same distance for all the features) or it can be taken from features data (a field in the input data layer).

        Returns:
            layer (QgsVectorLayer): Specify the output polygon vector layer
        """

        logger.info('Creating multiringconstantbuffer')
        try:
            dist = float(distance)
            logger.info('Using distance value')
        except:
            dist = QgsProperty.fromExpression(f'"{distance}"')
            logger.info('Using distance from field')

        try:
            parameters = {
                'INPUT': inputlayer,
                'RINGS': rings,
                'DISTANCE': distance,
                'OUTPUT': 'memory:output_from_multiringconstantbuffer'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:multiringconstantbuffer', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('multiringconstantbuffer finished')
            return result
        except Exception as error:
            logger.error("An error occured in multiringconstantbuffer")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed() 

    def poleofinaccessibility(inputlayer:QgsVectorLayer, tolerance: int):
        """
        Calculates the pole of inaccessibility for a polygon layer, which is the most distant internal point from the boundary of the surface. 
        This algorithm uses the ‘polylabel’ algorithm (Vladimir Agafonkin, 2016), which is an iterative approach guaranteed to find the true pole of inaccessibility within
        a specified tolerance. A more precise tolerance (lower value) requires more iterations and will take longer to calculate. 
        The distance from the calculated pole to the polygon boundary will be stored as a new attribute in the output layer.

        Args:
            inputlayer (QgsVectorLayer): Input vector layer
            tolerance (integer): Set the tolerance for the calculation. Default 1

        Returns:
            layer (QgsVectorLayer): Specify the output polygon vector layer.
        """

        logger.info('calcualting poleofinaccessibility')
        try:
            parameters = {
                'INPUT': inputlayer,
                'TOLERANCE' : tolerance,
                'OUTPUT': 'memory:output_from_poleofinaccessibility'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:poleofinaccessibility', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('poleofinaccessibility finished')
            return result
        except Exception as error:
            logger.error("An error occured in poleofinaccessibility")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()


    def symmetricaldifference(inputlayer: QgsVectorLayer, overlay_layer: QgsVectorLayer):
        """
        Creates a layer containing features from both the input and overlay layers but with the overlapping areas between the two layers removed.
        The attribute table of the symmetrical difference layer contains attributes and fields from both the input and overlay layers.

        Args:
            inputlayer (QgsVectorLayer): First layer to extract (parts of) features from.
            overlay_layer (QgsVectorLayer): Second layer to extract (parts of) features from. Ideally the geometry type should be the same as input layer.

        Returns:
            layer (QgsVectorLayer): Specify the layer to contain (the parts of) the features from the input and overlay layers that do not overlap features from the other layer
        """

        logger.info('calcualting symetrical difference')
        try:
            parameters = {
                'INPUT': inputlayer,
                'OVERLAY' : overlay_layer,
                'OUTPUT': 'memory:output_from_symmetricaldifference'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:symmetricaldifference', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Symmetricaldifference finished')
            return result
        except Exception as error:
            logger.error("An error occured in symmetricaldifference")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def lineintersections(inputlayer: QgsVectorLayer, split_layer: QgsVectorLayer, input_fields: list, intersect_fields: list):
        """
        Splits the lines or polygons in one layer using the lines or polygon rings in another layer to define the breaking points. Intersection between geometries in both layers are considered as split points.
        Output will contain multi geometries for split features.

        Args:
            inputlayer (QgsVectorLayer): Input line layer.
            split_layer (QgsVectorLayer): Layer to use to find line intersections.
            input_fields (list of strings): Field(s) of the input layer to keep in the output. If no fields are chosen all fields are taken.
            intersect_fields (list of strings): Field(s) of the intersect layer to keep in the output. If no fields are chosen all fields are taken. Duplicate field names will be appended a count suffix to avoid collision

        Returns:
            layer (QgsVectorLayer): Specify the layer to contain the intersection points of the lines from the input and overlay layers.
        """

        logger.info('Performing line intersections')
        try:
            parameters = {
                'INPUT': inputlayer,
                'INTERSECT': split_layer,
                'INPUT_FIELDS' : input_fields, 
                'INTERSECT_FIELDS' : intersect_fields,
                'OUTPUT': 'memory:output_from_lineintersections'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:lineintersections', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Lineintersections finished')
            return result
        except Exception as error:
            logger.error("An error occured in Lineintersections")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def kmeansclustering(inputlayer: QgsVectorLayer, clusters: int):
        """
        Calculates the 2D distance based k-means cluster number for each input feature.
        K-means clustering aims to partition the features into k clusters in which each feature belongs to the cluster with the nearest mean. The mean point is represented by the barycenter of the clustered features.
        If input geometries are lines or polygons, the clustering is based on the centroid of the feature.

        Args:
            inputlayer (QgsVectorLayer): Layer to analyze
            clusters (integer): Number of clusters to create with the features

        Returns:
            layer (QgsVectorLayer): Specify the output vector layer for generated the clusters.
        """

        logger.info('Calculating clusters')
        try:
            parameters = {
                'INPUT': inputlayer,
                'CLUSTERS' : clusters,
                'OUTPUT': 'memory:output_from_kmeansclustering'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:kmeansclustering', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Kmeansclustering finished')
            return result
        except Exception as error:
            logger.error("An error occured in Kmeansclustering")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def dbscanclustering(inputlayer: QgsVectorLayer, min_clusters: int, max_dist: int ):
        """
        Clusters point features based on a 2D implementation of Density-based spatial clustering of applications with noise (DBSCAN) algorithm.
        The algorithm requires two parameters, a minimum cluster size, and the maximum distance allowed between clustered points.

        Args:
            inputlayer (QgsVectorLayer): Layer to analyze
            min_clusters (integer): Minimum number of features to generate a cluster
            max_dist (integer): Distance beyond which two features can not belong to the same cluster (eps)

        Returns:
            layer (QgsVectorLayer): Specify the vector layer for the result of the clustering.
        """

        logger.info('Performing DBScan clustering')
        try:
            parameters = {
                'INPUT': inputlayer,
                'MIN_SIZE' : min_clusters,
                'EPS': max_dist,
                'OUTPUT': 'memory:output_from_dbscanclustering'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:dbscanclustering', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Dbscanclustering finished')
            return result
        except Exception as error:
            logger.error("An error occured in Dbscanclustering")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def countpointsinpolygon(polygons: QgsVectorLayer, points: QgsVectorLayer, weight : str, fieldname: str):
        """
        Takes a point and a polygon layer and counts the number of points from the point layer in each of the polygons of the polygon layer.
        A new polygon layer is generated, with the exact same content as the input polygon layer, but containing an additional field with the points count corresponding to each polygon.

        Args:
            polygons (QgsVectorLayer): Polygon layer whose features are associated with the count of points they contain
            points (QgsVectorLayer): Point layer with features to count
            weight (string): A field from the point layer. The count generated will be the sum of the weight field of the points contained by the polygon. If the weight field is not numeric, the count will be 0.
            fieldname (string): The name of the field to store the count of points

        Returns:
            layer (QgsVectorLayer): Specification of the output layer.
        """

        logger.info('Conducting point in polygon')
        try:
            if isinstance(weight, int):
                value = weight
            else:
                value = 0

            parameters = {
                'POLYGONS': polygons,
                'POINTS': points,
                'WEIGHT': value,
                'FIELD' : fieldname,
                'OUTPUT': 'memory:output_from_countpointsinpolygon'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:Countpointsinpolygon', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Promote to multipart finished')
            return result
        except Exception as error:
            logger.error("An error occured in Countpointsinpolygon")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()  

    def promoteToMultipart(layer: QgsVectorLayer):
        """
        Generates a vectorlayer in which all geometries are multipart.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer that is used as input.

        Returns:
            layer (QgsVectorLayer): The QgsVectorLayer containing multi geometries.
        """

        logger.info('Collecting geometries')
        try:
            parameters = {
                'INPUT': layer,
                'OUTPUT': 'memory:multipart'
            }
            logger.info(f'Parameters: {str(parameters)}')
            result = processing.run('native:promotetomulti', parameters, feedback=Worker.progress)['OUTPUT']
            logger.info('Promote to multipart finished')
            return result
        except Exception as error:
            logger.error("An error occured in promoteToMultipart")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def extractByExpression(layer: QgsVectorLayer, expression: str):
        """
        Creates a vector layer from an input layer, containing only matching features.
        The criteria for adding features to the resulting layer is based on a QGIS expression.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
            expression (string): Expression to filter the vector layer

        Returns:
            layer (QgsVectorLayer): The QgsVectorLayer output layer.
        """

        logger.info("Extracting by expression")
        try:
            parameter = {
                'INPUT': layer,
                'EXPRESSION': expression,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:extractbyexpression', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Extractbyexpression  finished")
            return result
        except Exception as error:
            logger.error("An error occured in extractByExpression")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def renameTableField (layer: QgsVectorLayer, field: str, newname: str):
        """
        Renames an existing field from a vector layer.  
        The original layer is not modified. A new layer is generated where the attribute table contains the renamed field.
        QGIS processing algorithem: native:renametablefield

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            field (string): The field that is to be renamed
            newname (string): New name for the field

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Renaming field")
        try:
            parameter = {
                'INPUT': layer,
                'FIELD': field,
                'NEW_NAME': newname,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:renametablefield', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("renameTableField  finished")
            return result
        except Exception as error:
            logger.error("An error occured in renameTableField")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def timeStamper(layer: QgsVectorLayer, ts_fieldname: str):
        """
        Create an attribute woth current timestamp on features.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            ts_fieldname (string): The name of the new timestamp field

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info(f'Creating timestamp {ts_fieldname} using fieldCalculator')
        newLayer = Worker.fieldCalculator(layer, ts_fieldname, 5, 0, 0, ' now() ')
        return newLayer

    def fieldCalculator (layer: QgsVectorLayer, fieldname: str, fieldtype: int, fieldlength: int, fieldprecision: int, formula: str):
        """
        Scripting the field calcualtor
        You can use all the supported expressions and functions.
        The original layer is not modified. A new layer is generated where the attribute table contains the calucalted field
        QGIS processing algorithem: native:fieldcalculator

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            fieldname (string): The name of the new calcualted field
            fieldtype (integer): Type of the field,  Default: 0  (0 — Float, 1 — Integer, 2 — String, 3 — Date)
            fieldlength (integer): Lenght of the field, Default: 10.
            fieldprecision (integer): Precision of the field, Default: 3.
            formula (string): The expression that populates the values of the field.

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Calculating field")
        try:
            parameter = {
                'INPUT': layer,
                'FIELD_NAME': fieldname,
                'FIELD_TYPE': fieldtype,
                'FIELD_LENGTH': fieldlength,
                'FIELD_PRECISION': fieldprecision,
                'FORMULA': formula,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:fieldcalculator', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("fieldCalculator  finished")
            return result
        except Exception as error:
            logger.error("An error occured in fieldCalculator")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def deleteColumns (layer: QgsVectorLayer, columns: list):
        """
        Takes a vector layer and generates a new one that has the same features but without the selected columns.

        Args:
            layer (QgsVectorLayer): Input vector layer to drop field(s) from
            columns (list of strings): The field(s) to drop

        Returns:
            layer (QgsVectorLayer): The QgsVectorLayer output layer.
        """

        logger.info("deleting fields")

        try:
            parameter = {
                'INPUT': layer,
                'COLUMN':columns,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:deletecolumn', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("deleteColumns  finished")
            return result
        except Exception as error:
            logger.error("An error occured in deleteColumns")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def addAutoIncrementalField(layer: QgsVectorLayer, fieldname: str, start: int):
        """
        Adds a new integer field to a vector layer, with a sequential value for each feature.
        This field can be used as a unique ID for features in the layer. The new attribute is not added to the input layer but a new layer is generated instead.
        The initial starting value for the incremental series can be specified. Optionally, the incremental series can be based on grouping 
        fields and a sort order for features can also be specified.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
            fieldname (string): Name of the field with autoincremental values.
            start (integer): Choose the initial number of the incremental count, Default: 0.

        Returns
            layer (QgsVectorLayer): The QgsVectorLayer output layer.
        """

        logger.info("Adding incremental field")
        try:
            parameter = {
                'INPUT': layer,
                'FIELD_NAME': fieldname,
                'START':start,
                'MODULUS':0,
                'GROUP_FIELDS':[],
                'SORT_EXPRESSION':'',
                'SORT_ASCENDING':True,
                'SORT_NULLS_FIRST':False,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:addautoincrementalfield', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("addAutoIncrementalField  finished")
            return result
        except Exception as error:
            logger.error("An error occured in addAutoIncrementalField")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def spatialindex(layer: QgsVectorLayer):
        """
        Creates an index to speed up access to the features in a layer based on their spatial location.
        Support for spatial index creation is dependent on the layer's data provider.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Crating spatial index on " + layer)
        try:
            parameter = {
                'INPUT': layer,
                'OUTPUT': 'memory:extracted'
            }
            result = processing.run('native:createspatialindex', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info(f'Parameters: {str(parameter)}')
            logger.info("createspatialindex  finished")
            return result
        except Exception as error:
            logger.error("An error occured in createspatialindex")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def clip(layer: QgsVectorLayer, overlay: str):
        """
        Clips a vector layer using the features of an additional polygon layer.
        Only the parts of the features in the input layer that fall within the polygons of 
        the overlay layer will be added to the resulting layer.

        Args:
            layer (QgsVectorLayer): Layer containing the features to be clipped
            overlay (QgsVectorLayer): Layer containing the clipping features

        Returns:
            layer (QgsVectorLayer): Layer to contain the features from the input layer that are inside the overlay (clipping) layer
        """

        logger.info("Clipping layers")
        try:
            parameter = {
                'INPUT': layer,
                'OVERLAY': overlay,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:clip', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Clip  finished")
            return result
        except Exception as error:
            logger.error("An error occured in Clip")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def joinByLocation(layer: QgsVectorLayer, predicate: int, join: str, join_fields: list, method: int, discard_nomatching: bool, prefix: str):
        """
        Takes an input vector layer and creates a new vector layer that is an extended version of
        the input one, with additional attributes in its attribute table.
        The additional attributes and their values are taken from a second vector layer.
        A spatial criteria is applied to select the values from the second layer that are added to each 
        feature from the first layer.

        Args:
            layer (QgsVectorLayer): Input vector layer. The output layer will consist of the features of this layer with attributes from matching features in the second layer.
            predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
            join (QgsVectorLayer): The join layer. Features of this vector layer will add their attributes to the source layer attribute table if they satisfy the spatial relationship.
            join_fields (list of strings): Select the specific fields you want to add from the join layer. By default all the fields are added.
            method (integer): The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one) 2 — Take attributes of the feature with largest overlap only (one-to-one)
            discard_nomatching (boolean): Remove from the output the input layer’s features which could not be joined
            prefix (string): Add a prefix to joined fields in order to easily identify them and avoid field name collision

        Returns:
            layer (QgsVectorLayer): the output vector layer for the join.
        """

        logger.info("Clipping layers")
        try:
            parameter = {
                'INPUT': layer,
                'PREDICATE':predicate,
                'JOIN':join,
                'JOIN_FIELDS':join_fields,
                'METHOD':method,
                'DISCARD_NONMATCHING':discard_nomatching,
                'PREFIX':prefix,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:joinattributesbylocation', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("joinByLocation finished")
            return result
        except Exception as error:
            logger.error("An error occured in joinByLocation")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def extractByLocation(layer: QgsVectorLayer, predicate: int, intersect: str):
        """_summary_

        Args:
            layer (QgsVectorLayer): Input vector layer. 
            predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
            intersect (QgsVectorLayer): Intersection vector layer

        Returns:
            layer (QgsVectorLayer): the output vector layer for the join.
        """

        logger.info("Extracting by location")
        try:
            parameter = {
                'INPUT': layer,
                'PREDICATE':predicate,
                'INTERSECT':intersect,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:extractbylocation', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("extractByLocation finished")
            return result
        except Exception as error:
            logger.error("An error occured in extractByLocation")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def randomExtract(layer: QgsVectorLayer, method: int, number: int):
        """
        Takes a vector layer and generates a new one that contains only a subset of the features in the input layer.
        The subset is defined randomly, based on feature IDs, using a percentage or count value to define 
        the total number of features in the subset.

        Args:
            layer (QgsVectorLayer): Input vector layer. 
            method (integer): Random selection method. One of: 0 — Number of selected features 1 — Percentage of selected features
            number (integer): Number or percentage of features to select

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Extracting random features")
        try:
            parameter = {
                'INPUT': layer,
                'METHOD':method,
                'NUMBER':number,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:randomextract', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("randomExtract finished")
            return result
        except Exception as error:
            logger.error("An error occured in randomExtract")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def difference(layer: QgsVectorLayer, overlay: QgsVectorLayer):
        """
        Extracts features from the input layer that don’t fall within the boundaries of the overlay layer.
        Input layer features that partially overlap the overlay layer feature(s) are split along the 
        boundary of those feature(s.

        Args:
            layer (QgsVectorLayer): Layer to extract (parts of) features from.
            overlay (QgsVectorLayer): Layer containing the geometries that will be subtracted from the iniput layer geometries

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Finding differences")
        try:
            parameter = {
                'INPUT': layer,
                'OVERLAY': overlay,
                'OUTPUT': 'memory:extracted'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:difference', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Difference  finished")
            return result
        except Exception as error:
            logger.error("An error occured in Difference")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def reproject(layer: QgsVectorLayer, targetEPSG: int):
        """
        Reprojects a vector layer in a different CRS.
        The reprojected layer will have the same features and attributes of the input layer.
        QGIS processing algorithem: native:reprojectlayer.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            targetEPSG (integer): The EPSG code og the target coordinate system.

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Running reporjector V2")
        if layerHasFeatures(layer):
            logger.info("Processing " + str(layer.featureCount()) +" features")
        try:
            parameter = {
                'INPUT': layer,
                'TARGET_CRS': QgsCoordinateReferenceSystem(targetEPSG),
                'OUTPUT': 'memory:Reprojected'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:reprojectlayer', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Reproject finished")
            return result
        except Exception as error:
            logger.error("An error occured reprojectiong layer")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def simplify(layer: QgsVectorLayer, method: int, tolerance:int):
            """
            Simplifies the geometries in a line or polygon layer. 
            It creates a new layer with the same features as the ones in the input layer, but with geometries containing a lower number of vertices.
            QGIS processing algorithem: native:simplifygeometries.

            Args:
                layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
                method (integer): Simplification method. One of: 0 — Distance (Douglas-Peucker), 1 — Snap to grid, 2 — Area (Visvalingam)
                tolerance (integer): Threshold tolerance (in units of the layer): if the distance between two nodes is smaller than the tolerance value, the segment will be simplified and vertices will be removed.

            Returns:
                layer (QgsVectorLayer): The result output from the algorithem
            """

            logger.info("Running simplify")
            if layerHasFeatures(layer):
                logger.info("Processing " + str(layer.featureCount()) +" features")
            try:
                parameter = {
                    'INPUT': layer,
                    'METHOD':method,
                    'TOLERANCE':tolerance,
                    'OUTPUT': 'memory:simplify'
                }
                logger.info(f'Parameters: {str(parameter)}')
                result = processing.run('native:simplifygeometries', parameter, feedback=Worker.progress)['OUTPUT']
                logger.info("Simplifygeometries finished")
                return result
            except Exception as error:
                logger.error("An error occured in simplifygeometries")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                sys.exit()

    def forceRHR(layer: QgsVectorLayer):
        """
        Forces polygon geometries to respect the Right-Hand-Rule, in which the area that is bounded
        by a polygon is to the right of the boundary. 
        In particular, the exterior ring is oriented in a clockwise direction and any interior
        rings in a counter-clockwise direction.
        QGIS processing algorithem: native:forcerhr

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem

        Takes a vector layer and selects a subset of its features. No new layer is generated by this algorithm.
        The subset is defined randomly, based on feature IDs, using a percentage or count value to define the 
        total number of features in the subset.

        """

        logger.info("Running force right-hand rule")
        if layerHasFeatures(layer):
            logger.info("Processing " + str(layer.featureCount()) +" features")
        try:
            parameter = {
                'INPUT': layer,
                'OUTPUT': 'memory:forced'
            }
            result = processing.run('native:forcerhr', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("forceRHR finished")
            return result
        except Exception as error:
            logger.error("An error occured in forceRHR")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def join_by_attribute(layer1: QgsVectorLayer, layer1_field:str, layer2: QgsVectorLayer, layer2_field: str, fields_to_copy: list, method:int, discard: bool, prefix:str):
        """
        Takes an input vector layer and creates a new vector layer that is an extended version of the input one, 
        with additional attributes in its attribute table.
        The additional attributes and their values are taken from a second vector layer. An attribute is selected in each of them 
        to define the join criteria.
        QGIS processing algorithem: native:joinattributestable.

        Args:
            layer1 (QgsVectorLayer): The 1. QgsVectorLayer input for the algorithem
            layer1_field (string): Field of the source layer to use for the join
            layer2 (QgsVectorLayer): The 2. QgsVectorLayer input for the algorithem
            layer2_field (string): Field of the source layer to use for the join
            fields_to_copy (list of strings): Select the specific fields you want to add. By default all the fields are added. Default []
            method (integer): The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one)
            discard (boolean): Check if you don’t want to keep the features that could not be joined
            prefix (string): Add a prefix to joined fields in order to easily identify them and avoid field name collision

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Joining features features")
        if layerHasFeatures(layer1):
            logger.info("Processing " + str(layer1.featureCount()) +" features")
        try:
            parameter = {
                'INPUT':layer1,
                'FIELD':layer1_field,
                'INPUT_2':layer2,
                'FIELD_2':layer2_field,
                'FIELDS_TO_COPY':fields_to_copy,
                'METHOD':method,
                'DISCARD_NONMATCHING':discard,
                'PREFIX':prefix,
                'OUTPUT': 'memory:joined'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:joinattributestable', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Joinattributestable finished")
            if layerHasFeatures(result):
                logger.info("Returning " + str(result.featureCount()) +" features")
            return result
        except Exception as error:
            logger.error("An error occured in joinattributestable")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def dissolveFeatures(layer: QgsVectorLayer, fieldList: list, disjoined: bool):
        """
        Takes a vector layer and combines its features into new features. 
        One or more attributes can be specified to dissolve features belonging to the same class 
        (having the same value for the specified attributes), alternatively all features can be dissolved to a single feature.
        All output geometries will be converted to multi geometries. 
        QGIS processing algorithem: native:dissolve.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            fieldList (list of strings): List of fields to dissolve on. Default []
            disjoined (boolean): Keep disjoint features separate ? Default: False

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem

        """
        logger.info("Dissolving features")
        if layerHasFeatures(layer):
            logger.info("Processing " + str(layer.featureCount()) +" features")
        try:
            parameter = {
                'INPUT': layer,
                'FIELD' : fieldList,
                'SEPARATE_DISJOINT' : False,
                'OUTPUT': 'memory:dissolved'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:dissolve', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("DissolveFeatures finished")
            if layerHasFeatures(result):
                logger.info("Returning " + str(result.featureCount()) +" features")
            return result
        except Exception as error:
            logger.error("An error occured in dissolveFeatures")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def bufferLayer(layer: QgsVectorLayer, distance: int, segements: int, endcapStyle: int, joinStyle: int, miterLimit: int, dissolve: bool):
        """
        Computes a buffer area for all the features in an input layer, using a fixed or data defined distance.
        It is possible to use a negative distance for polygon input layers.
        In this case the buffer will result in a smaller polygon (setback).
        QGIS processing algorithem: native:buffer

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            distance (integer): The buffer distance. Default: 10.0
            segements (integer): Number og segments. Default: 5
            endcapStyle (integer): Controls how line endings are handled in the buffer. Default: 0 (One of: 0 — Round, 1 — Flat, 2 — Square)
            joinStyle (integer): Specifies whether round, miter or beveled joins should be used when offsetting corners in a line. Default: 0 (Options are: 0 — Round, 1 — Miter, 2 — Bevel)
            miterLimit (integer): Sets the maximum distance from the offset geometry to use when creating a mitered join as a factor of the offset distance Default: 0, Minimum: 1
            dissolve (boolean): Dissolve the final buffer. Default: false.

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Creating buffer layer")
        if layerHasFeatures(layer):
            logger.info("Processing " + str(layer.featureCount()) +" features")
        try:
            parameter = {
                'INPUT': layer,
                'DISTANCE': distance,
                'SEGMENTS': segements,
                'END_CAP_STYLE': endcapStyle,
                'JOIN_STYLE': joinStyle,
                'MITER_LIMIT': miterLimit,
                'DISSOLVE': dissolve,
                'OUTPUT': 'memory:buffer'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:buffer', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("BufferLayer finished")
            return result
        except Exception as error:
            logger.error("An error occured in BufferLayer")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def fixGeometry(layer: QgsVectorLayer):
        """
        Attempts to create a valid representation of a given invalid geometry without losing any of the input vertices.
        Already valid geometries are returned without further intervention. Always outputs multi-geometry layer.
        QGIS processing algorithem: native:fixgeometries

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Fixing geometries")
        if layerHasFeatures(layer):
            logger.info("Processing " + str(layer.featureCount()) +" features")
        try:
            parameter = {
                'INPUT': layer,
                'OUTPUT': 'memory:buffer'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:fixgeometries', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("FixGeometry finished")
            return result
        except Exception as error:
            logger.error("An error occured in FixGeometry")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def createCentroids(layer: str):
        """
        Creates a new point layer, with points representing the centroids of the geometries of the input layer.
        The centroid is a single point representing the barycenter (of all parts) of the feature, so it can be outside the feature borders. But can also be a point on each part of the feature.
        The attributes of the points in the output layer are the same as for the original features.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Creating centroids")
        if layerHasFeatures(layer):
            logger.info("Processing " + str(layer.featureCount()) +" features")
        try:
            parameter = {
                'INPUT': layer,
                'ALL_PARTS':False,
                'OUTPUT': 'memory:buffer'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:centroids', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Centroids finished")
            return result
        except Exception as error:
            logger.error("An error occured in createCentroids")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def randomselection(layer: QgsVectorLayer, method: int, number: int):
        """
        Takes a vector layer and selects a subset of its features. No new layer is generated by this algorithm.
        The subset is defined randomly, based on feature IDs, using a percentage or count value to define the 
        total number of features in the subset.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            method (integer): Random selection method. One of: 0 — Number of selected features, 1 — Percentage of selected features
            number (integer): Number or percentage of features to select

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Performing random selection")
        if layerHasFeatures(layer):
            logger.info("Processing " + str(layer.featureCount()) +" features")
        try:
            parameter = {
                'INPUT': layer,
                'METHOD':method,
                'NUMBER':number,
                'OUTPUT': 'memory:buffer'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:randomextract', parameter, feedback=Worker.progress)['OUTPUT']
            if layerHasFeatures(result):
                logger.info("Returning " + str(result.featureCount()) +" features")
            logger.info("randomextract finished")
            return result
        except Exception as error:
            logger.error("An error occured in FixGeometry")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def execute_sql(connection, databasetype, sql_expression, pgdb_name=None, driver=None):
        """
        Execute an SQL query against a database. 
        This can be used to create tables, truncate, build indexes etc.
        The database type must be specified in the 'database' parameter (one of 'Mssql' or 'Postgres')
        The default Mssql driver is 'SQL Server' - if this needs to be overwritten, specify the parameter driver, else leave it empty.
        SQL statments must be trippel double-quoted - prepare the statement in the QGIS sql executor tool for testing. 

        Args:
            connection (string): Name of a database connection from settings.json
            databasetype (string): The database type, one of 'Mssql' or 'Postgres'.
            sql_expression (string): The SQL expression to be executed. Use trippel double-quotes arraound the expression
            pgdb_name (string): Name of postgres database if databasetype is  Postgres. Defaults to None.
            driver (string): Defaults to None. The name of the Mssql driver, if 'SQL Server' is not working.

        Returns:
            Errorcode (integer): Returns 0 if the SQL is executed without errors.

        """

        config = get_config()
        if databasetype in ('Postgres', 'Mssql'):
            logger.info(f'Running SQL executor on {databasetype}' )
        else :
            logger.info(f'Unsupported database: {databasetype}, use one of "Mssql" or "Postgres"' )
            logger.critical("Program terminated" )
            sys.exit()
        try:
            dbconnection = config['DatabaseConnections'][connection]
            if databasetype == 'Mssql':
                import pyodbc 
                if driver == "":
                    mssqldriver = 'SQL Server'
                else :
                    mssqldriver = 'driver'
                cnxn = pyodbc.connect('DRIVER={'+mssqldriver+'};Server='+dbconnection['host']+';Database='+dbconnection['databasename']+';User ID='+dbconnection['user']+';Password='+dbconnection['password'])
                logger.info("Using connection :" + 'DRIVER={'+mssqldriver+'};Server='+dbconnection['host']+';Database='+dbconnection['databasename']+';User ID='+dbconnection['user']+';Password=xxxxxxxx')
                cursor = cnxn.cursor()
                logger.info(f'Query: {sql_expression}' )
                cursor.execute(sql_expression) 
                logger.info("SQL executor finished")
                return 0

            if databasetype == 'Postgres':
                import psycopg2
                connection = psycopg2.connect(user=dbconnection['user'], password=dbconnection['password'], host=dbconnection['host'], port=dbconnection['port'], database=pgdb_name)
                logger.info("Using connection : user="+ dbconnection['user']+", password=xxxxxx, host="+dbconnection['host']+", port="+dbconnection['port']+", database="+pgdb_name )
                cursor = connection.cursor()
                logger.info(f'Query: {sql_expression}' )
                cursor.execute(sql_expression)
                connection.commit()
                cursor.close()
                connection.close()
                logger.info("SQL executor finished")
                return 0

        except Exception as error:
            logger.error("An error occured running SQL executor")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

    def mergeVectorLayers(layers: list, crs: str ):
        """
        Combines multiple vector layers of the same geometry type into a single one.
        The attribute table of the resulting layer will contain the fields from all input layers. 
        If fields with the same name but different types are found then the exported field will be automatically 
        converted into a string type field. New fields storing the original layer name and source are also added.

        Optionally, the destination coordinate reference system (CRS) for the merged layer can be set. If it is 
        not set, the CRS will be taken from the first input layer. All layers will be reprojected to match this CRS.

        Args:
            layer (QgsVectorLayer): The layers that are to be merged into a single layer. Layers should be of the same geometry type.
            CRS (Crs): Choose the CRS for the output layer. If not specified, the CRS of the first input layer is used.

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Performing mergeVectorLayers")
        logger.info(f'Processing {str(len(layers))} layers')
        try:
            parameter = {
                'LAYERS': layers,
                'CRS':crs,
                'OUTPUT': 'memory:buffer'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:mergevectorlayers', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Returning " + str(result.featureCount()) +" features")
            logger.info("mergeVectorLayers finished")
            return result
        except Exception as error:
            logger.error("An error occured in mergeVectorLayers")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()

    def delete_geopacakge_layers(geopackage: str, layernames: list):
        """
        Deletes one or more tables from a geopackage

        Args:
            geopackage (string): The full path for the geopackage file
            layernames (list of strings): List of layernames to be deleted
        """

        logger.info("Performing delete_geopacakge_layer")
        logger.info(f"Deleting layers {layernames}")

        if os.path.isfile(geopackage):
            try:
                for layer in layernames:
                    logger.info(f"Deleting layer {layer}")
                    parameter = {'DATABASE':'{0}|layername={1}'.format(geopackage, layer),
                    'SQL':'drop table {0}'.format(layer)}
                    logger.info(f'Parameters: {str(parameter)}')
                    processing.run("native:spatialiteexecutesql", parameter )
                    logger.info(f"Layer deleted")
                logger.info(f"Finished deleting layers")


            except Exception as error:
                logger.error("An error occured in delete_geopacakge_layer")
                logger.error(f'{type(error).__name__}{str(error)}')
                logger.critical("Program terminated" )
                script_failed()
        else:    
            pass

    def assign_projection(layer: QgsVectorLayer, targetEPSG: int):
        """
        Assign a new projection on a layer. The returned layer is precisely the same layer but assigned a new CRS.

        Args:
        layer : (QgsVectorLayer)Q The layer to be assigned a new CRS.
        targetEPSG (integer): The EPSG code og the target coordinate system.

        Returns:
            layer (QgsVectorLayer): Layer with the new projection assigned
        """

        logger.info(f'Assigning CRS EPSG:{targetEPSG} to {layer.name()}')
        try:
            parameter = {
                'INPUT': layer,
                'CRS': QgsCoordinateReferenceSystem(targetEPSG),
                'OUTPUT': 'TEMPORARY_OUTPUT'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:assignprojection', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info('Assigning projection finished')
            return result
        except Exception as error:
            logger.error("An error occured assigning a new crs to layer")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

addAutoIncrementalField(layer, fieldname, start)

Adds a new integer field to a vector layer, with a sequential value for each feature. This field can be used as a unique ID for features in the layer. The new attribute is not added to the input layer but a new layer is generated instead. The initial starting value for the incremental series can be specified. Optionally, the incremental series can be based on grouping fields and a sort order for features can also be specified.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer that is used as input.

required
fieldname string

Name of the field with autoincremental values.

required
start integer

Choose the initial number of the incremental count, Default: 0.

required

Returns layer (QgsVectorLayer): The QgsVectorLayer output layer.

Source code in python\engine\workers.py
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
def addAutoIncrementalField(layer: QgsVectorLayer, fieldname: str, start: int):
    """
    Adds a new integer field to a vector layer, with a sequential value for each feature.
    This field can be used as a unique ID for features in the layer. The new attribute is not added to the input layer but a new layer is generated instead.
    The initial starting value for the incremental series can be specified. Optionally, the incremental series can be based on grouping 
    fields and a sort order for features can also be specified.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
        fieldname (string): Name of the field with autoincremental values.
        start (integer): Choose the initial number of the incremental count, Default: 0.

    Returns
        layer (QgsVectorLayer): The QgsVectorLayer output layer.
    """

    logger.info("Adding incremental field")
    try:
        parameter = {
            'INPUT': layer,
            'FIELD_NAME': fieldname,
            'START':start,
            'MODULUS':0,
            'GROUP_FIELDS':[],
            'SORT_EXPRESSION':'',
            'SORT_ASCENDING':True,
            'SORT_NULLS_FIRST':False,
            'OUTPUT': 'memory:extracted'
        }
        result = processing.run('native:addautoincrementalfield', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info(f'Parameters: {str(parameter)}')
        logger.info("addAutoIncrementalField  finished")
        return result
    except Exception as error:
        logger.error("An error occured in addAutoIncrementalField")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

addxyfieldstolayer(layer, crs)

Adds X and Y (or latitude/longitude) fields to a point layer. The X/Y fields can be calculated in a different CRS to the layer (e.g. creating latitude/longitude fields for a layer in a projected CRS).

Parameters:

Name Type Description Default
layer QgsVectorLayer

The input layer.

required
crs string

Coordinate reference system to use for the generated x and y fields.

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the output layer.

Source code in python\engine\workers.py
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
def addxyfieldstolayer(layer: QgsVectorLayer, crs: str):
    """
    Adds X and Y (or latitude/longitude) fields to a point layer. The X/Y fields can be calculated in a different CRS to the layer (e.g. creating latitude/longitude fields for a layer in a projected CRS).

    Args:
        layer (QgsVectorLayer): The input layer.
        crs (string): Coordinate reference system to use for the generated x and y fields.

    Returns:
        layer (QgsVectorLayer): Specify the output layer.
    """

    logger.info(f"Adding X/Y fields to {layer}" )
    try:
        parameter = {
            'INPUT': layer,
            'CRS': crs,
            'OUTPUT': 'memory:output_from_addxyfieldstolayer'
        }
        result = processing.run('native:addxyfieldstolayer', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info(f'Parameters: {str(parameter)}')
        logger.info("addxyfieldstolayer  finished")
        return result
    except Exception as error:
        logger.error("An error occured in addxyfieldstolayer")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

assign_projection(layer, targetEPSG)

Assign a new projection on a layer. The returned layer is precisely the same layer but assigned a new CRS.

Args: layer : (QgsVectorLayer)Q The layer to be assigned a new CRS. targetEPSG (integer): The EPSG code og the target coordinate system.

Returns:

Name Type Description
layer QgsVectorLayer

Layer with the new projection assigned

Source code in python\engine\workers.py
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
def assign_projection(layer: QgsVectorLayer, targetEPSG: int):
    """
    Assign a new projection on a layer. The returned layer is precisely the same layer but assigned a new CRS.

    Args:
    layer : (QgsVectorLayer)Q The layer to be assigned a new CRS.
    targetEPSG (integer): The EPSG code og the target coordinate system.

    Returns:
        layer (QgsVectorLayer): Layer with the new projection assigned
    """

    logger.info(f'Assigning CRS EPSG:{targetEPSG} to {layer.name()}')
    try:
        parameter = {
            'INPUT': layer,
            'CRS': QgsCoordinateReferenceSystem(targetEPSG),
            'OUTPUT': 'TEMPORARY_OUTPUT'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:assignprojection', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info('Assigning projection finished')
        return result
    except Exception as error:
        logger.error("An error occured assigning a new crs to layer")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

attributeindex(layer, field)

Creates an index to speed up queries made against a field in a table. Support for index creation is dependent on the layer's data provider and the field type.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required
field string

The field to base the index on

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def attributeindex(layer: QgsVectorLayer, field: str):
    """
    Creates an index to speed up queries made against a field in a table.
    Support for index creation is dependent on the layer's data provider and the field type.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
        field (string): The field to base the index on

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Crating attribute index on " + layer + " on filed " + field)
    try:
        parameter = {
            'INPUT': field,
            'FIELD': field,
            'OUTPUT': 'memory:extracted'
        }
        result = processing.run('native:createattributeindex', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info(f'Parameters: {str(parameter)}')
        logger.info("createattributeindex  finished")
        return result
    except Exception as error:
        logger.error("An error occured in createattributeindex")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

bufferLayer(layer, distance, segements, endcapStyle, joinStyle, miterLimit, dissolve)

Computes a buffer area for all the features in an input layer, using a fixed or data defined distance. It is possible to use a negative distance for polygon input layers. In this case the buffer will result in a smaller polygon (setback). QGIS processing algorithem: native:buffer

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required
distance integer

The buffer distance. Default: 10.0

required
segements integer

Number og segments. Default: 5

required
endcapStyle integer

Controls how line endings are handled in the buffer. Default: 0 (One of: 0 — Round, 1 — Flat, 2 — Square)

required
joinStyle integer

Specifies whether round, miter or beveled joins should be used when offsetting corners in a line. Default: 0 (Options are: 0 — Round, 1 — Miter, 2 — Bevel)

required
miterLimit integer

Sets the maximum distance from the offset geometry to use when creating a mitered join as a factor of the offset distance Default: 0, Minimum: 1

required
dissolve boolean

Dissolve the final buffer. Default: false.

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
def bufferLayer(layer: QgsVectorLayer, distance: int, segements: int, endcapStyle: int, joinStyle: int, miterLimit: int, dissolve: bool):
    """
    Computes a buffer area for all the features in an input layer, using a fixed or data defined distance.
    It is possible to use a negative distance for polygon input layers.
    In this case the buffer will result in a smaller polygon (setback).
    QGIS processing algorithem: native:buffer

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
        distance (integer): The buffer distance. Default: 10.0
        segements (integer): Number og segments. Default: 5
        endcapStyle (integer): Controls how line endings are handled in the buffer. Default: 0 (One of: 0 — Round, 1 — Flat, 2 — Square)
        joinStyle (integer): Specifies whether round, miter or beveled joins should be used when offsetting corners in a line. Default: 0 (Options are: 0 — Round, 1 — Miter, 2 — Bevel)
        miterLimit (integer): Sets the maximum distance from the offset geometry to use when creating a mitered join as a factor of the offset distance Default: 0, Minimum: 1
        dissolve (boolean): Dissolve the final buffer. Default: false.

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Creating buffer layer")
    if layerHasFeatures(layer):
        logger.info("Processing " + str(layer.featureCount()) +" features")
    try:
        parameter = {
            'INPUT': layer,
            'DISTANCE': distance,
            'SEGMENTS': segements,
            'END_CAP_STYLE': endcapStyle,
            'JOIN_STYLE': joinStyle,
            'MITER_LIMIT': miterLimit,
            'DISSOLVE': dissolve,
            'OUTPUT': 'memory:buffer'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:buffer', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("BufferLayer finished")
        return result
    except Exception as error:
        logger.error("An error occured in BufferLayer")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

clip(layer, overlay)

Clips a vector layer using the features of an additional polygon layer. Only the parts of the features in the input layer that fall within the polygons of the overlay layer will be added to the resulting layer.

Parameters:

Name Type Description Default
layer QgsVectorLayer

Layer containing the features to be clipped

required
overlay QgsVectorLayer

Layer containing the clipping features

required

Returns:

Name Type Description
layer QgsVectorLayer

Layer to contain the features from the input layer that are inside the overlay (clipping) layer

Source code in python\engine\workers.py
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
def clip(layer: QgsVectorLayer, overlay: str):
    """
    Clips a vector layer using the features of an additional polygon layer.
    Only the parts of the features in the input layer that fall within the polygons of 
    the overlay layer will be added to the resulting layer.

    Args:
        layer (QgsVectorLayer): Layer containing the features to be clipped
        overlay (QgsVectorLayer): Layer containing the clipping features

    Returns:
        layer (QgsVectorLayer): Layer to contain the features from the input layer that are inside the overlay (clipping) layer
    """

    logger.info("Clipping layers")
    try:
        parameter = {
            'INPUT': layer,
            'OVERLAY': overlay,
            'OUTPUT': 'memory:extracted'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:clip', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("Clip  finished")
        return result
    except Exception as error:
        logger.error("An error occured in Clip")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

concavehull(inputlayer, alpha, holes, multigeom)

Computes the concave hull of the features from an input point layer.

Parameters:

Name Type Description Default
inputlayer QgsVectorLayer

Input point vector layer

required
alpha float

Number from 0 (maximum concave hull) to 1 (convex hull).

required
holes boolean

Choose whether to allow holes in the final concave hull

required
multigeom boolean

Check if you want to have singlepart geometries instead of multipart ones.

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the output vector layer

Source code in python\engine\workers.py
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
def concavehull(inputlayer:QgsVectorLayer, alpha: float, holes: bool, multigeom: bool ):
    """
    Computes the concave hull of the features from an input point layer.

    Args:
        inputlayer (QgsVectorLayer): Input point vector layer
        alpha (float): Number from 0 (maximum concave hull) to 1 (convex hull).
        holes (boolean): Choose whether to allow holes in the final concave hull
        multigeom (boolean): Check if you want to have singlepart geometries instead of multipart ones.

    Returns:
        layer (QgsVectorLayer): Specify the output vector layer
    """

    logger.info('calcualting concavehull')
    try:
        parameters = {
            'INPUT': inputlayer,
            'ALPHA' : alpha,
            'HOLES' : holes,
            'NO_MULTIGEOMETRY' : multigeom,
            'OUTPUT': 'memory:output_from_concavehull'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:concavehull', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('concavehull finished')
        return result
    except Exception as error:
        logger.error("An error occured in concavehull")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()            

convexhull(layer)

Calculates the convex hull for each feature in an input layer.

Parameters:

Name Type Description Default
layer QgsVectorLayer

Input vector layer

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the output vector layer.

Source code in python\engine\workers.py
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
def convexhull(layer: QgsVectorLayer):
    """
    Calculates the convex hull for each feature in an input layer.

    Args:
        layer (QgsVectorLayer): Input vector layer

    Returns:
        layer (QgsVectorLayer): Specify the output vector layer.
    """

    logger.info(f" Calculating convexhull for layer {layer}")
    try:
        parameter = {
            'INPUT': layer,
            'OUTPUT': 'memory:output_from_convexhull'
        }
        result = processing.run('native:convexhull', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info(f'Parameters: {str(parameter)}')
        logger.info("convexhull  finished")
        return result
    except Exception as error:
        logger.error("An error occured in convexhull")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

countpointsinpolygon(polygons, points, weight, fieldname)

Takes a point and a polygon layer and counts the number of points from the point layer in each of the polygons of the polygon layer. A new polygon layer is generated, with the exact same content as the input polygon layer, but containing an additional field with the points count corresponding to each polygon.

Parameters:

Name Type Description Default
polygons QgsVectorLayer

Polygon layer whose features are associated with the count of points they contain

required
points QgsVectorLayer

Point layer with features to count

required
weight string

A field from the point layer. The count generated will be the sum of the weight field of the points contained by the polygon. If the weight field is not numeric, the count will be 0.

required
fieldname string

The name of the field to store the count of points

required

Returns:

Name Type Description
layer QgsVectorLayer

Specification of the output layer.

Source code in python\engine\workers.py
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
def countpointsinpolygon(polygons: QgsVectorLayer, points: QgsVectorLayer, weight : str, fieldname: str):
    """
    Takes a point and a polygon layer and counts the number of points from the point layer in each of the polygons of the polygon layer.
    A new polygon layer is generated, with the exact same content as the input polygon layer, but containing an additional field with the points count corresponding to each polygon.

    Args:
        polygons (QgsVectorLayer): Polygon layer whose features are associated with the count of points they contain
        points (QgsVectorLayer): Point layer with features to count
        weight (string): A field from the point layer. The count generated will be the sum of the weight field of the points contained by the polygon. If the weight field is not numeric, the count will be 0.
        fieldname (string): The name of the field to store the count of points

    Returns:
        layer (QgsVectorLayer): Specification of the output layer.
    """

    logger.info('Conducting point in polygon')
    try:
        if isinstance(weight, int):
            value = weight
        else:
            value = 0

        parameters = {
            'POLYGONS': polygons,
            'POINTS': points,
            'WEIGHT': value,
            'FIELD' : fieldname,
            'OUTPUT': 'memory:output_from_countpointsinpolygon'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:Countpointsinpolygon', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('Promote to multipart finished')
        return result
    except Exception as error:
        logger.error("An error occured in Countpointsinpolygon")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()  

createCentroids(layer)

Creates a new point layer, with points representing the centroids of the geometries of the input layer. The centroid is a single point representing the barycenter (of all parts) of the feature, so it can be outside the feature borders. But can also be a point on each part of the feature. The attributes of the points in the output layer are the same as for the original features.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
def createCentroids(layer: str):
    """
    Creates a new point layer, with points representing the centroids of the geometries of the input layer.
    The centroid is a single point representing the barycenter (of all parts) of the feature, so it can be outside the feature borders. But can also be a point on each part of the feature.
    The attributes of the points in the output layer are the same as for the original features.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Creating centroids")
    if layerHasFeatures(layer):
        logger.info("Processing " + str(layer.featureCount()) +" features")
    try:
        parameter = {
            'INPUT': layer,
            'ALL_PARTS':False,
            'OUTPUT': 'memory:buffer'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:centroids', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("Centroids finished")
        return result
    except Exception as error:
        logger.error("An error occured in createCentroids")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

dbscanclustering(inputlayer, min_clusters, max_dist)

Clusters point features based on a 2D implementation of Density-based spatial clustering of applications with noise (DBSCAN) algorithm. The algorithm requires two parameters, a minimum cluster size, and the maximum distance allowed between clustered points.

Parameters:

Name Type Description Default
inputlayer QgsVectorLayer

Layer to analyze

required
min_clusters integer

Minimum number of features to generate a cluster

required
max_dist integer

Distance beyond which two features can not belong to the same cluster (eps)

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the vector layer for the result of the clustering.

Source code in python\engine\workers.py
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
def dbscanclustering(inputlayer: QgsVectorLayer, min_clusters: int, max_dist: int ):
    """
    Clusters point features based on a 2D implementation of Density-based spatial clustering of applications with noise (DBSCAN) algorithm.
    The algorithm requires two parameters, a minimum cluster size, and the maximum distance allowed between clustered points.

    Args:
        inputlayer (QgsVectorLayer): Layer to analyze
        min_clusters (integer): Minimum number of features to generate a cluster
        max_dist (integer): Distance beyond which two features can not belong to the same cluster (eps)

    Returns:
        layer (QgsVectorLayer): Specify the vector layer for the result of the clustering.
    """

    logger.info('Performing DBScan clustering')
    try:
        parameters = {
            'INPUT': inputlayer,
            'MIN_SIZE' : min_clusters,
            'EPS': max_dist,
            'OUTPUT': 'memory:output_from_dbscanclustering'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:dbscanclustering', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('Dbscanclustering finished')
        return result
    except Exception as error:
        logger.error("An error occured in Dbscanclustering")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

deleteColumns(layer, columns)

Takes a vector layer and generates a new one that has the same features but without the selected columns.

Parameters:

Name Type Description Default
layer QgsVectorLayer

Input vector layer to drop field(s) from

required
columns list of strings

The field(s) to drop

required

Returns:

Name Type Description
layer QgsVectorLayer

The QgsVectorLayer output layer.

Source code in python\engine\workers.py
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
def deleteColumns (layer: QgsVectorLayer, columns: list):
    """
    Takes a vector layer and generates a new one that has the same features but without the selected columns.

    Args:
        layer (QgsVectorLayer): Input vector layer to drop field(s) from
        columns (list of strings): The field(s) to drop

    Returns:
        layer (QgsVectorLayer): The QgsVectorLayer output layer.
    """

    logger.info("deleting fields")

    try:
        parameter = {
            'INPUT': layer,
            'COLUMN':columns,
            'OUTPUT': 'memory:extracted'
        }
        result = processing.run('native:deletecolumn', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info(f'Parameters: {str(parameter)}')
        logger.info("deleteColumns  finished")
        return result
    except Exception as error:
        logger.error("An error occured in deleteColumns")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

delete_geopacakge_layers(geopackage, layernames)

Deletes one or more tables from a geopackage

Parameters:

Name Type Description Default
geopackage string

The full path for the geopackage file

required
layernames list of strings

List of layernames to be deleted

required
Source code in python\engine\workers.py
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
def delete_geopacakge_layers(geopackage: str, layernames: list):
    """
    Deletes one or more tables from a geopackage

    Args:
        geopackage (string): The full path for the geopackage file
        layernames (list of strings): List of layernames to be deleted
    """

    logger.info("Performing delete_geopacakge_layer")
    logger.info(f"Deleting layers {layernames}")

    if os.path.isfile(geopackage):
        try:
            for layer in layernames:
                logger.info(f"Deleting layer {layer}")
                parameter = {'DATABASE':'{0}|layername={1}'.format(geopackage, layer),
                'SQL':'drop table {0}'.format(layer)}
                logger.info(f'Parameters: {str(parameter)}')
                processing.run("native:spatialiteexecutesql", parameter )
                logger.info(f"Layer deleted")
            logger.info(f"Finished deleting layers")


        except Exception as error:
            logger.error("An error occured in delete_geopacakge_layer")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            script_failed()
    else:    
        pass

difference(layer, overlay)

Extracts features from the input layer that don’t fall within the boundaries of the overlay layer. Input layer features that partially overlap the overlay layer feature(s) are split along the boundary of those feature(s.

Parameters:

Name Type Description Default
layer QgsVectorLayer

Layer to extract (parts of) features from.

required
overlay QgsVectorLayer

Layer containing the geometries that will be subtracted from the iniput layer geometries

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
def difference(layer: QgsVectorLayer, overlay: QgsVectorLayer):
    """
    Extracts features from the input layer that don’t fall within the boundaries of the overlay layer.
    Input layer features that partially overlap the overlay layer feature(s) are split along the 
    boundary of those feature(s.

    Args:
        layer (QgsVectorLayer): Layer to extract (parts of) features from.
        overlay (QgsVectorLayer): Layer containing the geometries that will be subtracted from the iniput layer geometries

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Finding differences")
    try:
        parameter = {
            'INPUT': layer,
            'OVERLAY': overlay,
            'OUTPUT': 'memory:extracted'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:difference', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("Difference  finished")
        return result
    except Exception as error:
        logger.error("An error occured in Difference")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

dissolveFeatures(layer, fieldList, disjoined)

Takes a vector layer and combines its features into new features. One or more attributes can be specified to dissolve features belonging to the same class (having the same value for the specified attributes), alternatively all features can be dissolved to a single feature. All output geometries will be converted to multi geometries. QGIS processing algorithem: native:dissolve.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required
fieldList list of strings

List of fields to dissolve on. Default []

required
disjoined boolean

Keep disjoint features separate ? Default: False

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
def dissolveFeatures(layer: QgsVectorLayer, fieldList: list, disjoined: bool):
    """
    Takes a vector layer and combines its features into new features. 
    One or more attributes can be specified to dissolve features belonging to the same class 
    (having the same value for the specified attributes), alternatively all features can be dissolved to a single feature.
    All output geometries will be converted to multi geometries. 
    QGIS processing algorithem: native:dissolve.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
        fieldList (list of strings): List of fields to dissolve on. Default []
        disjoined (boolean): Keep disjoint features separate ? Default: False

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem

    """
    logger.info("Dissolving features")
    if layerHasFeatures(layer):
        logger.info("Processing " + str(layer.featureCount()) +" features")
    try:
        parameter = {
            'INPUT': layer,
            'FIELD' : fieldList,
            'SEPARATE_DISJOINT' : False,
            'OUTPUT': 'memory:dissolved'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:dissolve', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("DissolveFeatures finished")
        if layerHasFeatures(result):
            logger.info("Returning " + str(result.featureCount()) +" features")
        return result
    except Exception as error:
        logger.error("An error occured in dissolveFeatures")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

execute_sql(connection, databasetype, sql_expression, pgdb_name=None, driver=None)

Execute an SQL query against a database. This can be used to create tables, truncate, build indexes etc. The database type must be specified in the 'database' parameter (one of 'Mssql' or 'Postgres') The default Mssql driver is 'SQL Server' - if this needs to be overwritten, specify the parameter driver, else leave it empty. SQL statments must be trippel double-quoted - prepare the statement in the QGIS sql executor tool for testing.

Parameters:

Name Type Description Default
connection string

Name of a database connection from settings.json

required
databasetype string

The database type, one of 'Mssql' or 'Postgres'.

required
sql_expression string

The SQL expression to be executed. Use trippel double-quotes arraound the expression

required
pgdb_name string

Name of postgres database if databasetype is Postgres. Defaults to None.

None
driver string

Defaults to None. The name of the Mssql driver, if 'SQL Server' is not working.

None

Returns:

Name Type Description
Errorcode integer

Returns 0 if the SQL is executed without errors.

Source code in python\engine\workers.py
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
def execute_sql(connection, databasetype, sql_expression, pgdb_name=None, driver=None):
    """
    Execute an SQL query against a database. 
    This can be used to create tables, truncate, build indexes etc.
    The database type must be specified in the 'database' parameter (one of 'Mssql' or 'Postgres')
    The default Mssql driver is 'SQL Server' - if this needs to be overwritten, specify the parameter driver, else leave it empty.
    SQL statments must be trippel double-quoted - prepare the statement in the QGIS sql executor tool for testing. 

    Args:
        connection (string): Name of a database connection from settings.json
        databasetype (string): The database type, one of 'Mssql' or 'Postgres'.
        sql_expression (string): The SQL expression to be executed. Use trippel double-quotes arraound the expression
        pgdb_name (string): Name of postgres database if databasetype is  Postgres. Defaults to None.
        driver (string): Defaults to None. The name of the Mssql driver, if 'SQL Server' is not working.

    Returns:
        Errorcode (integer): Returns 0 if the SQL is executed without errors.

    """

    config = get_config()
    if databasetype in ('Postgres', 'Mssql'):
        logger.info(f'Running SQL executor on {databasetype}' )
    else :
        logger.info(f'Unsupported database: {databasetype}, use one of "Mssql" or "Postgres"' )
        logger.critical("Program terminated" )
        sys.exit()
    try:
        dbconnection = config['DatabaseConnections'][connection]
        if databasetype == 'Mssql':
            import pyodbc 
            if driver == "":
                mssqldriver = 'SQL Server'
            else :
                mssqldriver = 'driver'
            cnxn = pyodbc.connect('DRIVER={'+mssqldriver+'};Server='+dbconnection['host']+';Database='+dbconnection['databasename']+';User ID='+dbconnection['user']+';Password='+dbconnection['password'])
            logger.info("Using connection :" + 'DRIVER={'+mssqldriver+'};Server='+dbconnection['host']+';Database='+dbconnection['databasename']+';User ID='+dbconnection['user']+';Password=xxxxxxxx')
            cursor = cnxn.cursor()
            logger.info(f'Query: {sql_expression}' )
            cursor.execute(sql_expression) 
            logger.info("SQL executor finished")
            return 0

        if databasetype == 'Postgres':
            import psycopg2
            connection = psycopg2.connect(user=dbconnection['user'], password=dbconnection['password'], host=dbconnection['host'], port=dbconnection['port'], database=pgdb_name)
            logger.info("Using connection : user="+ dbconnection['user']+", password=xxxxxx, host="+dbconnection['host']+", port="+dbconnection['port']+", database="+pgdb_name )
            cursor = connection.cursor()
            logger.info(f'Query: {sql_expression}' )
            cursor.execute(sql_expression)
            connection.commit()
            cursor.close()
            connection.close()
            logger.info("SQL executor finished")
            return 0

    except Exception as error:
        logger.error("An error occured running SQL executor")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

extractByExpression(layer, expression)

Creates a vector layer from an input layer, containing only matching features. The criteria for adding features to the resulting layer is based on a QGIS expression.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer that is used as input.

required
expression string

Expression to filter the vector layer

required

Returns:

Name Type Description
layer QgsVectorLayer

The QgsVectorLayer output layer.

Source code in python\engine\workers.py
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
def extractByExpression(layer: QgsVectorLayer, expression: str):
    """
    Creates a vector layer from an input layer, containing only matching features.
    The criteria for adding features to the resulting layer is based on a QGIS expression.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer that is used as input.
        expression (string): Expression to filter the vector layer

    Returns:
        layer (QgsVectorLayer): The QgsVectorLayer output layer.
    """

    logger.info("Extracting by expression")
    try:
        parameter = {
            'INPUT': layer,
            'EXPRESSION': expression,
            'OUTPUT': 'memory:extracted'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:extractbyexpression', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("Extractbyexpression  finished")
        return result
    except Exception as error:
        logger.error("An error occured in extractByExpression")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

extractByLocation(layer, predicate, intersect)

summary

Parameters:

Name Type Description Default
layer QgsVectorLayer

Input vector layer.

required
predicate integer

Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.

required
intersect QgsVectorLayer

Intersection vector layer

required

Returns:

Name Type Description
layer QgsVectorLayer

the output vector layer for the join.

Source code in python\engine\workers.py
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
def extractByLocation(layer: QgsVectorLayer, predicate: int, intersect: str):
    """_summary_

    Args:
        layer (QgsVectorLayer): Input vector layer. 
        predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
        intersect (QgsVectorLayer): Intersection vector layer

    Returns:
        layer (QgsVectorLayer): the output vector layer for the join.
    """

    logger.info("Extracting by location")
    try:
        parameter = {
            'INPUT': layer,
            'PREDICATE':predicate,
            'INTERSECT':intersect,
            'OUTPUT': 'memory:extracted'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:extractbylocation', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("extractByLocation finished")
        return result
    except Exception as error:
        logger.error("An error occured in extractByLocation")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

extractvertices(inputlayer)

Takes a vector layer and generates a point layer with points representing the vertices in the input geometries. The attributes associated to each point are the same ones associated to the feature that the vertex belongs to. Additional fields are added to the vertices indicating the vertex index (beginning at 0), the feature’s part and its index within the part (as well as its ring for polygons), distance along original geometry and bisector angle of vertex for original geometry.

Parameters:

Name Type Description Default
inputlayer QgsVectorLayer

Input vector layer

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the output vector layer

Source code in python\engine\workers.py
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
def extractvertices(inputlayer:QgsVectorLayer):
    """
    Takes a vector layer and generates a point layer with points representing the vertices in the input geometries.
    The attributes associated to each point are the same ones associated to the feature that the vertex belongs to.
    Additional fields are added to the vertices indicating the vertex index (beginning at 0), the feature’s part and its index within the part
    (as well as its ring for polygons), distance along original geometry and bisector angle of vertex for original geometry.

    Args:
        inputlayer (QgsVectorLayer): Input vector layer

    Returns:
        layer (QgsVectorLayer): Specify the output vector layer
    """

    logger.info('Extracting vertices')
    try:
        parameters = {
            'INPUT': inputlayer,
            'OUTPUT': 'memory:output_from_extractvertices'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:extractvertices', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('extractvertices finished')
        return result
    except Exception as error:
        logger.error("An error occured in extractvertices")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()    

fieldCalculator(layer, fieldname, fieldtype, fieldlength, fieldprecision, formula)

Scripting the field calcualtor You can use all the supported expressions and functions. The original layer is not modified. A new layer is generated where the attribute table contains the calucalted field QGIS processing algorithem: native:fieldcalculator

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required
fieldname string

The name of the new calcualted field

required
fieldtype integer

Type of the field, Default: 0 (0 — Float, 1 — Integer, 2 — String, 3 — Date)

required
fieldlength integer

Lenght of the field, Default: 10.

required
fieldprecision integer

Precision of the field, Default: 3.

required
formula string

The expression that populates the values of the field.

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
def fieldCalculator (layer: QgsVectorLayer, fieldname: str, fieldtype: int, fieldlength: int, fieldprecision: int, formula: str):
    """
    Scripting the field calcualtor
    You can use all the supported expressions and functions.
    The original layer is not modified. A new layer is generated where the attribute table contains the calucalted field
    QGIS processing algorithem: native:fieldcalculator

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
        fieldname (string): The name of the new calcualted field
        fieldtype (integer): Type of the field,  Default: 0  (0 — Float, 1 — Integer, 2 — String, 3 — Date)
        fieldlength (integer): Lenght of the field, Default: 10.
        fieldprecision (integer): Precision of the field, Default: 3.
        formula (string): The expression that populates the values of the field.

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Calculating field")
    try:
        parameter = {
            'INPUT': layer,
            'FIELD_NAME': fieldname,
            'FIELD_TYPE': fieldtype,
            'FIELD_LENGTH': fieldlength,
            'FIELD_PRECISION': fieldprecision,
            'FORMULA': formula,
            'OUTPUT': 'memory:extracted'
        }
        result = processing.run('native:fieldcalculator', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info(f'Parameters: {str(parameter)}')
        logger.info("fieldCalculator  finished")
        return result
    except Exception as error:
        logger.error("An error occured in fieldCalculator")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

fixGeometry(layer)

Attempts to create a valid representation of a given invalid geometry without losing any of the input vertices. Already valid geometries are returned without further intervention. Always outputs multi-geometry layer. QGIS processing algorithem: native:fixgeometries

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
def fixGeometry(layer: QgsVectorLayer):
    """
    Attempts to create a valid representation of a given invalid geometry without losing any of the input vertices.
    Already valid geometries are returned without further intervention. Always outputs multi-geometry layer.
    QGIS processing algorithem: native:fixgeometries

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Fixing geometries")
    if layerHasFeatures(layer):
        logger.info("Processing " + str(layer.featureCount()) +" features")
    try:
        parameter = {
            'INPUT': layer,
            'OUTPUT': 'memory:buffer'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:fixgeometries', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("FixGeometry finished")
        return result
    except Exception as error:
        logger.error("An error occured in FixGeometry")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

forceRHR(layer)

Forces polygon geometries to respect the Right-Hand-Rule, in which the area that is bounded by a polygon is to the right of the boundary. In particular, the exterior ring is oriented in a clockwise direction and any interior rings in a counter-clockwise direction. QGIS processing algorithem: native:forcerhr

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Takes a vector layer and selects a subset of its features. No new layer is generated by this algorithm. The subset is defined randomly, based on feature IDs, using a percentage or count value to define the total number of features in the subset.

Source code in python\engine\workers.py
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
def forceRHR(layer: QgsVectorLayer):
    """
    Forces polygon geometries to respect the Right-Hand-Rule, in which the area that is bounded
    by a polygon is to the right of the boundary. 
    In particular, the exterior ring is oriented in a clockwise direction and any interior
    rings in a counter-clockwise direction.
    QGIS processing algorithem: native:forcerhr

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem

    Takes a vector layer and selects a subset of its features. No new layer is generated by this algorithm.
    The subset is defined randomly, based on feature IDs, using a percentage or count value to define the 
    total number of features in the subset.

    """

    logger.info("Running force right-hand rule")
    if layerHasFeatures(layer):
        logger.info("Processing " + str(layer.featureCount()) +" features")
    try:
        parameter = {
            'INPUT': layer,
            'OUTPUT': 'memory:forced'
        }
        result = processing.run('native:forcerhr', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("forceRHR finished")
        return result
    except Exception as error:
        logger.error("An error occured in forceRHR")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

joinByLocation(layer, predicate, join, join_fields, method, discard_nomatching, prefix)

Takes an input vector layer and creates a new vector layer that is an extended version of the input one, with additional attributes in its attribute table. The additional attributes and their values are taken from a second vector layer. A spatial criteria is applied to select the values from the second layer that are added to each feature from the first layer.

Parameters:

Name Type Description Default
layer QgsVectorLayer

Input vector layer. The output layer will consist of the features of this layer with attributes from matching features in the second layer.

required
predicate integer

Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.

required
join QgsVectorLayer

The join layer. Features of this vector layer will add their attributes to the source layer attribute table if they satisfy the spatial relationship.

required
join_fields list of strings

Select the specific fields you want to add from the join layer. By default all the fields are added.

required
method integer

The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one) 2 — Take attributes of the feature with largest overlap only (one-to-one)

required
discard_nomatching boolean

Remove from the output the input layer’s features which could not be joined

required
prefix string

Add a prefix to joined fields in order to easily identify them and avoid field name collision

required

Returns:

Name Type Description
layer QgsVectorLayer

the output vector layer for the join.

Source code in python\engine\workers.py
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
def joinByLocation(layer: QgsVectorLayer, predicate: int, join: str, join_fields: list, method: int, discard_nomatching: bool, prefix: str):
    """
    Takes an input vector layer and creates a new vector layer that is an extended version of
    the input one, with additional attributes in its attribute table.
    The additional attributes and their values are taken from a second vector layer.
    A spatial criteria is applied to select the values from the second layer that are added to each 
    feature from the first layer.

    Args:
        layer (QgsVectorLayer): Input vector layer. The output layer will consist of the features of this layer with attributes from matching features in the second layer.
        predicate (integer): Type of spatial relation the source feature should have with the target feature so that they could be joined. One or more of: 0 — intersect, 1 — contain, 2 — equal, 3 — touch, 4 — overlap, 5 — are within 6 — cross.
        join (QgsVectorLayer): The join layer. Features of this vector layer will add their attributes to the source layer attribute table if they satisfy the spatial relationship.
        join_fields (list of strings): Select the specific fields you want to add from the join layer. By default all the fields are added.
        method (integer): The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one) 2 — Take attributes of the feature with largest overlap only (one-to-one)
        discard_nomatching (boolean): Remove from the output the input layer’s features which could not be joined
        prefix (string): Add a prefix to joined fields in order to easily identify them and avoid field name collision

    Returns:
        layer (QgsVectorLayer): the output vector layer for the join.
    """

    logger.info("Clipping layers")
    try:
        parameter = {
            'INPUT': layer,
            'PREDICATE':predicate,
            'JOIN':join,
            'JOIN_FIELDS':join_fields,
            'METHOD':method,
            'DISCARD_NONMATCHING':discard_nomatching,
            'PREFIX':prefix,
            'OUTPUT': 'memory:extracted'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:joinattributesbylocation', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("joinByLocation finished")
        return result
    except Exception as error:
        logger.error("An error occured in joinByLocation")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

join_by_attribute(layer1, layer1_field, layer2, layer2_field, fields_to_copy, method, discard, prefix)

Takes an input vector layer and creates a new vector layer that is an extended version of the input one, with additional attributes in its attribute table. The additional attributes and their values are taken from a second vector layer. An attribute is selected in each of them to define the join criteria. QGIS processing algorithem: native:joinattributestable.

Parameters:

Name Type Description Default
layer1 QgsVectorLayer

The 1. QgsVectorLayer input for the algorithem

required
layer1_field string

Field of the source layer to use for the join

required
layer2 QgsVectorLayer

The 2. QgsVectorLayer input for the algorithem

required
layer2_field string

Field of the source layer to use for the join

required
fields_to_copy list of strings

Select the specific fields you want to add. By default all the fields are added. Default []

required
method integer

The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one)

required
discard boolean

Check if you don’t want to keep the features that could not be joined

required
prefix string

Add a prefix to joined fields in order to easily identify them and avoid field name collision

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
def join_by_attribute(layer1: QgsVectorLayer, layer1_field:str, layer2: QgsVectorLayer, layer2_field: str, fields_to_copy: list, method:int, discard: bool, prefix:str):
    """
    Takes an input vector layer and creates a new vector layer that is an extended version of the input one, 
    with additional attributes in its attribute table.
    The additional attributes and their values are taken from a second vector layer. An attribute is selected in each of them 
    to define the join criteria.
    QGIS processing algorithem: native:joinattributestable.

    Args:
        layer1 (QgsVectorLayer): The 1. QgsVectorLayer input for the algorithem
        layer1_field (string): Field of the source layer to use for the join
        layer2 (QgsVectorLayer): The 2. QgsVectorLayer input for the algorithem
        layer2_field (string): Field of the source layer to use for the join
        fields_to_copy (list of strings): Select the specific fields you want to add. By default all the fields are added. Default []
        method (integer): The type of the final joined layer. One of: 0 — Create separate feature for each matching feature (one-to-many) 1 — Take attributes of the first matching feature only (one-to-one)
        discard (boolean): Check if you don’t want to keep the features that could not be joined
        prefix (string): Add a prefix to joined fields in order to easily identify them and avoid field name collision

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Joining features features")
    if layerHasFeatures(layer1):
        logger.info("Processing " + str(layer1.featureCount()) +" features")
    try:
        parameter = {
            'INPUT':layer1,
            'FIELD':layer1_field,
            'INPUT_2':layer2,
            'FIELD_2':layer2_field,
            'FIELDS_TO_COPY':fields_to_copy,
            'METHOD':method,
            'DISCARD_NONMATCHING':discard,
            'PREFIX':prefix,
            'OUTPUT': 'memory:joined'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:joinattributestable', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("Joinattributestable finished")
        if layerHasFeatures(result):
            logger.info("Returning " + str(result.featureCount()) +" features")
        return result
    except Exception as error:
        logger.error("An error occured in joinattributestable")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

kmeansclustering(inputlayer, clusters)

Calculates the 2D distance based k-means cluster number for each input feature. K-means clustering aims to partition the features into k clusters in which each feature belongs to the cluster with the nearest mean. The mean point is represented by the barycenter of the clustered features. If input geometries are lines or polygons, the clustering is based on the centroid of the feature.

Parameters:

Name Type Description Default
inputlayer QgsVectorLayer

Layer to analyze

required
clusters integer

Number of clusters to create with the features

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the output vector layer for generated the clusters.

Source code in python\engine\workers.py
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
def kmeansclustering(inputlayer: QgsVectorLayer, clusters: int):
    """
    Calculates the 2D distance based k-means cluster number for each input feature.
    K-means clustering aims to partition the features into k clusters in which each feature belongs to the cluster with the nearest mean. The mean point is represented by the barycenter of the clustered features.
    If input geometries are lines or polygons, the clustering is based on the centroid of the feature.

    Args:
        inputlayer (QgsVectorLayer): Layer to analyze
        clusters (integer): Number of clusters to create with the features

    Returns:
        layer (QgsVectorLayer): Specify the output vector layer for generated the clusters.
    """

    logger.info('Calculating clusters')
    try:
        parameters = {
            'INPUT': inputlayer,
            'CLUSTERS' : clusters,
            'OUTPUT': 'memory:output_from_kmeansclustering'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:kmeansclustering', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('Kmeansclustering finished')
        return result
    except Exception as error:
        logger.error("An error occured in Kmeansclustering")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

lineintersections(inputlayer, split_layer, input_fields, intersect_fields)

Splits the lines or polygons in one layer using the lines or polygon rings in another layer to define the breaking points. Intersection between geometries in both layers are considered as split points. Output will contain multi geometries for split features.

Parameters:

Name Type Description Default
inputlayer QgsVectorLayer

Input line layer.

required
split_layer QgsVectorLayer

Layer to use to find line intersections.

required
input_fields list of strings

Field(s) of the input layer to keep in the output. If no fields are chosen all fields are taken.

required
intersect_fields list of strings

Field(s) of the intersect layer to keep in the output. If no fields are chosen all fields are taken. Duplicate field names will be appended a count suffix to avoid collision

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the layer to contain the intersection points of the lines from the input and overlay layers.

Source code in python\engine\workers.py
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
def lineintersections(inputlayer: QgsVectorLayer, split_layer: QgsVectorLayer, input_fields: list, intersect_fields: list):
    """
    Splits the lines or polygons in one layer using the lines or polygon rings in another layer to define the breaking points. Intersection between geometries in both layers are considered as split points.
    Output will contain multi geometries for split features.

    Args:
        inputlayer (QgsVectorLayer): Input line layer.
        split_layer (QgsVectorLayer): Layer to use to find line intersections.
        input_fields (list of strings): Field(s) of the input layer to keep in the output. If no fields are chosen all fields are taken.
        intersect_fields (list of strings): Field(s) of the intersect layer to keep in the output. If no fields are chosen all fields are taken. Duplicate field names will be appended a count suffix to avoid collision

    Returns:
        layer (QgsVectorLayer): Specify the layer to contain the intersection points of the lines from the input and overlay layers.
    """

    logger.info('Performing line intersections')
    try:
        parameters = {
            'INPUT': inputlayer,
            'INTERSECT': split_layer,
            'INPUT_FIELDS' : input_fields, 
            'INTERSECT_FIELDS' : intersect_fields,
            'OUTPUT': 'memory:output_from_lineintersections'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:lineintersections', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('Lineintersections finished')
        return result
    except Exception as error:
        logger.error("An error occured in Lineintersections")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

mergeVectorLayers(layers, crs)

Combines multiple vector layers of the same geometry type into a single one. The attribute table of the resulting layer will contain the fields from all input layers. If fields with the same name but different types are found then the exported field will be automatically converted into a string type field. New fields storing the original layer name and source are also added.

Optionally, the destination coordinate reference system (CRS) for the merged layer can be set. If it is not set, the CRS will be taken from the first input layer. All layers will be reprojected to match this CRS.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The layers that are to be merged into a single layer. Layers should be of the same geometry type.

required
CRS Crs

Choose the CRS for the output layer. If not specified, the CRS of the first input layer is used.

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
def mergeVectorLayers(layers: list, crs: str ):
    """
    Combines multiple vector layers of the same geometry type into a single one.
    The attribute table of the resulting layer will contain the fields from all input layers. 
    If fields with the same name but different types are found then the exported field will be automatically 
    converted into a string type field. New fields storing the original layer name and source are also added.

    Optionally, the destination coordinate reference system (CRS) for the merged layer can be set. If it is 
    not set, the CRS will be taken from the first input layer. All layers will be reprojected to match this CRS.

    Args:
        layer (QgsVectorLayer): The layers that are to be merged into a single layer. Layers should be of the same geometry type.
        CRS (Crs): Choose the CRS for the output layer. If not specified, the CRS of the first input layer is used.

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Performing mergeVectorLayers")
    logger.info(f'Processing {str(len(layers))} layers')
    try:
        parameter = {
            'LAYERS': layers,
            'CRS':crs,
            'OUTPUT': 'memory:buffer'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:mergevectorlayers', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("Returning " + str(result.featureCount()) +" features")
        logger.info("mergeVectorLayers finished")
        return result
    except Exception as error:
        logger.error("An error occured in mergeVectorLayers")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

multiringconstantbuffer(inputlayer, rings, distance)

Computes multi-ring (donut) buffer for the features of the input layer, using a fixed or dynamic distance and number of rings.

Parameters:

Name Type Description Default
inputlayer QgsVectorLayer

Input vector layer

required
rings integer

The number of rings. It can be a unique value (same number of rings for all the features) or it can be taken from features data (the number of rings depends on feature values).

required
distance string

Distance between the rings. It can be a unique value (same distance for all the features) or it can be taken from features data (a field in the input data layer).

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the output polygon vector layer

Source code in python\engine\workers.py
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
def multiringconstantbuffer(inputlayer:QgsVectorLayer, rings: int, distance : str):
    """
    Computes multi-ring (donut) buffer for the features of the input layer, using a fixed or dynamic distance and number of rings.

    Args:
        inputlayer (QgsVectorLayer): Input vector layer
        rings (integer): The number of rings. It can be a unique value (same number of rings for all the features) or it can be taken from features data (the number of rings depends on feature values).
        distance (string): Distance between the rings. It can be a unique value (same distance for all the features) or it can be taken from features data (a field in the input data layer).

    Returns:
        layer (QgsVectorLayer): Specify the output polygon vector layer
    """

    logger.info('Creating multiringconstantbuffer')
    try:
        dist = float(distance)
        logger.info('Using distance value')
    except:
        dist = QgsProperty.fromExpression(f'"{distance}"')
        logger.info('Using distance from field')

    try:
        parameters = {
            'INPUT': inputlayer,
            'RINGS': rings,
            'DISTANCE': distance,
            'OUTPUT': 'memory:output_from_multiringconstantbuffer'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:multiringconstantbuffer', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('multiringconstantbuffer finished')
        return result
    except Exception as error:
        logger.error("An error occured in multiringconstantbuffer")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed() 

poleofinaccessibility(inputlayer, tolerance)

Calculates the pole of inaccessibility for a polygon layer, which is the most distant internal point from the boundary of the surface. This algorithm uses the ‘polylabel’ algorithm (Vladimir Agafonkin, 2016), which is an iterative approach guaranteed to find the true pole of inaccessibility within a specified tolerance. A more precise tolerance (lower value) requires more iterations and will take longer to calculate. The distance from the calculated pole to the polygon boundary will be stored as a new attribute in the output layer.

Parameters:

Name Type Description Default
inputlayer QgsVectorLayer

Input vector layer

required
tolerance integer

Set the tolerance for the calculation. Default 1

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the output polygon vector layer.

Source code in python\engine\workers.py
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
def poleofinaccessibility(inputlayer:QgsVectorLayer, tolerance: int):
    """
    Calculates the pole of inaccessibility for a polygon layer, which is the most distant internal point from the boundary of the surface. 
    This algorithm uses the ‘polylabel’ algorithm (Vladimir Agafonkin, 2016), which is an iterative approach guaranteed to find the true pole of inaccessibility within
    a specified tolerance. A more precise tolerance (lower value) requires more iterations and will take longer to calculate. 
    The distance from the calculated pole to the polygon boundary will be stored as a new attribute in the output layer.

    Args:
        inputlayer (QgsVectorLayer): Input vector layer
        tolerance (integer): Set the tolerance for the calculation. Default 1

    Returns:
        layer (QgsVectorLayer): Specify the output polygon vector layer.
    """

    logger.info('calcualting poleofinaccessibility')
    try:
        parameters = {
            'INPUT': inputlayer,
            'TOLERANCE' : tolerance,
            'OUTPUT': 'memory:output_from_poleofinaccessibility'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:poleofinaccessibility', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('poleofinaccessibility finished')
        return result
    except Exception as error:
        logger.error("An error occured in poleofinaccessibility")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

promoteToMultipart(layer)

Generates a vectorlayer in which all geometries are multipart.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer that is used as input.

required

Returns:

Name Type Description
layer QgsVectorLayer

The QgsVectorLayer containing multi geometries.

Source code in python\engine\workers.py
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
def promoteToMultipart(layer: QgsVectorLayer):
    """
    Generates a vectorlayer in which all geometries are multipart.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer that is used as input.

    Returns:
        layer (QgsVectorLayer): The QgsVectorLayer containing multi geometries.
    """

    logger.info('Collecting geometries')
    try:
        parameters = {
            'INPUT': layer,
            'OUTPUT': 'memory:multipart'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:promotetomulti', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('Promote to multipart finished')
        return result
    except Exception as error:
        logger.error("An error occured in promoteToMultipart")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

randomExtract(layer, method, number)

Takes a vector layer and generates a new one that contains only a subset of the features in the input layer. The subset is defined randomly, based on feature IDs, using a percentage or count value to define the total number of features in the subset.

Parameters:

Name Type Description Default
layer QgsVectorLayer

Input vector layer.

required
method integer

Random selection method. One of: 0 — Number of selected features 1 — Percentage of selected features

required
number integer

Number or percentage of features to select

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
def randomExtract(layer: QgsVectorLayer, method: int, number: int):
    """
    Takes a vector layer and generates a new one that contains only a subset of the features in the input layer.
    The subset is defined randomly, based on feature IDs, using a percentage or count value to define 
    the total number of features in the subset.

    Args:
        layer (QgsVectorLayer): Input vector layer. 
        method (integer): Random selection method. One of: 0 — Number of selected features 1 — Percentage of selected features
        number (integer): Number or percentage of features to select

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Extracting random features")
    try:
        parameter = {
            'INPUT': layer,
            'METHOD':method,
            'NUMBER':number,
            'OUTPUT': 'memory:extracted'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:randomextract', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("randomExtract finished")
        return result
    except Exception as error:
        logger.error("An error occured in randomExtract")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

randomselection(layer, method, number)

Takes a vector layer and selects a subset of its features. No new layer is generated by this algorithm. The subset is defined randomly, based on feature IDs, using a percentage or count value to define the total number of features in the subset.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required
method integer

Random selection method. One of: 0 — Number of selected features, 1 — Percentage of selected features

required
number integer

Number or percentage of features to select

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
def randomselection(layer: QgsVectorLayer, method: int, number: int):
    """
    Takes a vector layer and selects a subset of its features. No new layer is generated by this algorithm.
    The subset is defined randomly, based on feature IDs, using a percentage or count value to define the 
    total number of features in the subset.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
        method (integer): Random selection method. One of: 0 — Number of selected features, 1 — Percentage of selected features
        number (integer): Number or percentage of features to select

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Performing random selection")
    if layerHasFeatures(layer):
        logger.info("Processing " + str(layer.featureCount()) +" features")
    try:
        parameter = {
            'INPUT': layer,
            'METHOD':method,
            'NUMBER':number,
            'OUTPUT': 'memory:buffer'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:randomextract', parameter, feedback=Worker.progress)['OUTPUT']
        if layerHasFeatures(result):
            logger.info("Returning " + str(result.featureCount()) +" features")
        logger.info("randomextract finished")
        return result
    except Exception as error:
        logger.error("An error occured in FixGeometry")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

renameTableField(layer, field, newname)

Renames an existing field from a vector layer.
The original layer is not modified. A new layer is generated where the attribute table contains the renamed field. QGIS processing algorithem: native:renametablefield

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required
field string

The field that is to be renamed

required
newname string

New name for the field

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
def renameTableField (layer: QgsVectorLayer, field: str, newname: str):
    """
    Renames an existing field from a vector layer.  
    The original layer is not modified. A new layer is generated where the attribute table contains the renamed field.
    QGIS processing algorithem: native:renametablefield

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
        field (string): The field that is to be renamed
        newname (string): New name for the field

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Renaming field")
    try:
        parameter = {
            'INPUT': layer,
            'FIELD': field,
            'NEW_NAME': newname,
            'OUTPUT': 'memory:extracted'
        }
        result = processing.run('native:renametablefield', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info(f'Parameters: {str(parameter)}')
        logger.info("renameTableField  finished")
        return result
    except Exception as error:
        logger.error("An error occured in renameTableField")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

reproject(layer, targetEPSG)

Reprojects a vector layer in a different CRS. The reprojected layer will have the same features and attributes of the input layer. QGIS processing algorithem: native:reprojectlayer.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required
targetEPSG integer

The EPSG code og the target coordinate system.

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
def reproject(layer: QgsVectorLayer, targetEPSG: int):
    """
    Reprojects a vector layer in a different CRS.
    The reprojected layer will have the same features and attributes of the input layer.
    QGIS processing algorithem: native:reprojectlayer.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
        targetEPSG (integer): The EPSG code og the target coordinate system.

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Running reporjector V2")
    if layerHasFeatures(layer):
        logger.info("Processing " + str(layer.featureCount()) +" features")
    try:
        parameter = {
            'INPUT': layer,
            'TARGET_CRS': QgsCoordinateReferenceSystem(targetEPSG),
            'OUTPUT': 'memory:Reprojected'
        }
        logger.info(f'Parameters: {str(parameter)}')
        result = processing.run('native:reprojectlayer', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info("Reproject finished")
        return result
    except Exception as error:
        logger.error("An error occured reprojectiong layer")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

simplify(layer, method, tolerance)

Simplifies the geometries in a line or polygon layer. It creates a new layer with the same features as the ones in the input layer, but with geometries containing a lower number of vertices. QGIS processing algorithem: native:simplifygeometries.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required
method integer

Simplification method. One of: 0 — Distance (Douglas-Peucker), 1 — Snap to grid, 2 — Area (Visvalingam)

required
tolerance integer

Threshold tolerance (in units of the layer): if the distance between two nodes is smaller than the tolerance value, the segment will be simplified and vertices will be removed.

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
def simplify(layer: QgsVectorLayer, method: int, tolerance:int):
        """
        Simplifies the geometries in a line or polygon layer. 
        It creates a new layer with the same features as the ones in the input layer, but with geometries containing a lower number of vertices.
        QGIS processing algorithem: native:simplifygeometries.

        Args:
            layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
            method (integer): Simplification method. One of: 0 — Distance (Douglas-Peucker), 1 — Snap to grid, 2 — Area (Visvalingam)
            tolerance (integer): Threshold tolerance (in units of the layer): if the distance between two nodes is smaller than the tolerance value, the segment will be simplified and vertices will be removed.

        Returns:
            layer (QgsVectorLayer): The result output from the algorithem
        """

        logger.info("Running simplify")
        if layerHasFeatures(layer):
            logger.info("Processing " + str(layer.featureCount()) +" features")
        try:
            parameter = {
                'INPUT': layer,
                'METHOD':method,
                'TOLERANCE':tolerance,
                'OUTPUT': 'memory:simplify'
            }
            logger.info(f'Parameters: {str(parameter)}')
            result = processing.run('native:simplifygeometries', parameter, feedback=Worker.progress)['OUTPUT']
            logger.info("Simplifygeometries finished")
            return result
        except Exception as error:
            logger.error("An error occured in simplifygeometries")
            logger.error(f'{type(error).__name__}{str(error)}')
            logger.critical("Program terminated" )
            sys.exit()

spatialindex(layer)

Creates an index to speed up access to the features in a layer based on their spatial location. Support for spatial index creation is dependent on the layer's data provider.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
def spatialindex(layer: QgsVectorLayer):
    """
    Creates an index to speed up access to the features in a layer based on their spatial location.
    Support for spatial index creation is dependent on the layer's data provider.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info("Crating spatial index on " + layer)
    try:
        parameter = {
            'INPUT': layer,
            'OUTPUT': 'memory:extracted'
        }
        result = processing.run('native:createspatialindex', parameter, feedback=Worker.progress)['OUTPUT']
        logger.info(f'Parameters: {str(parameter)}')
        logger.info("createspatialindex  finished")
        return result
    except Exception as error:
        logger.error("An error occured in createspatialindex")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        sys.exit()

symmetricaldifference(inputlayer, overlay_layer)

Creates a layer containing features from both the input and overlay layers but with the overlapping areas between the two layers removed. The attribute table of the symmetrical difference layer contains attributes and fields from both the input and overlay layers.

Parameters:

Name Type Description Default
inputlayer QgsVectorLayer

First layer to extract (parts of) features from.

required
overlay_layer QgsVectorLayer

Second layer to extract (parts of) features from. Ideally the geometry type should be the same as input layer.

required

Returns:

Name Type Description
layer QgsVectorLayer

Specify the layer to contain (the parts of) the features from the input and overlay layers that do not overlap features from the other layer

Source code in python\engine\workers.py
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
def symmetricaldifference(inputlayer: QgsVectorLayer, overlay_layer: QgsVectorLayer):
    """
    Creates a layer containing features from both the input and overlay layers but with the overlapping areas between the two layers removed.
    The attribute table of the symmetrical difference layer contains attributes and fields from both the input and overlay layers.

    Args:
        inputlayer (QgsVectorLayer): First layer to extract (parts of) features from.
        overlay_layer (QgsVectorLayer): Second layer to extract (parts of) features from. Ideally the geometry type should be the same as input layer.

    Returns:
        layer (QgsVectorLayer): Specify the layer to contain (the parts of) the features from the input and overlay layers that do not overlap features from the other layer
    """

    logger.info('calcualting symetrical difference')
    try:
        parameters = {
            'INPUT': inputlayer,
            'OVERLAY' : overlay_layer,
            'OUTPUT': 'memory:output_from_symmetricaldifference'
        }
        logger.info(f'Parameters: {str(parameters)}')
        result = processing.run('native:symmetricaldifference', parameters, feedback=Worker.progress)['OUTPUT']
        logger.info('Symmetricaldifference finished')
        return result
    except Exception as error:
        logger.error("An error occured in symmetricaldifference")
        logger.error(f'{type(error).__name__}{str(error)}')
        logger.critical("Program terminated" )
        script_failed()

timeStamper(layer, ts_fieldname)

Create an attribute woth current timestamp on features.

Parameters:

Name Type Description Default
layer QgsVectorLayer

The QgsVectorLayer input for the algorithem

required
ts_fieldname string

The name of the new timestamp field

required

Returns:

Name Type Description
layer QgsVectorLayer

The result output from the algorithem

Source code in python\engine\workers.py
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
def timeStamper(layer: QgsVectorLayer, ts_fieldname: str):
    """
    Create an attribute woth current timestamp on features.

    Args:
        layer (QgsVectorLayer): The QgsVectorLayer input for the algorithem
        ts_fieldname (string): The name of the new timestamp field

    Returns:
        layer (QgsVectorLayer): The result output from the algorithem
    """

    logger.info(f'Creating timestamp {ts_fieldname} using fieldCalculator')
    newLayer = Worker.fieldCalculator(layer, ts_fieldname, 5, 0, 0, ' now() ')
    return newLayer