<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def alter_edge(self, from_index, to_index, to_jimage=None, new_weight=None, new_edge_properties=None):
 """ Alters either the weight or the edge_properties of an edge in the StructureGraph. :param from_index: int :param to_index: int :param to_jimage: tuple :param new_weight: alter_edge does not require that weight be altered. As such, by default, this is None. If weight is to be changed, it should be a float. :param new_edge_properties: alter_edge does not require that edge_properties be altered. As such, by default, this is None. If any edge properties are to be changed, it should be a dictionary of edge properties to be changed. :return: """


        existing_edges = self.graph.get_edge_data(from_index, to_index)

        # ensure that edge exists before attempting to change it
        if not existing_edges:
            raise ValueError("Edge between {} and {} cannot be altered;\
                                no edge exists between those sites.".format(
                                from_index, to_index
                                ))

        if to_jimage is None:
            edge_index = 0
        else:
            for i, properties in existing_edges.items():
                if properties["to_jimage"] == to_jimage:
                    edge_index = i

        if new_weight is not None:
            self.graph[from_index][to_index][edge_index]['weight'] = new_weight

        if new_edge_properties is not None:
            for prop in list(new_edge_properties.keys()):
                self.graph[from_index][to_index][edge_index][prop] = new_edge_properties[prop]