def __init__(self, graph: Graph, matrix: Matrix) -> None:
        if not np.array_equal(matrix.index, graph.centroids):
            raise ValueError("Matrix and graph do not have compatible sets of centroids.")

        self.graph = graph
        self.matrix = matrix
        self.pce = 1
        self.mode = graph.mode
        self.class_flow: np.array
        self.results = AssignmentResults()
        self.results.prepare(self.graph, self.matrix)
        self.results.reset()
        self._aon_results = AssignmentResults()
        self._aon_results.prepare(self.graph, self.matrix)
    def test_set_cores(self):
        a = AssignmentResults()
        a.set_cores(10)

        with self.assertRaises(ValueError):
            a.set_cores(1.3)

        a.set_cores(-2)
        self.assertEqual(a.cores, max(1, mp.cpu_count() - 2))
    def test_set_cores(self):
        a = AssignmentResults()
        a.set_cores(10)

        with self.assertRaises(ValueError):
            a.set_cores(1.3)

        with self.assertRaises(ValueError):
            a.set_cores(-2)
    def test_execute(self):
        # Loads and prepares the graph
        res1 = AssignmentResults()
        res1.prepare(self.g, self.matrix)
        assig1 = allOrNothing(self.matrix, self.g, res1)
        assig1.execute()

        res2 = AssignmentResults()
        res2.prepare(self.g, self.matrix2)
        assig2 = allOrNothing(self.matrix2, self.g, res2)
        assig2.execute()

        load1 = res1.get_load_results()
        load2 = res2.get_load_results()

        self.assertEqual(list(load1.matrix_tot * 2), list(load2.matrix_tot),
                         "Something wrong with the AoN")
Exemple #5
0
    def __init__(self, graph: Graph, matrix: AequilibraeMatrix) -> None:
        """
        Instantiates the class

         Args:
            graph (:obj:`Graph`): Class/mode-specific graph

            matrix (:obj:`AequilibraeMatrix`): Class/mode-specific matrix. Supports multiple user classes
        """
        if not np.array_equal(matrix.index, graph.centroids):
            raise ValueError("Matrix and graph do not have compatible sets of centroids.")

        self.graph = graph
        self.matrix = matrix
        self.pce = 1
        self.mode = graph.mode
        self.class_flow: np.array
        self.results = AssignmentResults()
        self.results.prepare(self.graph, self.matrix)
        self.results.reset()
        self._aon_results = AssignmentResults()
        self._aon_results.prepare(self.graph, self.matrix)
    def __init__(self, name: str, graph: Graph,
                 matrix: AequilibraeMatrix) -> None:
        """
        Instantiates the class

         Args:
            name (:obj:`str`): UNIQUE class name.

            graph (:obj:`Graph`): Class/mode-specific graph

            matrix (:obj:`AequilibraeMatrix`): Class/mode-specific matrix. Supports multiple user classes
        """
        if not np.array_equal(matrix.index, graph.centroids):
            raise ValueError(
                "Matrix and graph do not have compatible sets of centroids.")

        if matrix.matrix_view.dtype != graph.default_types('float'):
            raise TypeError(
                "Matrix's computational view need to be of type np.float64")

        self.graph = graph
        self.matrix = matrix
        self.pce = 1.0
        self.vot = 1.0
        self.mode = graph.mode
        self.class_flow: np.array
        self.results = AssignmentResults()
        self.results.prepare(self.graph, self.matrix)
        self.fixed_cost = np.zeros(graph.graph.shape[0],
                                   graph.default_types('float'))
        self.fixed_cost_field = ''
        self.fc_multiplier = 1.0
        self.results.reset()
        self._aon_results = AssignmentResults()
        self._aon_results.prepare(self.graph, self.matrix)
        self.__id__ = name
class TrafficClass():
    """Traffic class for equilibrium traffic assignment

    ::

        from aequilibrae.paths import TrafficClass

        tc = TrafficClass(graph, demand_matrix)
        tc.set_pce(1.3)
    """
    def __init__(self, graph: Graph, matrix: AequilibraeMatrix) -> None:
        """
        Instantiates the class

         Args:
            graph (:obj:`Graph`): Class/mode-specific graph

            matrix (:obj:`AequilibraeMatrix`): Class/mode-specific matrix. Supports multiple user classes
        """
        if not np.array_equal(matrix.index, graph.centroids):
            raise ValueError(
                "Matrix and graph do not have compatible sets of centroids.")

        self.graph = graph
        self.matrix = matrix
        self.pce = 1
        self.mode = graph.mode
        self.class_flow: np.array
        self.results = AssignmentResults()
        self.results.prepare(self.graph, self.matrix)
        self.results.reset()
        self._aon_results = AssignmentResults()
        self._aon_results.prepare(self.graph, self.matrix)
        self._id = uuid4().hex

    def set_pce(self, pce: Union[float, int]) -> None:
        """Sets Passenger Car equivalent

        Args:
            pce (:obj:`Union[float, int]`): PCE. Defaults to 1 if not set
        """
        if not isinstance(pce, (float, int)):
            raise ValueError('PCE needs to be either integer or float ')
        self.pce = pce
class TrafficClass():
    def __init__(self, graph: Graph, matrix: Matrix) -> None:
        if not np.array_equal(matrix.index, graph.centroids):
            raise ValueError("Matrix and graph do not have compatible sets of centroids.")

        self.graph = graph
        self.matrix = matrix
        self.pce = 1
        self.mode = graph.mode
        self.class_flow: np.array
        self.results = AssignmentResults()
        self.results.prepare(self.graph, self.matrix)
        self.results.reset()
        self._aon_results = AssignmentResults()
        self._aon_results.prepare(self.graph, self.matrix)

    def set_pce(self, pce: Union[float, int]) -> None:
        if not isinstance(pce, (float, int)):
            raise ValueError('PCE needs to be either integer or float ')
        self.pce = pce
    def test_skimming_on_assignment(self):

        res = AssignmentResults()

        res.prepare(self.g, self.matrix)

        self.g.set_skimming([])
        self.g.set_blocked_centroid_flows(True)
        assig = allOrNothing(self.matrix, self.g, res)
        assig.execute()

        if res.skims.distance.sum() > 0:
            self.fail(
                "skimming for nothing during assignment returned something different than zero"
            )

        res.prepare(self.g, self.matrix)

        assig = allOrNothing(self.matrix, self.g, res)
        assig.execute()
