diff --git a/python_map_scripts/forwarn3_products_1yr.map b/python_map_scripts/forwarn3_products_1yr.map
new file mode 100644
index 00000000..3634912d
--- /dev/null
+++ b/python_map_scripts/forwarn3_products_1yr.map
@@ -0,0 +1,128 @@
+MAP
+ # background color of image if transparency
+ # is not requested
+ IMAGECOLOR 255 255 255
+
+ # default output image dimensions
+ SIZE 600 400
+ MAXSIZE 4000
+ # always returns a map
+ STATUS ON
+
+ # set top level projection
+ PROJECTION
+ "init=epsg:3857"
+ END
+
+ # image format options
+ OUTPUTFORMAT
+ NAME png
+ DRIVER "GD/PNG"
+ MIMETYPE "image/png"
+ IMAGEMODE RGB
+ EXTENSION "png"
+ END
+
+ OUTPUTFORMAT
+ NAME "GEOTIFF"
+ DRIVER "GDAL/GTiff"
+ MIMETYPE "image/tiff"
+ IMAGEMODE "BYTE"
+ EXTENSION "tif"
+ END
+
+ # minx miny maxx maxy
+ # sets:
+ # /WMT_MS_Capabilities/Capability/Layer/LatLonBoundingBox(@minx @miny @maxx @maxx)
+ EXTENT -180 -90 180 90 # World
+
+ # add def pointers for symbols
+ SYMBOLSET "./symbols/symbols35.sym"
+ FONTSET "./fonts/fonts.list"
+
+ # Start of web interface definition
+ WEB
+ # this is the real filepath to the temp dir for intermediate file creation
+ IMAGEPATH "./tmp"
+ # this is the web-accessible path to IMAGEPATH
+ IMAGEURL "/tmp/"
+ HEADER "./templates/query_header.html"
+ FOOTER "./templates/query_footer.html"
+ METADATA
+ "ows_enable_request" "*"
+ "wms_title" "NEMAC WMS"
+ "wms_abstract" "NEMAC WMS"
+ "wms_contactperson" "nemac@unca.edu"
+ "wms_rootlayer_name" "" # this sets queryable=0 for root layer
+ "wms_onlineresource" "https://mapserver.nemac.org/?map=/etc/mapserver/ecs_test_map_files/forwarn3_products_1yr.map"
+ "wms_keywordlist" "2024-05-09_2024-06-01.napolygon.1yrdeparture.LAEA.img,
+ 2024-05-17_2024-06-09.napolygon.1yrdeparture.LAEA.img,
+ 2024-05-25_2024-06-17.napolygon.1yrdeparture.LAEA.img,
+ 2024-06-02_2024-06-25.napolygon.1yrdeparture.LAEA.img,
+ 2024-06-10_2024-07-03.napolygon.1yrdeparture.LAEA.img,
+ 2024-06-18_2024-07-11.napolygon.1yrdeparture.LAEA.img,
+ 2024-06-26_2024-07-19.napolygon.1yrdeparture.LAEA.img,
+ 2024-07-04_2024-07-27.napolygon.1yrdeparture.LAEA.img"
+ "wms_srs" "EPSG:4326 EPSG:2163 EPSG:3857 EPSG:900913"
+ "wcs_label" "forwarn3_products_1yr.map"
+ "wcs_srs" "EPSG:2163"
+ "ows_contactorganization" "UNCA's NEMAC"
+ END # end METADATA
+ END # end WEB
+
+ QUERYMAP
+ STATUS OFF
+ END # end QUERYMAP
+
+ LEGEND
+ STATUS ON
+ LABEL
+ COLOR 0 0 0
+ FONT "vera_serif"
+ TYPE truetype
+ SIZE 9
+ POSITION cl
+ END # end LABEL
+ END # end LEGEND
+
+ LAYER
+ NAME "forwarn3_products_1yr"
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END # END PROJECTION
+ TYPE RASTER
+ STATUS OFF
+ VALIDATION
+ "mask" "^[a-zA-Z0-9_]+$"
+ "default_mask" "empty_mask"
+ END # END VALIDATION
+ DATA /etc/mapserver/forwarn3_products/1yr/%data%
+ TEMPLATE layer_query_body.html # THIS DOES NOT EXIST AT THE MOMENT BUT IT IS NEEDED TO HAVE queryable=1
+ #GROUP "forwarn3_products_1yr"
+ INCLUDE "new-forwarn2-standard-2.cmap"
+ METADATA
+ "wms_title" "forwarn3_products_1yr"
+ #"wms_group_title" "forwarn3_products_1yr"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "forwarn3_products_1yr"
+ "wcs_label" "forwarn3_products_1yr"
+ "wcs_rangeset_name" "forwarn3_products_1yr"
+ "wcs_rangeset_label" "forwarn3_products_1yr"
+ "wcs_bandcount" "1"
+ "wcs_formats" "GEOTIFF"
+ "wcs_nativeformat" "8-bit GeoTIF"
+ "gml_include_items" "value_0"
+ END # end METADATA
+ MASK '%mask%'
+ END # end LAYER
+
+ INCLUDE "masks.map"
+END
diff --git a/python_map_scripts/make_maps.py b/python_map_scripts/make_maps.py
new file mode 100644
index 00000000..ac37f185
--- /dev/null
+++ b/python_map_scripts/make_maps.py
@@ -0,0 +1,90 @@
+import os
+import glob
+import re
+
+DATA_DIR = "forwarn"
+EXCLUDE_DIRS = ["archive", "bill_c", "forwarn2_build_prod", "forwarn2_products",
+ "forwarn3_test", "graph_data", "jspruce", "masks", "precursors",
+ "rescaled_precursors", "scripts"]
+DATA_LOCATION_DIRECTORY = "/etc/mapserver" # where ECS container expects data to be
+
+def extract_date_range(filename):
+ # Use a regular expression to find the date range
+ match = re.search(r'(\d{4}-\d{2}-\d{2})_(\d{4}-\d{2}-\d{2})', filename)
+ if match:
+ return match.group(2)
+ return None
+
+def extract_subdirs(file_path, base_dir):
+ # Get the relative path
+ rel_path = os.path.relpath(file_path, base_dir)
+ # Split the path into parts
+ parts = rel_path.split(os.sep)
+ # Return all parts except the last one (filename)
+ return os.sep.join(parts[:-1])
+
+def create_layers_from_template(map_template_file, raster_template_file, data_dir):
+ with open(map_template_file, 'r', encoding='utf-8') as f:
+ map_template = f.read()
+
+ with open(raster_template_file, 'r', encoding='utf-8') as f:
+ raster_template = f.read()
+
+ # Get list of .img files
+ img_files = [
+ f for f in glob.glob(os.path.join(data_dir, '**/*.img'), recursive=True)
+ if not any(exclude_dir in f.split(os.sep) for exclude_dir in EXCLUDE_DIRS)
+ if "muted" not in os.path.basename(f).lower()
+ ]
+ # img_files = glob.glob(os.path.join(data_dir, '**/*.img'), recursive=True)
+ img_files.sort()
+
+ # Group files by subdirectory
+ subdirectory_files = {}
+ for absolute_path in img_files:
+ subdirs = extract_subdirs(absolute_path, data_dir)
+ if subdirs not in subdirectory_files:
+ subdirectory_files[subdirs] = []
+ subdirectory_files[subdirs].append(absolute_path)
+
+ # Process each subdirectory
+ for subdirs, files in subdirectory_files.items():
+ layers = []
+ layer_filenames = []
+ layer_content = raster_template.format(
+ layer_name = subdirs.replace(os.sep, '_'),
+ group_name = subdirs.replace(os.sep, '_'),
+ metadata_name = subdirs.replace(os.sep, '_'),
+ data_location = os.path.join(DATA_LOCATION_DIRECTORY, subdirs, "%data%")
+ )
+ layers.append(layer_content)
+ for absolute_path in files:
+ filename = os.path.basename(absolute_path)
+ layer_filenames.append(filename)
+ grouped = [layer_filenames[i:i+1] for i in range(0, len(layer_filenames), 1)]
+ final_string = ',\n '.join(','.join(group) for group in grouped)
+# date_range = extract_date_range(filename)
+# if date_range:
+# layer_content = raster_template.format(
+# layer_name = f"{subdirs.replace(os.sep, '_')}_{date_range.replace('-', '')}",
+# group_name = subdirs.replace(os.sep, '_'),
+# metadata_name = f"{subdirs.replace(os.sep, '_')}_{date_range}",
+# metadata_date = date_range.replace('-', ''),
+# data_location = os.path.join(DATA_LOCATION_DIRECTORY, absolute_path)
+# )
+# layers.append(layer_content)
+# layer_filenames.append(filename)
+# else:
+# print(f"Warning: Could not extract date range from {filename}")
+
+ layers_str = "\n".join(layers)
+ output_filename = f"{subdirs.replace(os.sep, '_')}.map"
+ map_content = map_template.format(layers=layers_str, layer_filenames=final_string, map_file_name=output_filename)
+ with open(output_filename, 'w', encoding='utf-8') as f:
+ f.write(map_content)
+
+ print(f"Created map file: {output_filename}")
+
+MAP_TEMPLATE = "map_template.map"
+RASTER_TEMPLATE = "raster_layers_template.map"
+create_layers_from_template(MAP_TEMPLATE, RASTER_TEMPLATE, DATA_DIR)
diff --git a/python_map_scripts/map_template.map b/python_map_scripts/map_template.map
new file mode 100644
index 00000000..133a84e1
--- /dev/null
+++ b/python_map_scripts/map_template.map
@@ -0,0 +1,83 @@
+MAP
+ # background color of image if transparency
+ # is not requested
+ IMAGECOLOR 255 255 255
+
+ # default output image dimensions
+ SIZE 600 400
+ MAXSIZE 4000
+ # always returns a map
+ STATUS ON
+
+ # set top level projection
+ PROJECTION
+ "init=epsg:3857"
+ END
+
+ # image format options
+ OUTPUTFORMAT
+ NAME png
+ DRIVER "GD/PNG"
+ MIMETYPE "image/png"
+ IMAGEMODE RGB
+ EXTENSION "png"
+ END
+
+ OUTPUTFORMAT
+ NAME "GEOTIFF"
+ DRIVER "GDAL/GTiff"
+ MIMETYPE "image/tiff"
+ IMAGEMODE "BYTE"
+ EXTENSION "tif"
+ END
+
+ # minx miny maxx maxy
+ # sets:
+ # /WMT_MS_Capabilities/Capability/Layer/LatLonBoundingBox(@minx @miny @maxx @maxx)
+ EXTENT -180 -90 180 90 # World
+
+ # add def pointers for symbols
+ SYMBOLSET "./symbols/symbols35.sym"
+ FONTSET "./fonts/fonts.list"
+
+ # Start of web interface definition
+ WEB
+ # this is the real filepath to the temp dir for intermediate file creation
+ IMAGEPATH "./tmp"
+ # this is the web-accessible path to IMAGEPATH
+ IMAGEURL "/tmp/"
+ HEADER "./templates/query_header.html"
+ FOOTER "./templates/query_footer.html"
+ METADATA
+ "ows_enable_request" "*"
+ "wms_title" "NEMAC WMS"
+ "wms_abstract" "NEMAC WMS"
+ "wms_contactperson" "nemac@unca.edu"
+ "wms_rootlayer_name" "" # this sets queryable=0 for root layer
+ "wms_onlineresource" "https://mapserver.nemac.org/?map=/etc/mapserver/ecs_test_map_files/{map_file_name}"
+ "wms_keywordlist" "{layer_filenames}"
+ "wms_srs" "EPSG:4326 EPSG:2163 EPSG:3857 EPSG:900913"
+ "wcs_label" "{map_file_name}"
+ "wcs_srs" "EPSG:2163"
+ "ows_contactorganization" "UNCA's NEMAC"
+ END # end METADATA
+ END # end WEB
+
+ QUERYMAP
+ STATUS OFF
+ END # end QUERYMAP
+
+ LEGEND
+ STATUS ON
+ LABEL
+ COLOR 0 0 0
+ FONT "vera_serif"
+ TYPE truetype
+ SIZE 9
+ POSITION cl
+ END # end LABEL
+ END # end LEGEND
+
+ {layers}
+ INCLUDE "masks.map"
+END
diff --git a/python_map_scripts/masks.map b/python_map_scripts/masks.map
new file mode 100644
index 00000000..47e56cbd
--- /dev/null
+++ b/python_map_scripts/masks.map
@@ -0,0 +1,355 @@
+LAYER
+ NAME empty_mask
+ STATUS OFF
+ TYPE POLYGON
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ FEATURE
+ POINTS
+ -2401951.937575 -2238222.70389
+ 2345858.525679 -2238222.70389
+ 2345858.525679 967021.455769
+ -2401951.937575 967021.455769
+ -2401951.937575 -2238222.70389
+ END
+ END
+ CLASS
+ STYLE
+ OPACITY 100
+ COLOR 255 255 255
+ END
+ END
+ METADATA
+ "is_empty_mask" "true"
+ END
+END
+
+LAYER
+ NAME MaskForForest
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_all_forests_mask.img
+ CLASS
+ EXPRESSION ([pixel] > 0)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForForest_Mask_file"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForForest"
+ "wcs_label" "MaskForForest"
+ "wcs_rangeset_name" "MaskForForest"
+ "wcs_rangeset_label" "MaskForForest"
+ END # end METADATA
+END # end LAYER
+
+LAYER
+ NAME MaskForAgriculture
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ GROUP Masks
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_crops_mask.img
+ CLASS
+ EXPRESSION ([pixel] = 1)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForAgriculture_Mask_File"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForAgriculture"
+ "wcs_label" "MaskForAgriculture"
+ "wcs_rangeset_name" "MaskForAgriculture"
+ "wcs_rangeset_label" "MaskForAgriculture"
+ END # end METADATA
+END # end LAYER
+
+LAYER
+ NAME MaskForConiferForest
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_evergreen_forest_mask.img
+ CLASS
+ EXPRESSION ([pixel] > 0)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForConiferForest"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForConiferForest"
+ "wcs_label" "MaskForConiferForest"
+ "wcs_rangeset_name" "MaskForConiferForest"
+ "wcs_rangeset_label" "MaskForConiferForest"
+ END # end METADATA
+END # end LAYER
+
+LAYER
+ NAME MaskForDeciduousForest
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_deciduous_forest_mask.img
+ CLASS
+ EXPRESSION ([pixel] > 0)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForDeciduousForest"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForDeciduousForest"
+ "wcs_label" "MaskForDeciduousForest"
+ "wcs_rangeset_name" "MaskForDeciduousForest"
+ "wcs_rangeset_label" "MaskForDeciduousForest"
+ END # end METADATA
+END # end LAYER
+
+LAYER
+ NAME MaskForGrass
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_grass_mask.img
+ CLASS
+ EXPRESSION ([pixel] > 0)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForGrass"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForGrass"
+ "wcs_label" "MaskForGrass"
+ "wcs_rangeset_name" "MaskForGrass"
+ "wcs_rangeset_label" "MaskForGrass"
+ END # end METADATA
+END # end LAYER
+
+LAYER
+ NAME MaskForMixedForest
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_mixed_forest_mask.img
+ CLASS
+ EXPRESSION ([pixel] > 0)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForMixedForest"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForMixedForest"
+ "wcs_label" "MaskForMixedForest"
+ "wcs_rangeset_name" "MaskForMixedForest"
+ "wcs_rangeset_label" "MaskForMixedForest"
+ END # end METADATA
+END # end LAYER
+
+LAYER
+ NAME MaskForNonVegetated
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_non_vegetated_mask.img
+ CLASS
+ EXPRESSION ([pixel] > 0)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForNonVegetated"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForNonVegetated"
+ "wcs_label" "MaskForNonVegetated"
+ "wcs_rangeset_name" "MaskForNonVegetated"
+ "wcs_rangeset_label" "MaskForNonVegetated"
+ END # end METADATA
+END # end LAYER
+
+LAYER
+ NAME MaskForShrubland
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_shrubland_mask.img
+ CLASS
+ EXPRESSION ([pixel] > 0)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForShrubland"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForShrubland"
+ "wcs_label" "MaskForShrubland"
+ "wcs_rangeset_name" "MaskForShrubland"
+ "wcs_rangeset_label" "MaskForShrubland"
+ END # end METADATA
+END # end LAYER
+
+LAYER
+ NAME MaskForUrban
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_urban_mask.img
+ CLASS
+ EXPRESSION ([pixel] > 0)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForUrban"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForUrban"
+ "wcs_label" "MaskForUrban"
+ "wcs_rangeset_name" "MaskForUrban"
+ "wcs_rangeset_label" "MaskForUrban"
+ END # end METADATA
+END # end LAYER
+
+LAYER
+ NAME MaskForWetland
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END
+ TYPE RASTER
+ STATUS OFF
+ DATA ../fsdata1/fsdata-internal/efetac_nasa/Mask/updated_masks_2020_2021/fw3_non_woody_wetland_mask.img
+ CLASS
+ EXPRESSION ([pixel] > 0)
+ STYLE
+ COLOR 0 0 0
+ END
+ END
+ METADATA
+ "wms_title" "MaskForWetland"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "MaskForWetland"
+ "wcs_label" "MaskForWetland"
+ "wcs_rangeset_name" "MaskForWetland"
+ "wcs_rangeset_label" "MaskForWetland"
+ END # end METADATA
+END # end LAYER
\ No newline at end of file
diff --git a/python_map_scripts/net_ecological_impact_dev_products_3yr_dev.map b/python_map_scripts/net_ecological_impact_dev_products_3yr_dev.map
new file mode 100644
index 00000000..08ec3d4a
--- /dev/null
+++ b/python_map_scripts/net_ecological_impact_dev_products_3yr_dev.map
@@ -0,0 +1,123 @@
+MAP
+ # background color of image if transparency
+ # is not requested
+ IMAGECOLOR 255 255 255
+
+ # default output image dimensions
+ SIZE 600 400
+ MAXSIZE 4000
+ # always returns a map
+ STATUS ON
+
+ # set top level projection
+ PROJECTION
+ "init=epsg:3857"
+ END
+
+ # image format options
+ OUTPUTFORMAT
+ NAME png
+ DRIVER "GD/PNG"
+ MIMETYPE "image/png"
+ IMAGEMODE RGB
+ EXTENSION "png"
+ END
+
+ OUTPUTFORMAT
+ NAME "GEOTIFF"
+ DRIVER "GDAL/GTiff"
+ MIMETYPE "image/tiff"
+ IMAGEMODE "BYTE"
+ EXTENSION "tif"
+ END
+
+ # minx miny maxx maxy
+ # sets:
+ # /WMT_MS_Capabilities/Capability/Layer/LatLonBoundingBox(@minx @miny @maxx @maxx)
+ EXTENT -180 -90 180 90 # World
+
+ # add def pointers for symbols
+ SYMBOLSET "./symbols/symbols35.sym"
+ FONTSET "./fonts/fonts.list"
+
+ # Start of web interface definition
+ WEB
+ # this is the real filepath to the temp dir for intermediate file creation
+ IMAGEPATH "./tmp"
+ # this is the web-accessible path to IMAGEPATH
+ IMAGEURL "/tmp/"
+ HEADER "./templates/query_header.html"
+ FOOTER "./templates/query_footer.html"
+ METADATA
+ "ows_enable_request" "*"
+ "wms_title" "NEMAC WMS"
+ "wms_abstract" "NEMAC WMS"
+ "wms_contactperson" "nemac@unca.edu"
+ "wms_rootlayer_name" "" # this sets queryable=0 for root layer
+ "wms_onlineresource" "https://mapserver.nemac.org/?map=/etc/mapserver/ecs_test_map_files/net_ecological_impact_dev_products_3yr_dev.map"
+ "wms_keywordlist" "2023-11-25_2023-12-02.napolygon.auc3yrdeparture.pct.LAEA.datumfix.img,
+ 2023-12-03_2023-12-10.napolygon.auc3yrdeparture.pct.LAEA.datumfix.img,
+ 2023-12-11_2023-12-18.napolygon.auc3yrdeparture.pct.LAEA.datumfix.img"
+ "wms_srs" "EPSG:4326 EPSG:2163 EPSG:3857 EPSG:900913"
+ "wcs_label" "net_ecological_impact_dev_products_3yr_dev.map"
+ "wcs_srs" "EPSG:2163"
+ "ows_contactorganization" "UNCA's NEMAC"
+ END # end METADATA
+ END # end WEB
+
+ QUERYMAP
+ STATUS OFF
+ END # end QUERYMAP
+
+ LEGEND
+ STATUS ON
+ LABEL
+ COLOR 0 0 0
+ FONT "vera_serif"
+ TYPE truetype
+ SIZE 9
+ POSITION cl
+ END # end LABEL
+ END # end LEGEND
+
+ LAYER
+ NAME "net_ecological_impact_dev_products_3yr_dev"
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END # END PROJECTION
+ TYPE RASTER
+ STATUS OFF
+ VALIDATION
+ "mask" "^[a-zA-Z0-9_]+$"
+ "default_mask" "empty_mask"
+ END # END VALIDATION
+ DATA /etc/mapserver/net_ecological_impact_dev_products/3yr_dev/%data%
+ TEMPLATE layer_query_body.html # THIS DOES NOT EXIST AT THE MOMENT BUT IT IS NEEDED TO HAVE queryable=1
+ #GROUP "net_ecological_impact_dev_products_3yr_dev"
+ INCLUDE "new-forwarn2-standard-2.cmap"
+ METADATA
+ "wms_title" "net_ecological_impact_dev_products_3yr_dev"
+ #"wms_group_title" "net_ecological_impact_dev_products_3yr_dev"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "net_ecological_impact_dev_products_3yr_dev"
+ "wcs_label" "net_ecological_impact_dev_products_3yr_dev"
+ "wcs_rangeset_name" "net_ecological_impact_dev_products_3yr_dev"
+ "wcs_rangeset_label" "net_ecological_impact_dev_products_3yr_dev"
+ "wcs_bandcount" "1"
+ "wcs_formats" "GEOTIFF"
+ "wcs_nativeformat" "8-bit GeoTIF"
+ "gml_include_items" "value_0"
+ END # end METADATA
+ MASK '%mask%'
+ END # end LAYER
+
+ INCLUDE "masks.map"
+END
diff --git a/python_map_scripts/net_ecological_impact_dev_products_4yr_dev.map b/python_map_scripts/net_ecological_impact_dev_products_4yr_dev.map
new file mode 100644
index 00000000..4090a758
--- /dev/null
+++ b/python_map_scripts/net_ecological_impact_dev_products_4yr_dev.map
@@ -0,0 +1,123 @@
+MAP
+ # background color of image if transparency
+ # is not requested
+ IMAGECOLOR 255 255 255
+
+ # default output image dimensions
+ SIZE 600 400
+ MAXSIZE 4000
+ # always returns a map
+ STATUS ON
+
+ # set top level projection
+ PROJECTION
+ "init=epsg:3857"
+ END
+
+ # image format options
+ OUTPUTFORMAT
+ NAME png
+ DRIVER "GD/PNG"
+ MIMETYPE "image/png"
+ IMAGEMODE RGB
+ EXTENSION "png"
+ END
+
+ OUTPUTFORMAT
+ NAME "GEOTIFF"
+ DRIVER "GDAL/GTiff"
+ MIMETYPE "image/tiff"
+ IMAGEMODE "BYTE"
+ EXTENSION "tif"
+ END
+
+ # minx miny maxx maxy
+ # sets:
+ # /WMT_MS_Capabilities/Capability/Layer/LatLonBoundingBox(@minx @miny @maxx @maxx)
+ EXTENT -180 -90 180 90 # World
+
+ # add def pointers for symbols
+ SYMBOLSET "./symbols/symbols35.sym"
+ FONTSET "./fonts/fonts.list"
+
+ # Start of web interface definition
+ WEB
+ # this is the real filepath to the temp dir for intermediate file creation
+ IMAGEPATH "./tmp"
+ # this is the web-accessible path to IMAGEPATH
+ IMAGEURL "/tmp/"
+ HEADER "./templates/query_header.html"
+ FOOTER "./templates/query_footer.html"
+ METADATA
+ "ows_enable_request" "*"
+ "wms_title" "NEMAC WMS"
+ "wms_abstract" "NEMAC WMS"
+ "wms_contactperson" "nemac@unca.edu"
+ "wms_rootlayer_name" "" # this sets queryable=0 for root layer
+ "wms_onlineresource" "https://mapserver.nemac.org/?map=/etc/mapserver/ecs_test_map_files/net_ecological_impact_dev_products_4yr_dev.map"
+ "wms_keywordlist" "2023-11-25_2023-12-02.napolygon.auc4yrdeparture.pct.LAEA.datumfix.img,
+ 2023-12-03_2023-12-10.napolygon.auc4yrdeparture.pct.LAEA.datumfix.img,
+ 2023-12-11_2023-12-18.napolygon.auc4yrdeparture.pct.LAEA.datumfix.img"
+ "wms_srs" "EPSG:4326 EPSG:2163 EPSG:3857 EPSG:900913"
+ "wcs_label" "net_ecological_impact_dev_products_4yr_dev.map"
+ "wcs_srs" "EPSG:2163"
+ "ows_contactorganization" "UNCA's NEMAC"
+ END # end METADATA
+ END # end WEB
+
+ QUERYMAP
+ STATUS OFF
+ END # end QUERYMAP
+
+ LEGEND
+ STATUS ON
+ LABEL
+ COLOR 0 0 0
+ FONT "vera_serif"
+ TYPE truetype
+ SIZE 9
+ POSITION cl
+ END # end LABEL
+ END # end LEGEND
+
+ LAYER
+ NAME "net_ecological_impact_dev_products_4yr_dev"
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END # END PROJECTION
+ TYPE RASTER
+ STATUS OFF
+ VALIDATION
+ "mask" "^[a-zA-Z0-9_]+$"
+ "default_mask" "empty_mask"
+ END # END VALIDATION
+ DATA /etc/mapserver/net_ecological_impact_dev_products/4yr_dev/%data%
+ TEMPLATE layer_query_body.html # THIS DOES NOT EXIST AT THE MOMENT BUT IT IS NEEDED TO HAVE queryable=1
+ #GROUP "net_ecological_impact_dev_products_4yr_dev"
+ INCLUDE "new-forwarn2-standard-2.cmap"
+ METADATA
+ "wms_title" "net_ecological_impact_dev_products_4yr_dev"
+ #"wms_group_title" "net_ecological_impact_dev_products_4yr_dev"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "net_ecological_impact_dev_products_4yr_dev"
+ "wcs_label" "net_ecological_impact_dev_products_4yr_dev"
+ "wcs_rangeset_name" "net_ecological_impact_dev_products_4yr_dev"
+ "wcs_rangeset_label" "net_ecological_impact_dev_products_4yr_dev"
+ "wcs_bandcount" "1"
+ "wcs_formats" "GEOTIFF"
+ "wcs_nativeformat" "8-bit GeoTIF"
+ "gml_include_items" "value_0"
+ END # end METADATA
+ MASK '%mask%'
+ END # end LAYER
+
+ INCLUDE "masks.map"
+END
diff --git a/python_map_scripts/net_ecological_impact_dev_products_5yr_dev.map b/python_map_scripts/net_ecological_impact_dev_products_5yr_dev.map
new file mode 100644
index 00000000..3387f877
--- /dev/null
+++ b/python_map_scripts/net_ecological_impact_dev_products_5yr_dev.map
@@ -0,0 +1,123 @@
+MAP
+ # background color of image if transparency
+ # is not requested
+ IMAGECOLOR 255 255 255
+
+ # default output image dimensions
+ SIZE 600 400
+ MAXSIZE 4000
+ # always returns a map
+ STATUS ON
+
+ # set top level projection
+ PROJECTION
+ "init=epsg:3857"
+ END
+
+ # image format options
+ OUTPUTFORMAT
+ NAME png
+ DRIVER "GD/PNG"
+ MIMETYPE "image/png"
+ IMAGEMODE RGB
+ EXTENSION "png"
+ END
+
+ OUTPUTFORMAT
+ NAME "GEOTIFF"
+ DRIVER "GDAL/GTiff"
+ MIMETYPE "image/tiff"
+ IMAGEMODE "BYTE"
+ EXTENSION "tif"
+ END
+
+ # minx miny maxx maxy
+ # sets:
+ # /WMT_MS_Capabilities/Capability/Layer/LatLonBoundingBox(@minx @miny @maxx @maxx)
+ EXTENT -180 -90 180 90 # World
+
+ # add def pointers for symbols
+ SYMBOLSET "./symbols/symbols35.sym"
+ FONTSET "./fonts/fonts.list"
+
+ # Start of web interface definition
+ WEB
+ # this is the real filepath to the temp dir for intermediate file creation
+ IMAGEPATH "./tmp"
+ # this is the web-accessible path to IMAGEPATH
+ IMAGEURL "/tmp/"
+ HEADER "./templates/query_header.html"
+ FOOTER "./templates/query_footer.html"
+ METADATA
+ "ows_enable_request" "*"
+ "wms_title" "NEMAC WMS"
+ "wms_abstract" "NEMAC WMS"
+ "wms_contactperson" "nemac@unca.edu"
+ "wms_rootlayer_name" "" # this sets queryable=0 for root layer
+ "wms_onlineresource" "https://mapserver.nemac.org/?map=/etc/mapserver/ecs_test_map_files/net_ecological_impact_dev_products_5yr_dev.map"
+ "wms_keywordlist" "2023-11-25_2023-12-02.napolygon.auc5yrdeparture.pct.LAEA.datumfix.img,
+ 2023-12-03_2023-12-10.napolygon.auc5yrdeparture.pct.LAEA.datumfix.img,
+ 2023-12-11_2023-12-18.napolygon.auc5yrdeparture.pct.LAEA.datumfix.img"
+ "wms_srs" "EPSG:4326 EPSG:2163 EPSG:3857 EPSG:900913"
+ "wcs_label" "net_ecological_impact_dev_products_5yr_dev.map"
+ "wcs_srs" "EPSG:2163"
+ "ows_contactorganization" "UNCA's NEMAC"
+ END # end METADATA
+ END # end WEB
+
+ QUERYMAP
+ STATUS OFF
+ END # end QUERYMAP
+
+ LEGEND
+ STATUS ON
+ LABEL
+ COLOR 0 0 0
+ FONT "vera_serif"
+ TYPE truetype
+ SIZE 9
+ POSITION cl
+ END # end LABEL
+ END # end LEGEND
+
+ LAYER
+ NAME "net_ecological_impact_dev_products_5yr_dev"
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END # END PROJECTION
+ TYPE RASTER
+ STATUS OFF
+ VALIDATION
+ "mask" "^[a-zA-Z0-9_]+$"
+ "default_mask" "empty_mask"
+ END # END VALIDATION
+ DATA /etc/mapserver/net_ecological_impact_dev_products/5yr_dev/%data%
+ TEMPLATE layer_query_body.html # THIS DOES NOT EXIST AT THE MOMENT BUT IT IS NEEDED TO HAVE queryable=1
+ #GROUP "net_ecological_impact_dev_products_5yr_dev"
+ INCLUDE "new-forwarn2-standard-2.cmap"
+ METADATA
+ "wms_title" "net_ecological_impact_dev_products_5yr_dev"
+ #"wms_group_title" "net_ecological_impact_dev_products_5yr_dev"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "net_ecological_impact_dev_products_5yr_dev"
+ "wcs_label" "net_ecological_impact_dev_products_5yr_dev"
+ "wcs_rangeset_name" "net_ecological_impact_dev_products_5yr_dev"
+ "wcs_rangeset_label" "net_ecological_impact_dev_products_5yr_dev"
+ "wcs_bandcount" "1"
+ "wcs_formats" "GEOTIFF"
+ "wcs_nativeformat" "8-bit GeoTIF"
+ "gml_include_items" "value_0"
+ END # end METADATA
+ MASK '%mask%'
+ END # end LAYER
+
+ INCLUDE "masks.map"
+END
diff --git a/python_map_scripts/raster_layers_template.map b/python_map_scripts/raster_layers_template.map
new file mode 100644
index 00000000..33b02d8a
--- /dev/null
+++ b/python_map_scripts/raster_layers_template.map
@@ -0,0 +1,38 @@
+ LAYER
+ NAME "{layer_name}"
+ PROJECTION
+ "+proj=laea"
+ "+lat_0=45"
+ "+lon_0=-100"
+ "+x_0=0"
+ "+y_0=0"
+ "+a=6370997"
+ "+b=6370997"
+ "+units=m"
+ "+no_defs"
+ END # END PROJECTION
+ TYPE RASTER
+ STATUS OFF
+ VALIDATION
+ "mask" "^[a-zA-Z0-9_]+$"
+ "default_mask" "empty_mask"
+ END # END VALIDATION
+ DATA {data_location}
+ TEMPLATE layer_query_body.html # THIS DOES NOT EXIST AT THE MOMENT BUT IT IS NEEDED TO HAVE queryable=1
+ #GROUP "{group_name}"
+ INCLUDE "new-forwarn2-standard-2.cmap"
+ METADATA
+ "wms_title" "{metadata_name}"
+ #"wms_group_title" "{group_name}"
+ "wms_extent" "-2401951.937575, -2238222.70389, 2345858.525679, 967021.455769"
+ "wms_abstract" "{metadata_name}"
+ "wcs_label" "{metadata_name}"
+ "wcs_rangeset_name" "{metadata_name}"
+ "wcs_rangeset_label" "{metadata_name}"
+ "wcs_bandcount" "1"
+ "wcs_formats" "GEOTIFF"
+ "wcs_nativeformat" "8-bit GeoTIF"
+ "gml_include_items" "value_0"
+ END # end METADATA
+ MASK '%mask%'
+ END # end LAYER
diff --git a/src/App.jsx b/src/App.jsx
index 228c47d4..69aed575 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,15 +1,15 @@
import React from 'react';
import dayjs from 'dayjs';
-import { MapContainer, WMSTileLayer } from "react-leaflet";
-import Paper from '@mui/material/Paper';
-import Typography from '@mui/material/Typography';
+import { MapContainer, useMapEvents, WMSTileLayer } from "react-leaflet";
import Slider from '@mui/material/Slider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
+import {IconButton} from "@mui/material";
import Grid from '@mui/material/Unstable_Grid2'; // Grid version 2
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import PauseIcon from '@mui/icons-material/Pause';
+import ShowChartIcon from '@mui/icons-material/ShowChart';
import styled from "@emotion/styled";
import {
useQuery,
@@ -23,24 +23,25 @@ import BasicButton from './components/BasicButton';
import BasicDatePicker from './components/BasicDatePicker';
import DateSlider from './components/DateSlider';
import { config } from './config';
-import { webMercatorToLatLng, convertStringToDate } from "./utils.js";
+import {webMercatorToLatLng, convertStringToDate, parseDateString} from "./utils.js";
import BasicText from "./components/BasicText.jsx";
export const StyledMapContainer = styled(MapContainer)(() => ({
height: '100%',
- width: '100%'
+ width: '100%',
}));
function App() {
+ const [map, setMap] = React.useState(null)
const [changeProduct, setChangeProduct] = React.useState(config.wmsLayers['FW3 1 year']);
const [mask, setMask] = React.useState(config.masks['MaskForForest']);
- const [overlay, setOverlay] = React.useState(config.vectorLayers['Tropical Cyclone Lines 2022']);
+ const [overlay, setOverlay] = React.useState(config.vectorLayers['Tropical Cyclone Lines Since 1980']);
const [basemap, setBasemap] = React.useState(config.basemaps['ArcGIS Imagery']);
const [availableLayers, setAvailableLayers] = React.useState([]);
const [activeLayerIndex, setActiveLayerIndex] = React.useState(0);
const [rasterOpacity, setRasterOpacity] = React.useState(75);
const [startDate, setStartDate] = React.useState(dayjs('2024-07-01'));
- const [endDate, setEndDate] = React.useState(dayjs('2024-07-31'));
+ const [endDate, setEndDate] = React.useState(dayjs('2024-07-08'));
const [isPlaying, setIsPlaying] = React.useState(false);
const [playSpeed, setPlaySpeed] = React.useState(config.playSpeeds['2x']);
const [unFilteredLayers, setUnfilteredLayers] = React.useState([]);
@@ -87,8 +88,8 @@ function App() {
};
const handleMaskChange = (event) => {
- const selectedMask = config.masks(event.target.value);
- setMask(selectedMask);
+ const selectedMask = event.target.value;
+ setMask(config.masks[selectedMask]);
}
const handleOverlayChange = (event) => {
@@ -101,6 +102,36 @@ function App() {
setBasemap(config.basemaps[selectedBasemap]);
}
+ const NdviChartButton = () => {
+ const map = useMapEvents({
+ click() {
+ if(map.getContainer().style.cursor === 'crosshair') {
+ console.log('map click for graph')
+ map.getContainer().style.cursor = 'grab'
+ }
+ }
+ })
+ const chartOnClick = (event) => {
+ event.stopPropagation();
+ if(map.getContainer().style.cursor === 'grab') {
+ map.getContainer().style.cursor = 'crosshair';
+ return
+ }
+ map.getContainer().style.cursor = 'grab';
+ }
+
+ return (
+ chartOnClick(event)}
+ >
+
+
+ )
+ }
+
const handleIsPlayingPress = (event) => {
let currentLayerIndex = activeLayerIndex;
if (isPlaying) {
@@ -135,7 +166,6 @@ function App() {
// Update available layers when the getCapabilities query has returned
React.useEffect(() => {
if (!data) return;
- // const layerName = event.target.value;
const layers = data?.getElementsByTagName('Layer');
const queryableLayers = layers.filter(layer => layer.attributes.queryable === "1");
const availableLayers = [];
@@ -168,10 +198,11 @@ function App() {
const northEast = webMercatorToLatLng(maxX, maxY);
const southEast = webMercatorToLatLng(maxX, minY);
-// Calculate the center
+ // Calculate the center
const centerLat = (southWest[0] + northWest[0] + northEast[0] + southEast[0]) / 4;
const centerLng = (southWest[1] + northWest[1] + northEast[1] + southEast[1]) / 4;
+
return (
@@ -243,53 +274,69 @@ function App() {
onClick={(event) => handleIsPlayingPress(event)}
/>
-
-
-
- {availableLayers.map((layer, index) => (
+
+
+
+ {/*{availableLayers.map((layer, index) => (*/}
+ {/* */}
+ {/*))}*/}
- ))}
-
-
-
-
-
-
-
-
+
+
+
+
)
}
diff --git a/src/config.js b/src/config.js
index ee20fc58..940c00ab 100644
--- a/src/config.js
+++ b/src/config.js
@@ -18,9 +18,14 @@ export const config = {
url: wmsUrl.concat('forwarn3_products_1yr.map'),
layer_regex: /^forwarn3_products_1yr_(\d{4})(\d{2})(\d{2})$/
},
+ 'forwarn3_products_1yr': {
+ name: 'forwarn3_products_1yr',
+ url: wmsUrl.concat('test_runtime_sub.map'),
+ layer_regex: /^forwarn3_products_1yr_(\d{4})(\d{2})(\d{2})$/
+ },
'FW3 2 year Early Detect': {
name: 'FW3 2 year Early Detect',
- url: wmsUrlFull,
+ url: wmsUrl,
layer_regex: /^forwarn3_products_2yrED_(\d{4})(\d{2})(\d{2})$/
},
'FW3 2 year Early Early Detect': {
@@ -129,6 +134,11 @@ export const config = {
name: 'Tropical Cyclone Lines 2023',
url: wmsUrl.concat('vlayers.map'),
layerName: 'tropical_cyclone_lines_2023'
+ },
+ 'Tropical Cyclone Lines Since 1980': {
+ name: 'Tropical Cyclone Lines Since 1980',
+ url: wmsUrl.concat('vector_map_files/tropical_cyclone_lines.map'),
+ layerName: 'tropical_cyclone_lines_since_1980'
}
},
masks: {
diff --git a/src/utils.js b/src/utils.js
index 7beafb09..4ca0c731 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -25,9 +25,21 @@ export function calculateCenterAndZoom(extent) {
return { center: [center.lat, center.lng], zoom };
}
-export const convertStringToDate = (dateString) => {
+export function convertStringToDate(dateString) {
const year = dateString.slice(0, 4);
const month = dateString.slice(4, 6);
const day = dateString.slice(6, 8);
return new Date(`${year}-${month}-${day}T00:00:00-04:00`);
-};
\ No newline at end of file
+};
+
+// parses "2024-06-26_2024-07-19.napolygon.1yrdeparture.LAEA.img" into "20240719
+export function parseDateString(inputString) {
+ // Split the string by underscore and period
+ const parts = inputString.split('_')[1].split('.');
+
+ // Extract the date part (2024-07-19)
+ const datePart = parts[0];
+
+ // Remove hyphens and return only the digits
+ return datePart.replace(/-/g, '');
+}
\ No newline at end of file