public void save() {
		int transactionID = programUserData.startTransaction();
		try {

			if (!colorUpdateMap.isEmpty()) {
				ObjectPropertyMap<SaveableColor> propertyMap =
					programUserData.getObjectProperty(FunctionGraphPlugin.class.getSimpleName(),
						COLOR_PROPERTY_NAME, SaveableColor.class, true);
				saveMap(colorUpdateMap, propertyMap);
			}

			if (!locationUpdateMap.isEmpty()) {
				ObjectPropertyMap<SaveablePoint> propertyMap =
					programUserData.getObjectProperty(FunctionGraphPlugin.class.getSimpleName(),
						LOCATION_PROPERTY_NAME, SaveablePoint.class, true);
				saveMap(locationUpdateMap, propertyMap);
			}

			if (!groupLocationUpdateMap.isEmpty()) {
				ObjectPropertyMap<SaveablePoint> propertyMap =
					programUserData.getObjectProperty(FunctionGraphPlugin.class.getSimpleName(),
						GROUP_LOCATION_PROPERTY_NAME, SaveablePoint.class, true);
				saveMap(groupLocationUpdateMap, propertyMap);
			}

			if (!groupedSettingsUpdateMap.isEmpty()) {
				ObjectPropertyMap<SaveableXML> propertyMap =
					programUserData.getObjectProperty(FunctionGraphPlugin.class.getSimpleName(),
						GROUP_SETTINGS_PROPERTY_NAME, SaveableXML.class, true);
				saveMap(groupedSettingsUpdateMap, propertyMap);
			}

			if (!regroupSettingsUpdateMap.isEmpty()) {
				ObjectPropertyMap<SaveableXML> propertyMap =
					programUserData.getObjectProperty(FunctionGraphPlugin.class.getSimpleName(),
						REGROUP_SETTINGS_PROPERTY_NAME, SaveableXML.class, true);
				saveMap(regroupSettingsUpdateMap, propertyMap);
			}
		}
		finally {
			programUserData.endTransaction(transactionID);
		}
	}
Note: this method does not clear group vertex locations.
@param functionGraph function graph
Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphVertexAttributes.java