Exemple #10
0
    def __init__(self, assig_spec, algorithm) -> None:
        WorkerThread.__init__(self, None)
        self.algorithm = algorithm
        self.rgap_target = assig_spec.rgap_target
        self.max_iter = assig_spec.max_iter
        self.cores = assig_spec.cores

        self.assig = assig_spec  # type: TrafficAssignment

        if None in [
                assig_spec.classes,
                assig_spec.vdf,
                assig_spec.capacity_field,
                assig_spec.time_field,
                assig_spec.vdf_parameters,
        ]:
            all_par = 'Traffic classes, VDF, VDF_parameters, capacity field & time_field'
            raise Exception(
                "Parameter missing. Setting the algorithm is the last thing to do "
                f"when assigning. Check if you have all of these: {all_par}")

        self.traffic_classes = assig_spec.classes  # type: List[TrafficClass]
        self.num_classes = len(assig_spec.classes)

        self.cap_field = assig_spec.capacity_field
        self.time_field = assig_spec.time_field
        self.vdf = assig_spec.vdf
        self.vdf_parameters = assig_spec.vdf_parameters

        self.iter = 0
        self.rgap = np.inf
        self.stepsize = 1.0
        self.conjugate_stepsize = 0.0
        self.fw_class_flow = 0
        # rgap can be a bit wiggly, specifying how many times we need to be below target rgap is a quick way to
        # ensure a better result. We might want to demand that the solution is that many consecutive times below.
        self.steps_below_needed_to_terminate = 1
        self.steps_below = 0

        # if this is one, we do not have a new direction and will get stuck. Make it 1.
        self.conjugate_direction_max = 0.99999

        # if FW stepsize is zero, we set it to the corresponding MSA stepsize and then need to not make
        # the step direction conjugate to the previous direction.
        self.do_fw_step = False
        self.do_conjugate_step = False

        # BFW specific stuff
        self.betas = np.array([1.0, 0.0, 0.0])

        # Instantiates the arrays that we will use over and over
        self.capacity = assig_spec.capacity
        self.free_flow_tt = assig_spec.free_flow_tt
        self.fw_total_flow = assig_spec.total_flow
        self.congested_time = assig_spec.congested_time
        self.vdf_der = np.array(assig_spec.congested_time, copy=True)
        self.congested_value = np.array(assig_spec.congested_time, copy=True)

        self.step_direction = {}  # type: Dict[AssignmentResults]
        self.previous_step_direction = {}  # type: Dict[AssignmentResults]
        self.pre_previous_step_direction = {}  # type: Dict[AssignmentResults]

        for c in self.traffic_classes:
            r = AssignmentResults()
            r.prepare(c.graph, c.matrix)
            self.step_direction[c.mode] = r

        if self.algorithm in ['cfw', 'bfw']:

            for c in self.traffic_classes:
                r = AssignmentResults()
                r.prepare(c.graph, c.matrix)
                self.previous_step_direction[c.mode] = r

                r = AssignmentResults()
                r.prepare(c.graph, c.matrix)
                self.step_direction[c.mode] = r

                r = AssignmentResults()
                r.prepare(c.graph, c.matrix)
                self.pre_previous_step_direction[c.mode] = r
