|
| 1 | +# Grid Cell and Subgrid Template Data |
| 2 | +# Loads CVs from CMIP-LD to avoid hardcoding |
| 3 | + |
| 4 | +import cmipld |
| 5 | +from cmipld.utils.ldparse import name_multikey_extract |
| 6 | + |
| 7 | +# Data for this template - loaded from CVs |
| 8 | +DATA = { |
| 9 | + # Grid types from CV |
| 10 | + 'grid_type': name_multikey_extract( |
| 11 | + cmipld.get('constants:grid_type/graph.jsonld', depth=0), |
| 12 | + ['id', 'validation_key'], 'validation_key' |
| 13 | + ), |
| 14 | + |
| 15 | + # Grid mapping from CV |
| 16 | + 'grid_mapping': name_multikey_extract( |
| 17 | + cmipld.get('constants:grid_mapping/graph.jsonld', depth=0), |
| 18 | + ['id', 'validation_key'], 'validation_key' |
| 19 | + ), |
| 20 | + |
| 21 | + # Region from CV |
| 22 | + 'region': name_multikey_extract( |
| 23 | + cmipld.get('constants:region/graph.jsonld', depth=0), |
| 24 | + ['id', 'validation_key'], 'validation_key' |
| 25 | + ), |
| 26 | + |
| 27 | + # Temporal refinement from CV |
| 28 | + 'temporal_refinement': name_multikey_extract( |
| 29 | + cmipld.get('constants:temporal_refinement/graph.jsonld', depth=0), |
| 30 | + ['id', 'validation_key'], 'validation_key' |
| 31 | + ), |
| 32 | + |
| 33 | + # Units from CV |
| 34 | + 'units': name_multikey_extract( |
| 35 | + cmipld.get('constants:units/graph.jsonld', depth=0), |
| 36 | + ['id', 'validation_key'], 'validation_key' |
| 37 | + ), |
| 38 | + |
| 39 | + # Truncation method from CV |
| 40 | + 'truncation_method': name_multikey_extract( |
| 41 | + cmipld.get('constants:truncation_method/graph.jsonld', depth=0), |
| 42 | + ['id', 'validation_key'], 'validation_key' |
| 43 | + ), |
| 44 | + |
| 45 | + # Cell variable types from CV |
| 46 | + 'cell_variable_type': name_multikey_extract( |
| 47 | + cmipld.get('constants:cell_variable_type/graph.jsonld', depth=0), |
| 48 | + ['id', 'validation_key'], 'validation_key' |
| 49 | + ), |
| 50 | + |
| 51 | + # Issue metadata |
| 52 | + 'issue_kind': ['New', 'Modify'] |
| 53 | +} |
| 54 | + |
| 55 | + |
| 56 | +def generate_grid_cell_and_subgrid(issue_data): |
| 57 | + """ |
| 58 | + Generate horizontal_grid_cells and horizontal_subgrid from issue data. |
| 59 | + |
| 60 | + Auto-generates: |
| 61 | + - Grid cells description from properties |
| 62 | + - Subgrid description from variable types |
| 63 | + - IDs (g###, s###) |
| 64 | + - Cross-reference link |
| 65 | + |
| 66 | + Returns: |
| 67 | + dict: { |
| 68 | + 'grid_cells_id': 'g100', |
| 69 | + 'subgrid_id': 's100', |
| 70 | + 'entities': { |
| 71 | + 'horizontal_grid_cells': {...}, |
| 72 | + 'horizontal_subgrid': {...} |
| 73 | + } |
| 74 | + } |
| 75 | + """ |
| 76 | + # Get next available IDs |
| 77 | + grid_cells_id = get_next_id('horizontal_grid_cells') # e.g., g100 |
| 78 | + subgrid_id = get_next_id('horizontal_subgrid') # e.g., s100 |
| 79 | + |
| 80 | + # Auto-generate grid_cells description |
| 81 | + grid_cells_desc = generate_grid_cells_description(issue_data) |
| 82 | + # Example: "Global regular-latitude-longitude grid with 1.25° x 0.9° resolution and 55296 cells." |
| 83 | + |
| 84 | + # Auto-generate subgrid description |
| 85 | + subgrid_desc = generate_subgrid_description(issue_data) |
| 86 | + # Example: "Mass variables on a regular latitude-longitude grid." |
| 87 | + |
| 88 | + # Create grid_cells entity |
| 89 | + grid_cells = { |
| 90 | + 'validation_key': grid_cells_id, |
| 91 | + 'ui_label': '', |
| 92 | + 'description': grid_cells_desc, |
| 93 | + 'grid_type': issue_data['grid_type'], |
| 94 | + 'grid_mapping': issue_data['grid_mapping'], |
| 95 | + 'region': issue_data['region'], |
| 96 | + 'temporal_refinement': issue_data['temporal_refinement'], |
| 97 | + '@context': '_context', |
| 98 | + '@type': ['emd', 'wcrp:horizontal_grid_cells', 'esgvoc:HorizontalGridCells'], |
| 99 | + '@id': grid_cells_id |
| 100 | + } |
| 101 | + |
| 102 | + # Add optional fields if provided |
| 103 | + if issue_data.get('x_resolution'): |
| 104 | + grid_cells['x_resolution'] = float(issue_data['x_resolution']) |
| 105 | + if issue_data.get('y_resolution'): |
| 106 | + grid_cells['y_resolution'] = float(issue_data['y_resolution']) |
| 107 | + if issue_data.get('units'): |
| 108 | + grid_cells['units'] = issue_data['units'] |
| 109 | + if issue_data.get('n_cells'): |
| 110 | + grid_cells['n_cells'] = int(issue_data['n_cells']) |
| 111 | + if issue_data.get('southernmost_latitude'): |
| 112 | + grid_cells['southernmost_latitude'] = float(issue_data['southernmost_latitude']) |
| 113 | + if issue_data.get('westernmost_longitude'): |
| 114 | + grid_cells['westernmost_longitude'] = float(issue_data['westernmost_longitude']) |
| 115 | + if issue_data.get('truncation_method'): |
| 116 | + grid_cells['truncation_method'] = issue_data['truncation_method'] |
| 117 | + if issue_data.get('truncation_number'): |
| 118 | + grid_cells['truncation_number'] = int(issue_data['truncation_number']) |
| 119 | + |
| 120 | + # Create subgrid entity (auto-linked) |
| 121 | + subgrid = { |
| 122 | + 'validation_key': subgrid_id, |
| 123 | + 'ui_label': '', |
| 124 | + 'description': subgrid_desc, |
| 125 | + 'cell_variable_type': issue_data['cell_variable_type'], |
| 126 | + 'horizontal_grid_cells': grid_cells_id, # Auto-link |
| 127 | + '@context': '_context', |
| 128 | + '@type': ['emd', 'wcrp:horizontal_subgrid', 'esgvoc:HorizontalSubgrid'], |
| 129 | + '@id': subgrid_id |
| 130 | + } |
| 131 | + |
| 132 | + return { |
| 133 | + 'grid_cells_id': grid_cells_id, |
| 134 | + 'subgrid_id': subgrid_id, |
| 135 | + 'entities': { |
| 136 | + 'horizontal_grid_cells': grid_cells, |
| 137 | + 'horizontal_subgrid': subgrid |
| 138 | + } |
| 139 | + } |
| 140 | + |
| 141 | + |
| 142 | +def generate_grid_cells_description(data): |
| 143 | + """Generate description for grid_cells from properties.""" |
| 144 | + parts = [] |
| 145 | + |
| 146 | + # Region |
| 147 | + if data.get('region'): |
| 148 | + if 'global' in data['region']: |
| 149 | + parts.append('Global') |
| 150 | + else: |
| 151 | + parts.append(' '.join(data['region'])) |
| 152 | + |
| 153 | + # Grid type |
| 154 | + parts.append(data.get('grid_type', '').replace('-', ' ')) |
| 155 | + parts.append('grid') |
| 156 | + |
| 157 | + # Resolution |
| 158 | + if data.get('x_resolution') and data.get('y_resolution'): |
| 159 | + parts.append(f"with {data['x_resolution']}° x {data['y_resolution']}° resolution") |
| 160 | + |
| 161 | + # Cell count |
| 162 | + if data.get('n_cells'): |
| 163 | + parts.append(f"and {data['n_cells']} cells") |
| 164 | + |
| 165 | + return ' '.join(parts) + '.' |
| 166 | + |
| 167 | + |
| 168 | +def generate_subgrid_description(data): |
| 169 | + """Generate description for subgrid from variable types.""" |
| 170 | + var_types = data.get('cell_variable_type', []) |
| 171 | + grid_type = data.get('grid_type', '').replace('-', ' ') |
| 172 | + |
| 173 | + # Format variable types |
| 174 | + if len(var_types) == 1: |
| 175 | + var_str = var_types[0].replace('_', ' ').replace('-', ' ').capitalize() |
| 176 | + else: |
| 177 | + var_str = ' and '.join(v.replace('_', ' ') for v in var_types).capitalize() |
| 178 | + |
| 179 | + return f"{var_str} variables on a {grid_type} grid." |
0 commit comments