Exemple #11
0
    def doWork(self):
        if self.error is None:
            # In case we have only one class
            unnasigned = 0
            classes = self.matrix.matrix_view.shape[2]

            layer = get_vector_layer_by_name(self.layer)
            idx = layer.dataProvider().fieldNameIndex(self.id_field)
            feature_count = layer.featureCount()
            self.desire_lines.emit(('job_size_dl', feature_count))

            all_centroids = {}
            for P, feat in enumerate(layer.getFeatures()):
                geom = feat.geometry()
                if geom is not None:
                    point = list(geom.centroid().asPoint())
                    centroid_id = feat.attributes()[idx]
                    all_centroids[centroid_id] = point
                self.desire_lines.emit(('jobs_done_dl', P))
                self.desire_lines.emit(('text_dl', "Loading Layer Features: " + str(P) + "/" + str(feature_count)))

            # Creating resulting layer
            EPSG_code = int(layer.crs().authid().split(":")[1])

            desireline_layer = QgsVectorLayer("LineString?crs=epsg:" + str(EPSG_code), self.dl_type, "memory")
            dlpr = desireline_layer.dataProvider()
            base_dl_fields = [QgsField("link_id", QVariant.Int),
                              QgsField("A_Node", QVariant.Int),
                              QgsField("B_Node", QVariant.Int),
                              QgsField("direct", QVariant.Int),
                              QgsField("distance", QVariant.Double)]

            if self.dl_type == "DesireLines":
                items = []
                for i, j in all_centroids.items():
                    items.append((i, j[0], j[1]))
                coords = np.array(items)

                coord_index = np.zeros((self.matrix.index[:].max().astype(np.int64) + 1, 2))
                coord_index[coords[:, 0].astype(np.int64), 0] = coords[:, 1]
                coord_index[coords[:, 0].astype(np.int64), 1] = coords[:, 2]

                self.desire_lines.emit(('text_dl', "Manipulating matrix indices"))
                zones = self.matrix.index[:].shape[0]
                a = np.array(self.matrix.index[:], np.int64)
                ij, ji = np.meshgrid(a, a, sparse=False, indexing='ij')
                ij = ij.flatten()
                ji = ji.flatten()

                arrays = [ij, ji]

                self.desire_lines.emit(('text_dl', "Collecting all matrices"))
                self.desire_lines.emit(('job_size_dl', len(self.matrix.view_names)))

                total_mat = np.zeros((zones, zones), np.float64)
                for i, mat in enumerate(self.matrix.view_names):
                    arrays.append(self.matrix.matrix[mat].flatten())
                    total_mat += self.matrix.matrix[mat]
                    self.desire_lines.emit(('jobs_done_dl', i + 1))

                # Eliminates the cells for which we don't have geography
                self.desire_lines.emit(('text_dl', "Filtering zones with no geography available"))
                zones_with_no_geography = [x for x in self.matrix.index[:] if x not in all_centroids]
                if zones_with_no_geography:
                    self.desire_lines.emit(('job_size_dl', len(zones_with_no_geography)))
                for k, z in enumerate(zones_with_no_geography):
                    i = self.matrix.matrix_hash[z]
                    t = np.nansum(total_mat[i, :]) + np.nansum(total_mat[:, i])
                    unnasigned += t
                    self.report.append(
                        'Zone {} does not have a corresponding centroid/zone. Total flow {}'.format(z, t))
                    total_mat[i, :] = 0
                    total_mat[:, i] = 0
                    self.desire_lines.emit(('jobs_done_dl', k + 1))

                self.desire_lines.emit(('text_dl', "Filtering down to OD pairs with flows"))
                field_names = [x for x in self.matrix.view_names]
                nonzero = np.nonzero(total_mat.flatten())
                arrays = np.vstack(arrays).transpose()
                arrays = arrays[nonzero, :]
                arrays = arrays.reshape(arrays.shape[1], arrays.shape[2])

                base_types = [(x, np.float64) for x in ['from', 'to']]
                base_types = base_types + [(x + '_AB', np.float64) for x in field_names]

                dtypes_ab = [(x, np.int64) for x in ['from', 'to']] + [(x + '_AB', float) for x in field_names]
                dtypes_ba = [(x, np.int64) for x in ['to', 'from']] + [(x + '_BA', float) for x in field_names]

                ab_mat = np.array(arrays[arrays[:, 0] > arrays[:, 1], :])
                ba_mat = np.array(arrays[arrays[:, 0] < arrays[:, 1], :])

                flows_ab = ab_mat.view(base_types)
                flows_ab = flows_ab.reshape(flows_ab.shape[:-1])
                flows_ab = flows_ab.astype(dtypes_ab)

                flows_ba = ba_mat.view(base_types)
                flows_ba = flows_ba.reshape(flows_ba.shape[:-1])
                flows_ba = flows_ba.astype(dtypes_ba)

                defaults1 = {x + '_AB': 0.0 for x in field_names}
                defaults = {x + '_BA': 0.0 for x in field_names}
                defaults = {**defaults, **defaults1}

                self.desire_lines.emit(('text_dl', "Concatenating AB & BA flows"))
                flows = rfn.join_by(['from', 'to'], flows_ab, flows_ba, jointype='outer', defaults=defaults,
                                    usemask=True, asrecarray=True)
                flows = flows.filled()
                flows_ab = 0
                flows_ba = 0

                for f in flows.dtype.names[2:]:
                    base_dl_fields.extend([QgsField(f, QVariant.Double)])

                dlpr.addAttributes(base_dl_fields)
                desireline_layer.updateFields()

                self.desire_lines.emit(('text_dl', "Creating Desire Lines"))
                self.desire_lines.emit(('job_size_dl', flows.shape[0]))
                all_features = []
                for i, rec in enumerate(flows):
                    a_node = rec[0]
                    b_node = rec[1]

                    a_point = QgsPointXY(*all_centroids[a_node])
                    b_point = QgsPointXY(*all_centroids[b_node])
                    dist = QgsGeometry().fromPointXY(a_point).distance(
                        QgsGeometry().fromPointXY(b_point))
                    feature = QgsFeature()
                    feature.setGeometry(QgsGeometry.fromPolylineXY([a_point, b_point]))

                    attrs = [i + 1, int(a_node), int(b_node), 0, dist]
                    attrs.extend([float(x) for x in list(rec)[2:]])
                    feature.setAttributes(attrs)
                    all_features.append(feature)
                    self.desire_lines.emit(('jobs_done_dl', i))
                if unnasigned > 0:
                    self.report.append('Total non assigned flows (not counting intrazonals):' + str(unnasigned))

                if flows.shape[0] > 1:
                    a = dlpr.addFeatures(all_features)
                    self.result_layer = desireline_layer
                else:
                    self.report.append('Nothing to show')

            elif self.dl_type == "DelaunayLines":

                for f in self.matrix.view_names:
                    base_dl_fields.extend([QgsField(f + '_ab', QVariant.Double),
                                           QgsField(f + '_ba', QVariant.Double),
                                           QgsField(f + '_tot', QVariant.Double)])

                dlpr.addAttributes(base_dl_fields)
                desireline_layer.updateFields()

                self.desire_lines.emit(('text_dl', "Building Delaunay dataset"))
                points = []
                node_id_in_delaunay_results = {}
                i = 0
                self.desire_lines.emit(('job_size_dl', len(all_centroids)))
                for k, v in all_centroids.items():
                    self.desire_lines.emit(('jobs_done_dl', i))
                    points.append(v)
                    node_id_in_delaunay_results[i] = k
                    i += 1

                self.desire_lines.emit(('text_dl', "Computing Delaunay Triangles"))
                tri = Delaunay(np.array(points))

                # We process all the triangles to only get each edge once
                self.desire_lines.emit(('text_dl', "Building Delaunay Network: Collecting Edges"))
                edges = []
                if self.python_version == 32:
                    all_edges = tri.vertices
                else:
                    all_edges = tri.simplices

                self.desire_lines.emit(('job_size_dl', len(all_edges)))

                for j, triangle in enumerate(all_edges):
                    self.desire_lines.emit(('jobs_done_dl', j))
                    links = list(itertools.combinations(triangle, 2))
                    for i in links:
                        edges.append([min(i[0], i[1]), max(i[0], i[1])])

                self.desire_lines.emit(('text_dl', "Building Delaunay Network: Getting unique edges"))
                edges = OrderedDict((str(x), x) for x in edges).values()

                # Writing Delaunay layer
                self.desire_lines.emit(('text_dl', "Building Delaunay Network: Assembling Layer"))

                desireline_link_id = 1
                data = []
                dl_ids_on_links = {}
                self.desire_lines.emit(('job_size_dl', len(edges)))
                for j, edge in enumerate(edges):
                    self.desire_lines.emit(('jobs_done_dl', j))
                    a_node = node_id_in_delaunay_results[edge[0]]
                    a_point = all_centroids[a_node]
                    a_point = QgsPointXY(a_point[0], a_point[1])
                    b_node = node_id_in_delaunay_results[edge[1]]
                    b_point = all_centroids[b_node]
                    b_point = QgsPointXY(b_point[0], b_point[1])
                    dist = QgsGeometry().fromPointXY(a_point).distance(QgsGeometry().fromPointXY(b_point))
                    line = []
                    line.append(desireline_link_id)
                    line.append(a_node)
                    line.append(b_node)
                    line.append(dist)
                    line.append(dist)
                    line.append(0)
                    data.append(line)
                    dl_ids_on_links[desireline_link_id] = [a_node, b_node, 0, dist]
                    desireline_link_id += 1

                self.desire_lines.emit(('text_dl', "Building graph"))
                network = np.asarray(data)
                del data

                # types for the network
                self.graph = Graph()
                itype = self.graph.default_types('int')
                ftype = self.graph.default_types('float')
                all_types = [itype, itype, itype, ftype, ftype, np.int8]
                all_titles = ['link_id', 'a_node', 'b_node', 'distance_ab', 'distance_ba', 'direction']
                dt = [(t, d) for t, d in zip(all_titles, all_types)]
                self.graph.network = np.zeros(network.shape[0], dtype=dt)

                for k, t in enumerate(dt):
                    self.graph.network[t[0]] = network[:, k].astype(t[1])
                del network

                self.graph.type_loaded = 'NETWORK'
                self.graph.status = 'OK'
                self.graph.network_ok = True
                self.graph.prepare_graph(self.matrix.index.astype(np.int64))
                self.graph.set_graph(cost_field='distance', skim_fields=False, block_centroid_flows=False)

                self.results = AssignmentResults()
                self.results.prepare(self.graph, self.matrix)
                self.desire_lines.emit(('text_dl', "Assigning demand"))
                self.desire_lines.emit(('job_size_dl', self.matrix.index.shape[0]))

                assigner = allOrNothing(self.matrix, self.graph, self.results)
                assigner.execute()
                self.report = assigner.report
                print(self.results.link_loads)
                self.desire_lines.emit(('text_dl', "Collecting results"))
                self.desire_lines.emit(('text_dl', "Building resulting layer"))
                features = []
                max_edges = len(edges)
                self.desire_lines.emit(('job_size_dl', max_edges))
                link_loads = self.results.save_to_disk()
                for i, link_id in enumerate(link_loads.index):
                    self.desire_lines.emit(('jobs_done_dl', i))
                    a_node, b_node, direct, dist = dl_ids_on_links[link_id]

                    attr = [int(link_id), a_node, b_node, direct, dist]

                    a_point = all_centroids[a_node]
                    a_point = QgsPointXY(a_point[0], a_point[1])
                    b_point = all_centroids[b_node]
                    b_point = QgsPointXY(b_point[0], b_point[1])

                    feature = QgsFeature()
                    feature.setGeometry(QgsGeometry.fromPolylineXY([a_point, b_point]))

                    for c in self.matrix.view_names:
                        attr.extend([float(link_loads.data[c + '_ab'][i]),
                                     float(link_loads.data[c + '_ba'][i]),
                                     float(link_loads.data[c + '_tot'][i])])
                    feature.setAttributes(attr)
                    features.append(feature)
                a = dlpr.addFeatures(features)
                self.result_layer = desireline_layer

        self.desire_lines.emit(('finished_desire_lines_procedure', 0))
class TrafficClass():
    """Traffic class for equilibrium traffic assignment

    ::

        from aequilibrae.paths import TrafficClass

        tc = TrafficClass(graph, demand_matrix)
        tc.set_pce(1.3)
    """
    def __init__(self, name: str, graph: Graph,
                 matrix: AequilibraeMatrix) -> None:
        """
        Instantiates the class

         Args:
            name (:obj:`str`): UNIQUE class name.

            graph (:obj:`Graph`): Class/mode-specific graph

            matrix (:obj:`AequilibraeMatrix`): Class/mode-specific matrix. Supports multiple user classes
        """
        if not np.array_equal(matrix.index, graph.centroids):
            raise ValueError(
                "Matrix and graph do not have compatible sets of centroids.")

        if matrix.matrix_view.dtype != graph.default_types('float'):
            raise TypeError(
                "Matrix's computational view need to be of type np.float64")

        self.graph = graph
        self.matrix = matrix
        self.pce = 1.0
        self.vot = 1.0
        self.mode = graph.mode
        self.class_flow: np.array
        self.results = AssignmentResults()
        self.results.prepare(self.graph, self.matrix)
        self.fixed_cost = np.zeros(graph.graph.shape[0],
                                   graph.default_types('float'))
        self.fixed_cost_field = ''
        self.fc_multiplier = 1.0
        self.results.reset()
        self._aon_results = AssignmentResults()
        self._aon_results.prepare(self.graph, self.matrix)
        self.__id__ = name

    def set_pce(self, pce: Union[float, int]) -> None:
        """Sets Passenger Car equivalent

        Args:
            pce (:obj:`Union[float, int]`): PCE. Defaults to 1 if not set
        """
        if not isinstance(pce, (float, int)):
            raise ValueError('PCE needs to be either integer or float ')
        self.pce = pce

    def set_fixed_cost(self, field_name: str, multiplier=1):
        """Sets value of time

        Args:
            field_name (:obj:`str`): Name of the graph field with fixed costs for this class
            multiplier (:obj:`Union[float, int]`): Multiplier for the fixed cost. Defaults to 1 if not set
        """
        self.fc_multiplier = float(multiplier)
        if field_name not in self.graph.graph.columns:
            raise ValueError('Field does not exist in the graph')

        self.fixed_cost_field = field_name
        if np.any(np.isnan(self.graph.graph[field_name].values)):
            logger.warning(
                f'Cost field {field_name} has NaN values. Converted to zero')

        if self.graph.graph[field_name].min() < 0:
            msg = f'Cost field {field_name} has negative values. That is not allowed'
            logger.error(msg)
            raise ValueError(msg)

    def set_vot(self, value_of_time: float) -> None:
        """Sets value of time

        Args:
            value_of_time (:obj:`Union[float, int]`): Value of time. Defaults to 1 if not set
        """

        self.vot = float(value_of_time)

    def __setattr__(self, key, value):

        if key not in [
                'graph', 'matrix', 'pce', 'mode', 'class_flow', 'results',
                '_aon_results', '__id__', 'vot', 'fixed_cost', 'fc_multiplier',
                'fixed_cost_field'
        ]:
            raise KeyError('Traffic Class does not have that element')
        self.__dict__[key] = value
Exemple #13
0
    def doWork(self):
        if self.error is None:
            layer = get_vector_layer_by_name(self.layer)
            idx = layer.fieldNameIndex(self.id_field)
            matrix = self.matrix

            featcount = layer.featureCount()
            self.emit(SIGNAL("ProgressMaxValue(PyQt_PyObject)"),
                      (0, featcount))

            P = 0
            points = []
            point_ids = []
            for feat in layer.getFeatures():
                P += 1
                self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"), (0, int(P)))
                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Loading Layer Features: " + str(P) + "/" +
                           str(featcount)))

                geom = feat.geometry()
                if geom is not None:
                    point = list(geom.centroid().asPoint())
                    points.append(point)
                    point_ids.append(feat.attributes()[idx])

            points = np.array(points)
            self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"), (0, featcount))

            self.emit(
                SIGNAL("ProgressText (PyQt_PyObject)"),
                (0, "Preparing consistency check Matrix Vs. Zoning layer"))

            vector1 = np.nonzero(np.sum(matrix, axis=0))[0]
            vector2 = np.nonzero(np.sum(matrix, axis=1))[0]
            nonzero = np.hstack((vector1, vector2))

            self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"),
                      (0, nonzero.shape[0]))
            for i, zone in enumerate(nonzero):
                if zone not in point_ids:
                    self.error = 'Zone ' + str(
                        zone) + ' with positive flow not in zoning file'
                    break
                self.emit(SIGNAL("ProgressMaxValue(PyQt_PyObject)"),
                          (0, i + 1))
            self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"),
                      (0, nonzero.shape[0]))

        if self.error is None:

            #Creating resulting layer
            EPSG_code = int(layer.crs().authid().split(":")[1])

            desireline_layer = QgsVectorLayer(
                "LineString?crs=epsg:" + str(EPSG_code), self.dl_type,
                "memory")
            dlpr = desireline_layer.dataProvider()
            dlpr.addAttributes([
                QgsField("link_id", QVariant.Int),
                QgsField("A_Node", QVariant.Int),
                QgsField("B_Node", QVariant.Int),
                QgsField("direct", QVariant.Int),
                QgsField("length", QVariant.Double),
                QgsField("AB_FLOW", QVariant.Double),
                QgsField("BA_FLOW", QVariant.Double),
                QgsField("TOT_FLOW", QVariant.Double)
            ])
            desireline_layer.updateFields()

            if self.dl_type == "DesireLines":
                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Creating Desire Lines"))
                self.emit(SIGNAL("ProgressMaxValue(PyQt_PyObject)"),
                          (0, self.matrix.shape[0] * self.matrix.shape[1] / 2))

                #We create the dictionary with point information
                all_points = {}
                point_ids = np.array(point_ids).astype(np.int)
                for i in range(point_ids.shape[0]):
                    all_points[point_ids[i]] = points[i]

                # We are assuming that the matrix is square here. Maybe we could add more general code layer
                desireline_link_id = 1
                q = 0
                all_features = []
                for i in range(self.matrix.shape[0]):
                    for j in xrange(i + 1, self.matrix.shape[1]):
                        q += 1
                        self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"),
                                  (0, q))
                        if self.matrix[i, j] + self.matrix[j, i] > 0:
                            a_node = i
                            a_point = QgsPoint(all_points[a_node][0],
                                               all_points[a_node][1])
                            b_node = j
                            b_point = QgsPoint(all_points[b_node][0],
                                               all_points[b_node][1])
                            dist = QgsGeometry().fromPoint(a_point).distance(
                                QgsGeometry().fromPoint(b_point))
                            feature = QgsFeature()
                            feature.setGeometry(
                                QgsGeometry.fromPolyline([a_point, b_point]))
                            feature.setAttributes([
                                desireline_link_id, a_node, b_node, 0, dist,
                                float(self.matrix[i, j]),
                                float(self.matrix[j, i]),
                                float(self.matrix[i, j] + self.matrix[j, i])
                            ])
                            all_features.append(feature)

                            desireline_link_id += 1
                a = dlpr.addFeatures(all_features)
                self.result_layer = desireline_layer

            elif self.dl_type == "DelaunayLines":
                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Computing Delaunay Triangles"))
                tri = Delaunay(points)

                #We process all the triangles to only get each edge once
                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Building Delaunay Network: Collecting Edges"))
                edges = []
                for triangle in tri.simplices:
                    links = list(itertools.combinations(triangle, 2))

                    for i in links:
                        l = [min(i[0], i[1]), max(i[0], i[1])]
                        if l not in edges:
                            edges.append(l)

                #Writing Delaunay layer
                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Building Delaunay Network: Assembling Layer"))
                desireline_link_id = 1
                data = []
                for edge in edges:
                    a_node = edge[0]
                    a_point = QgsPoint(points[a_node][0], points[a_node][1])
                    b_node = edge[1]
                    b_point = QgsPoint(points[b_node][0], points[b_node][1])
                    dist = QgsGeometry().fromPoint(a_point).distance(
                        QgsGeometry().fromPoint(b_point))
                    line = []
                    line.append(desireline_link_id)
                    line.append(point_ids[a_node])
                    line.append(point_ids[b_node])
                    line.append(dist)
                    line.append(dist)
                    line.append(0)
                    data.append(line)
                    desireline_link_id += 1

                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Building graph"))
                network = np.asarray(data)
                del data

                #types for the network
                all_types = [
                    np.int64, np.int64, np.int64, np.float64, np.float64,
                    np.int64
                ]
                all_titles = [
                    'link_id', 'a_node', 'b_node', 'length_ab', 'length_ba',
                    'direction'
                ]
                dt = [(t, d) for t, d in zip(all_titles, all_types)]

                self.graph = Graph()
                self.graph.network = np.zeros(network.shape[0], dtype=dt)

                for k, t in enumerate(dt):
                    self.graph.network[t[0]] = network[:, k].astype(t[1])
                del network

                # Here we transform the network to go from node 1 to N
                max_node = max(np.max(self.graph.network['a_node']),
                               np.max(self.graph.network['b_node']))
                max_node = max(max_node, self.matrix.shape[0],
                               self.matrix.shape[1]) + 1
                self.hash = np.zeros(max_node, np.int)

                # Checks if any zone from the matrix is not present in the areas/node layer
                t1 = np.sum(self.matrix, axis=0)
                t2 = np.sum(self.matrix, axis=1)

                if t1.shape[0] > t2.shape[0]:
                    t2.resize(t1.shape)
                elif t2.shape[0] > t1.shape[0]:
                    t1.resize(t2.shape)
                totals = t1 + t2

                all_nodes = np.bincount(self.graph.network['a_node'])
                for i in range(totals.shape[0]):
                    if totals[i]:
                        if not all_nodes[i]:
                            qgis.utils.iface.messageBar().pushMessage(
                                "Matrix has demand for zones that do not exist "
                                "in the zones/nodes provided. Demand for those"
                                "ones were ignored. e.g. " + str(i),
                                '',
                                level=3)
                            break

                h = 1
                for i in range(self.graph.network.shape[0]):
                    a_node = self.graph.network['a_node'][i]
                    if self.hash[a_node] == 0:
                        self.hash[a_node] = h
                        h += 1

                    b_node = self.graph.network['b_node'][i]
                    if self.hash[b_node] == 0:
                        self.hash[b_node] = h
                        h += 1

                    self.graph.network['a_node'][i] = self.hash[a_node]
                    self.graph.network['b_node'][i] = self.hash[b_node]
                # End of network transformation

                #Now we transform the matrix appropriately
                self.matrix = reblocks_matrix(self.matrix, self.hash, h)

                self.graph.type_loaded = 'NETWORK'
                self.graph.status = 'OK'
                self.graph.network_ok = True
                self.graph.prepare_graph()

                self.graph.set_graph(h - 1,
                                     cost_field='length',
                                     block_centroid_flows=False)
                self.results = AssignmentResults()
                self.results.prepare(self.graph)
                self.results.set_cores(1)

                # Do the assignment
                all_or_nothing(self.matrix, self.graph, self.results)

                f = self.results.link_loads[:, 0]
                link_loads = np.zeros((f.shape[0] + 1, 2))
                for i in range(f.shape[0] - 1):
                    direction = self.graph.graph['direction'][i]
                    link_id = self.graph.graph['link_id'][i]
                    flow = f[i]
                    if direction == 1:
                        link_loads[link_id, 0] = flow
                    else:
                        link_loads[link_id, 1] = flow

                desireline_link_id = 1
                for edge in edges:
                    a_node = edge[0]
                    a_point = QgsPoint(points[a_node][0], points[a_node][1])
                    b_node = edge[1]
                    b_point = QgsPoint(points[b_node][0], points[b_node][1])
                    dist = QgsGeometry().fromPoint(a_point).distance(
                        QgsGeometry().fromPoint(b_point))
                    feature = QgsFeature()
                    feature.setGeometry(
                        QgsGeometry.fromPolyline([a_point, b_point]))
                    feature.setAttributes([
                        desireline_link_id, point_ids[a_node],
                        point_ids[b_node], 0, dist,
                        float(link_loads[desireline_link_id, 0]),
                        float(link_loads[desireline_link_id, 1]),
                        float(link_loads[desireline_link_id, 0] +
                              link_loads[desireline_link_id, 1])
                    ])
                    a = dlpr.addFeatures([feature])
                    desireline_link_id += 1
                self.result_layer = desireline_layer

        self.emit(SIGNAL("finished_threaded_procedure( PyQt_PyObject )"), True)
    def doWork(self):
        if self.error is None:
            # In case we have only one class

            unnasigned = 0
            classes = self.matrix.matrix_view.shape[2]

            layer = get_vector_layer_by_name(self.layer)
            idx = layer.fieldNameIndex(self.id_field)
            feature_count = layer.featureCount()
            self.emit(SIGNAL("desire_lines"), ('job_size_dl', feature_count))

            all_centroids = {}
            P = 0
            for feat in layer.getFeatures():
                P += 1
                self.emit(SIGNAL("desire_lines"), ('jobs_done_dl', P))
                self.emit(SIGNAL("desire_lines"), ('text_dl',"Loading Layer Features: " + str(P) + "/" + str(feature_count)))
                geom = feat.geometry()
                if geom is not None:
                    point = list(geom.centroid().asPoint())
                    centroid_id = feat.attributes()[idx]
                    all_centroids[centroid_id] = point

            #Creating resulting layer
            EPSG_code = int(layer.crs().authid().split(":")[1])

            desireline_layer = QgsVectorLayer("LineString?crs=epsg:" + str(EPSG_code), self.dl_type, "memory")
            dlpr = desireline_layer.dataProvider()
            fields = [QgsField("link_id", QVariant.Int),
                              QgsField("A_Node", QVariant.Int),
                              QgsField("B_Node", QVariant.Int),
                              QgsField("direct", QVariant.Int),
                              QgsField("distance",  QVariant.Double)]
            for f in self.matrix.view_names:
                fields.extend([QgsField(f + '_ab',  QVariant.Double),
                              QgsField(f + '_ba',  QVariant.Double),
                              QgsField(f + '_tot',  QVariant.Double)])

            dlpr.addAttributes(fields)
            desireline_layer.updateFields()

            if self.dl_type == "DesireLines":
                self.emit(SIGNAL("desire_lines"), ('text_dl',"Creating Desire Lines"))
                self.emit(SIGNAL("desire_lines"), ('job_size_dl', self.matrix.zones ** 2 / 2))

                desireline_link_id = 1
                q = 0
                all_features = []
                for i in range(self.matrix.zones):
                    a_node = self.matrix.index[i]
                    if a_node in all_centroids.keys():
                        if np.sum(self.matrix.matrix_view[i, :, :]) + np.sum(self.matrix.matrix_view[:, i, :]) > 0:
                            columns_with_filled_cells = np.nonzero(np.sum(self.matrix.matrix_view[i, :, :], axis=1))
                            for j in columns_with_filled_cells[0]:
                                if np.sum(self.matrix.matrix_view[i, j, :]) + np.sum(self.matrix.matrix_view[j, i, :]) > 0:
                                    b_node = self.matrix.index[j]
                                    if a_node in all_centroids.keys() and b_node in all_centroids.keys():
                                        a_point = all_centroids[a_node]
                                        a_point = QgsPoint(a_point[0], a_point[1])
                                        b_point = all_centroids[b_node]
                                        b_point = QgsPoint(b_point[0], b_point[1])
                                        dist = QgsGeometry().fromPoint(a_point).distance(QgsGeometry().fromPoint(b_point))
                                        feature = QgsFeature()
                                        feature.setGeometry(QgsGeometry.fromPolyline([a_point, b_point]))
                                        attrs = [desireline_link_id, int(a_node), int(b_node), 0, dist]
                                        for c in range(classes):
                                            attrs.extend([float(self.matrix.matrix_view[i, j, c]),
                                                          float(self.matrix.matrix_view[j, i, c]),
                                                           float(self.matrix.matrix_view[i, j, c]) +
                                                          float(self.matrix.matrix_view[j, i, c])])

                                        feature.setAttributes(attrs)
                                        all_features.append(feature)
                                        desireline_link_id += 1
                                    else:
                                        tu = (a_node, b_node, np.sum(self.matrix.matrix_view[i, j, :]),
                                              np.sum(self.matrix.matrix_view[j, i, :]))
                                        self.report.append('No centroids available to depict flow between node {0} and node'
                                                           '{1}. Total AB flow was equal to {2} and total BA flow was '
                                                           'equal to {3}'.format(*tu))
                                        unnasigned += np.sum(self.matrix.matrix_view[i, j, :]) + \
                                                      np.sum(self.matrix.matrix_view[j, i, :])
                    else:
                        tu = (a_node, np.sum(self.matrix.matrix_view[i, :, :]))
                        self.report.append('No centroids available to depict flows from node {0} to all the others.'
                                           'Total flow from this zone is equal to {1}'.format(*tu))
                        unnasigned += np.sum(self.matrix.matrix_view[i, :, :])


                    q += self.matrix.zones
                    self.emit(SIGNAL("desire_lines"), ('jobs_done_dl', q))
                if unnasigned > 0:
                    self.report.append('Total non assigned flows (not counting intrazonals):' + str(unnasigned))

                if desireline_link_id > 1:
                    a = dlpr.addFeatures(all_features)
                    self.result_layer = desireline_layer
                else:
                    self.report.append('Nothing to show')

            elif self.dl_type == "DelaunayLines":

                self.emit(SIGNAL("desire_lines"), ('text_dl', "Building Delaunay dataset"))
                points = []
                node_id_in_delaunay_results = {}
                i = 0
                self.emit(SIGNAL("desire_lines"), ('job_size_dl', len(all_centroids)))
                for k, v in all_centroids.iteritems():
                    self.emit(SIGNAL("desire_lines"), ('jobs_done_dl', i))
                    points.append(v)
                    node_id_in_delaunay_results[i] = k
                    i += 1

                self.emit(SIGNAL("desire_lines"), ('text_dl', "Computing Delaunay Triangles"))
                tri = Delaunay(np.array(points))

                # We process all the triangles to only get each edge once
                self.emit(SIGNAL("desire_lines"), ('text_dl', "Building Delaunay Network: Collecting Edges"))
                edges = []
                if self.python_version == 32:
                    all_edges = tri.vertices
                else:
                    all_edges = tri.simplices

                self.emit(SIGNAL("desire_lines"), ('job_size_dl', len(all_edges)))
                for j, triangle in enumerate(all_edges):
                    self.emit(SIGNAL("desire_lines"), ('jobs_done_dl', j))
                    links = list(itertools.combinations(triangle, 2))
                    for i in links:
                        edges.append([min(i[0],i[1]), max(i[0],i[1])])

                self.emit(SIGNAL("desire_lines"), ('text_dl', "Building Delaunay Network: Getting unique edges"))
                edges = OrderedDict((str(x), x) for x in edges).values()

                # Writing Delaunay layer
                self.emit(SIGNAL("desire_lines"), ('text_dl', "Building Delaunay Network: Assembling Layer"))

                desireline_link_id = 1
                data = []
                dl_ids_on_links = {}
                self.emit(SIGNAL("desire_lines"), ('job_size_dl', len(edges)))
                for j, edge in enumerate(edges):
                    self.emit(SIGNAL("desire_lines"), ('jobs_done_dl', j))
                    a_node = node_id_in_delaunay_results[edge[0]]
                    a_point = all_centroids[a_node]
                    a_point = QgsPoint(a_point[0], a_point[1])
                    b_node = node_id_in_delaunay_results[edge[1]]
                    b_point = all_centroids[b_node]
                    b_point = QgsPoint(b_point[0], b_point[1])
                    dist = QgsGeometry().fromPoint(a_point).distance(QgsGeometry().fromPoint(b_point))
                    line = []
                    line.append(desireline_link_id)
                    line.append(a_node)
                    line.append(b_node)
                    line.append(dist)
                    line.append(dist)
                    line.append(0)
                    data.append(line)
                    dl_ids_on_links[desireline_link_id] = [a_node, b_node, 0, dist]
                    desireline_link_id += 1

                self.emit(SIGNAL("desire_lines"), ('text_dl', "Building graph"))
                network = np.asarray(data)
                del data

                #types for the network
                self.graph = Graph()
                itype = self.graph.default_types('int')
                ftype = self.graph.default_types('float')
                all_types = [itype, itype, itype, ftype, ftype, np.int8]
                all_titles = ['link_id', 'a_node', 'b_node', 'distance_ab', 'distance_ba', 'direction']
                dt = [(t, d) for t, d in zip(all_titles, all_types)]
                self.graph.network = np.zeros(network.shape[0], dtype=dt)

                for k, t in enumerate(dt):
                    self.graph.network[t[0]] = network[:, k].astype(t[1])
                del network

                self.graph.type_loaded = 'NETWORK'
                self.graph.status = 'OK'
                self.graph.network_ok = True
                try:
                    self.graph.prepare_graph(self.matrix.index.astype(np.int64))
                    self.graph.set_graph(cost_field='distance', skim_fields=False, block_centroid_flows=False)

                    self.results = AssignmentResults()
                    self.results.prepare(self.graph, self.matrix)
                    self.emit(SIGNAL("desire_lines"), ('text_dl', "Assigning demand"))
                    self.emit(SIGNAL("desire_lines"), ('job_size_dl', self.matrix.index.shape[0]))

                    assigner = allOrNothing(self.matrix, self.graph, self.results)
                    assigner.execute()
                    self.report = assigner.report
                    self.emit(SIGNAL("desire_lines"), ('text_dl', "Collecting results"))
                    link_loads = self.results.save_to_disk()
                    self.emit(SIGNAL("desire_lines"), ('text_dl', "Building resulting layer"))
                    features = []
                    max_edges = len(edges)
                    self.emit(SIGNAL("desire_lines"), ('job_size_dl', max_edges))

                    for i, link_id in enumerate(link_loads.index):
                        self.emit(SIGNAL("desire_lines"), ('jobs_done_dl', i))
                        a_node, b_node, direct, dist = dl_ids_on_links[link_id]

                        attr = [int(link_id), a_node, b_node, direct, dist]

                        a_point = all_centroids[a_node]
                        a_point = QgsPoint(a_point[0], a_point[1])
                        b_point = all_centroids[b_node]
                        b_point = QgsPoint(b_point[0], b_point[1])

                        feature = QgsFeature()
                        feature.setGeometry(QgsGeometry.fromPolyline([a_point, b_point]))

                        for c in self.matrix.view_names:
                            attr.extend([float(link_loads.data[c + '_ab'][i]),
                                         float(link_loads.data[c + '_ba'][i]),
                                         float(link_loads.data[c + '_tot'][i])])
                        feature.setAttributes(attr)
                        features.append(feature)
                    a = dlpr.addFeatures(features)
                    self.result_layer = desireline_layer
                except ValueError as error:
                    self.report = [error.message]

        self.emit(SIGNAL("desire_lines"), ('finished_desire_lines_procedure', 0))
    def doWork(self):
        if self.error is None:
            layer = get_vector_layer_by_name(self.layer)
            idx = layer.fieldNameIndex(self.id_field)
            matrix = self.matrix

            matrix_nodes = max(self.matrix_hash.values()) + 1
            featcount = layer.featureCount()
            self.emit(SIGNAL("ProgressMaxValue(PyQt_PyObject)"),
                      (0, featcount))

            all_centroids = {}
            P = 0
            for feat in layer.getFeatures():
                P += 1
                self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"), (0, int(P)))
                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Loading Layer Features: " + str(P) + "/" +
                           str(featcount)))

                geom = feat.geometry()
                if geom is not None:
                    point = list(geom.centroid().asPoint())
                    centroid_id = feat.attributes()[idx]
                    all_centroids[centroid_id] = point

                    if centroid_id not in self.matrix_hash.keys():
                        self.matrix_hash[centroid_id] = matrix_nodes
                        matrix_nodes += 1
            reverse_hash = {v: k for k, v in self.matrix_hash.iteritems()}

            #Creating resulting layer
            EPSG_code = int(layer.crs().authid().split(":")[1])

            desireline_layer = QgsVectorLayer(
                "LineString?crs=epsg:" + str(EPSG_code), self.dl_type,
                "memory")
            dlpr = desireline_layer.dataProvider()
            dlpr.addAttributes([
                QgsField("link_id", QVariant.Int),
                QgsField("A_Node", QVariant.Int),
                QgsField("B_Node", QVariant.Int),
                QgsField("direct", QVariant.Int),
                QgsField("length", QVariant.Double),
                QgsField("ab_flow", QVariant.Double),
                QgsField("ba_flow", QVariant.Double),
                QgsField("tot_flow", QVariant.Double)
            ])
            desireline_layer.updateFields()

            if self.dl_type == "DesireLines":
                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Creating Desire Lines"))
                self.emit(SIGNAL("ProgressMaxValue(PyQt_PyObject)"),
                          (0, self.matrix.shape[0] * self.matrix.shape[1] / 2))

                desireline_link_id = 1
                q = 0
                all_features = []
                for i in range(self.matrix.shape[0]):
                    if np.sum(self.matrix[i, :]) > 0:
                        a_node = reverse_hash[i]
                        for j in xrange(i + 1, self.matrix.shape[1]):
                            q += 1
                            b_node = reverse_hash[j]
                            self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"),
                                      (0, q))
                            if self.matrix[i, j] + self.matrix[j, i] > 0:
                                if a_node in all_centroids.keys(
                                ) and b_node in all_centroids.keys():
                                    a_point = all_centroids[a_node]
                                    a_point = QgsPoint(a_point[0], a_point[1])
                                    b_point = all_centroids[b_node]
                                    b_point = QgsPoint(b_point[0], b_point[1])
                                    dist = QgsGeometry().fromPoint(
                                        a_point).distance(
                                            QgsGeometry().fromPoint(b_point))
                                    feature = QgsFeature()
                                    feature.setGeometry(
                                        QgsGeometry.fromPolyline(
                                            [a_point, b_point]))
                                    feature.setAttributes([
                                        desireline_link_id,
                                        int(a_node),
                                        int(b_node), 0, dist,
                                        float(self.matrix[i, j]),
                                        float(self.matrix[j, i]),
                                        float(self.matrix[i, j] +
                                              self.matrix[j, i])
                                    ])
                                    all_features.append(feature)
                                    desireline_link_id += 1
                                else:
                                    tu = (a_node, b_node, self.matrix[i, j],
                                          self.matrix[j, i])
                                    self.report.append(
                                        'No centroids available to depict flow between node {0} and node {1}. AB flow was equal to {2} and BA flow was equal to {3}'
                                        .format(*tu))
                    else:
                        q += self.matrix.shape[1]
                        self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"),
                                  (0, q))

                if desireline_link_id > 1:
                    a = dlpr.addFeatures(all_features)
                    self.result_layer = desireline_layer
                else:
                    self.error = 'Nothing to show'

            elif self.dl_type == "DelaunayLines":

                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Computing Delaunay Triangles"))
                points = []
                seccond_relation = {}
                i = 0
                for k, v in all_centroids.iteritems():
                    points.append(v)
                    seccond_relation[i] = k
                    i += 1

                tri = Delaunay(np.array(points))

                #We process all the triangles to only get each edge once
                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Building Delaunay Network: Collecting Edges"))
                edges = []
                if self.python_version == 32:
                    all_edges = tri.vertices
                else:
                    all_edges = tri.simplices

                for triangle in all_edges:
                    links = list(itertools.combinations(triangle, 2))
                    for i in links:
                        l = [min(i[0], i[1]), max(i[0], i[1])]
                        if l not in edges:
                            edges.append(l)

                #Writing Delaunay layer
                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Building Delaunay Network: Assembling Layer"))

                desireline_link_id = 1
                data = []
                dl_link_ids = {}
                for edge in edges:
                    a_node = seccond_relation[edge[0]]
                    a_point = all_centroids[a_node]
                    a_point = QgsPoint(a_point[0], a_point[1])
                    b_node = seccond_relation[edge[1]]
                    b_point = all_centroids[b_node]
                    b_point = QgsPoint(b_point[0], b_point[1])
                    dist = QgsGeometry().fromPoint(a_point).distance(
                        QgsGeometry().fromPoint(b_point))
                    line = []
                    line.append(desireline_link_id)
                    line.append(self.matrix_hash[a_node])
                    line.append(self.matrix_hash[b_node])
                    line.append(dist)
                    line.append(dist)
                    line.append(0)
                    data.append(line)
                    if a_node not in dl_link_ids.keys():
                        dl_link_ids[a_node] = {}
                    dl_link_ids[a_node][b_node] = desireline_link_id
                    desireline_link_id += 1

                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Building graph"))
                network = np.asarray(data)
                del data

                #types for the network
                all_types = [
                    np.int64, np.int64, np.int64, np.float64, np.float64,
                    np.int64
                ]
                all_titles = [
                    'link_id', 'a_node', 'b_node', 'length_ab', 'length_ba',
                    'direction'
                ]
                dt = [(t, d) for t, d in zip(all_titles, all_types)]

                self.graph = Graph()
                self.graph.network = np.zeros(network.shape[0], dtype=dt)

                for k, t in enumerate(dt):
                    self.graph.network[t[0]] = network[:, k].astype(t[1])
                del network

                self.graph.type_loaded = 'NETWORK'
                self.graph.status = 'OK'
                self.graph.network_ok = True
                self.graph.prepare_graph()

                self.graph.set_graph(matrix_nodes,
                                     cost_field='length',
                                     block_centroid_flows=False)
                self.results = AssignmentResults()
                self.results.prepare(self.graph)
                # self.results.set_cores(1)

                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Assigning demand"))
                # Do the assignment
                #self.all_or_nothing(self.matrix, self.graph, self.results)
                self.report = all_or_nothing(self.matrix, self.graph,
                                             self.results)

                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Collecting results"))
                f = self.results.link_loads

                link_loads = np.zeros((f.shape[0] + 1, 2))
                self.emit(SIGNAL("ProgressMaxValue(PyQt_PyObject)"),
                          (0, f.shape[0] - 1))
                for i in range(f.shape[0] - 1):
                    self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"), (0, i))
                    direction = self.graph.graph['direction'][i]
                    link_id = self.graph.graph['link_id'][i]
                    flow = f[i]
                    if direction == 1:
                        link_loads[link_id, 0] = flow
                    else:
                        link_loads[link_id, 1] = flow

                self.emit(SIGNAL("ProgressText (PyQt_PyObject)"),
                          (0, "Building resulting layer"))
                features = []
                max_edges = len(edges)
                self.emit(SIGNAL("ProgressMaxValue(PyQt_PyObject)"),
                          (0, max_edges))

                for i, edge in enumerate(edges):
                    self.emit(SIGNAL("ProgressValue(PyQt_PyObject)"), (0, i))
                    a_node = seccond_relation[edge[0]]
                    a_point = all_centroids[a_node]
                    a_point = QgsPoint(a_point[0], a_point[1])
                    b_node = seccond_relation[edge[1]]
                    b_point = all_centroids[b_node]
                    b_point = QgsPoint(b_point[0], b_point[1])
                    dist = QgsGeometry().fromPoint(a_point).distance(
                        QgsGeometry().fromPoint(b_point))

                    feature = QgsFeature()
                    feature.setGeometry(
                        QgsGeometry.fromPolyline([a_point, b_point]))
                    desireline_link_id = dl_link_ids[a_node][b_node]
                    feature.setAttributes([
                        desireline_link_id, a_node, b_node, 0, dist,
                        float(link_loads[desireline_link_id, 0]),
                        float(link_loads[desireline_link_id, 1]),
                        float(link_loads[desireline_link_id, 0] +
                              link_loads[desireline_link_id, 1])
                    ])
                    features.append(feature)
                a = dlpr.addFeatures(features)
                self.result_layer = desireline_layer

        self.emit(SIGNAL("finished_threaded_procedure( PyQt_PyObject )"), True)
Exemple #16
0
    def test_set_save_path_file(self):
        a = AssignmentResults()

        # Never save by default
        self.assertEqual(a.save_path_file, False)