def publish_run(request): """ Publish a scenario run to Cambium (https://cambium.nrel.gov/) Parameters: model_uuid (uuid): required run_id (int): required Returns (json): Action Confirmation Example: POST: /api/publish_run/ """ model_uuid = request.POST["model_uuid"] run_id = request.POST["run_id"] model = Model.by_uuid(model_uuid) model.handle_edit_access(request.user) run = model.runs.filter(id=run_id).first() msg = Cambium.push_run(run) payload = {'message': msg} return HttpResponse(json.dumps(payload), content_type="application/json")
def map_viz_view(request, model_uuid, run_id): """ Example: http://0.0.0.0:8000/<model_uuid>/<run_id>/map_viz """ model = Model.by_uuid(model_uuid) try: can_edit = model.handle_view_access(request.user) except Exception: return HttpResponseRedirect(reverse('home')) run = model.runs.filter(id=run_id).first() subset_time = run.subset_time # 2005-01-01 to 2005-01-07 run_min_date, run_max_date = re.match( "^(\d{4}-\d{2}-\d{2}) to (\d{4}-\d{2}-\d{2})$", subset_time).groups() context = { "timezones": common_timezones, "model": model, "run": run, "scenario": run.scenario, "mapbox_token": settings.MAPBOX_TOKEN, "can_edit": can_edit, "run_min_date": run_min_date, "run_max_date": run_max_date } return render(request, "map_viz.html", context)
def scenarios_view(request, model_uuid): """ View the "Scenarios" page Parameters: model_uuid (uuid): required Returns: HttpResponse Example: http://0.0.0.0:8000/<model_uuid>/scenarios """ model = Model.by_uuid(model_uuid) try: can_edit = model.handle_view_access(request.user) except Exception: return HttpResponseRedirect(reverse('home')) scenarios = model.scenarios session_scenario_id = request.session.get('scenario_id', None) session_scenario = scenarios.filter(id=session_scenario_id).first() context = { "timezones": common_timezones, "model": model, "scenarios": scenarios, "session_scenario": session_scenario, "mapbox_token": settings.MAPBOX_TOKEN, "can_edit": can_edit, "help_content": Help_Guide.get_safe_html('scenarios'), } return render(request, "scenarios.html", context)
def add_technologies_view(request, model_uuid): """ View the "Add Technology" page Parameters: model_uuid (uuid): required Returns: HttpResponse Example: http://0.0.0.0:8000/<model_uuid>/add_technologies_view """ model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) public_model_ids = Model.objects.filter(snapshot_version=None, public=True).values_list('id', flat=True) public_techs = Technology.objects.filter(model_id__in=public_model_ids) context = { "timezones": common_timezones, "model": model, "abstract_techs": Abstract_Tech.objects.all(), "public_techs": public_techs, "my_techs": model.technologies, "can_edit": can_edit, "help_content": Help_Guide.get_safe_html('add_technology'), } return render(request, "add_technology.html", context)
def timeseries_view(request, model_uuid): """ View the "Timeseries" page Parameters: model_uuid (uuid): required Returns: HttpResponse Example: http://0.0.0.0:8000/<model_uuid>/timeseries/ """ model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) files = User_File.objects.filter(model=model, filename__contains=".csv") context = { "timezones": common_timezones, "model": model, "files": files, "can_edit": can_edit, "help_content": Help_Guide.get_safe_html('timeseries'), } return render(request, "timeseries.html", context)
def add_scenarios_view(request, model_uuid): """ View the "Add Scenario" page Parameters: model_uuid (uuid): required Returns: HttpResponse Example: http://0.0.0.0:8000/<model_uuid>/add_scenarios_view """ model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) context = { "timezones": common_timezones, "model": model, "scenarios": model.scenarios, "can_edit": can_edit, "help_content": Help_Guide.get_safe_html('add_scenario'), } return render(request, "add_scenario.html", context)
def parameters_view(request, model_uuid, parameter_name): """ View the "Parameters" page Parameters: model_uuid (uuid): required parameter_name (str): required Returns: HttpResponse Example: http://0.0.0.0:8000/<model_uuid>/parameters/resource/ """ model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) parameter = Parameter.objects.filter(name=parameter_name).first() context = { "timezones": common_timezones, "model": model, "parameter": parameter, "can_edit": can_edit, "help_content": Help_Guide.get_safe_html('parameters'), } return render(request, "parameters.html", context)
def timeseries_table(request, model_uuid): """ View the "Timeseries" page Parameters: model_uuid (uuid): required Returns: HttpResponse Example: http://0.0.0.0:8000/<model_uuid>/timeseries_table/ """ model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) timeseries = Timeseries_Meta.objects.filter(model=model) context = { "timezones": common_timezones, "model": model, "timeseries": timeseries, "can_edit": can_edit, } return render(request, "timeseries_table.html", context)
def plot_outputs(request): """ Retrieve the plots from a run path Parameters: model_uuid (uuid): required run_id (int): required Returns: HttpResponse Example: POST: /component/plot_outputs/ """ model_uuid = request.POST["model_uuid"] run_id = request.POST["run_id"] model = Model.by_uuid(model_uuid) model.handle_view_access(request.user) try: run = Run.objects.get(id=run_id) except Exception: raise Http404 with open(run.plots_path) as f: html = f.read() return HttpResponse(html, content_type="text/html")
def delete_run(request): """ Delete a scenario run Parameters: model_uuid (uuid): required run_id (int): required Returns (json): Action Confirmation Example: POST: /api/delete_run/ """ model_uuid = request.POST["model_uuid"] run_id = request.POST["run_id"] model = Model.by_uuid(model_uuid) model.handle_edit_access(request.user) run = model.runs.filter(id=run_id) if run.outputs_key: data = { 'filename': run.outputs_key, 'project_uuid': str(model.uuid), 'private_key': settings.CAMBIUM_API_KEY, } try: url = urljoin(settings.CAMBIUM_URL, "api/remove-data/") requests.post(url, data=data).json() except Exception as e: print("Cambium removal failed - {}".format(e)) run.delete() return HttpResponseRedirect("")
def all_tech_params(request): """ Retrieve the parameters for a technology Parameters: model_uuid (uuid): required technology_id (int): required Returns: HttpResponse Example: GET: /component/all_tech_params/ """ model_uuid = request.GET['model_uuid'] technology_id = request.GET['technology_id'] request.session['technology_id'] = technology_id model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) technology = model.technologies.get(id=technology_id) essentials, parameters = ParamsManager.all_tech_params(technology) timeseries = Timeseries_Meta.objects.filter(model=model, failure=False, is_uploading=False) # Technology Definition context = {"technology": technology, "essentials": essentials, "carriers": model.carriers, "required_carrier_ids": [4, 5, 6], "cplus_carrier_ids": [66, 67, 68, 69], "can_edit": can_edit} html_essentials = list(render(request, 'technology_essentials.html', context))[0] # Parameters Table context = { "technology": technology, "model": model, "parameters": parameters, "carriers": model.carriers, "level": "1_tech", "timeseries": timeseries, "can_edit": can_edit} html_parameters = list(render(request, 'technology_parameters.html', context))[0] payload = { 'technology_id': technology_id, 'html_essentials': html_essentials.decode('utf-8'), 'html_parameters': html_parameters.decode('utf-8'), 'favorites': model.favorites} return HttpResponse(json.dumps(payload), content_type="application/json")
def add_run_precheck(request): """ Retrieve the precheck for a new scenario run Parameters: model_uuid (uuid): required scenario_id (int): required Returns: HttpResponse Example: GET: /component/add_run_precheck/ """ model_uuid = request.GET['model_uuid'] scenario_id = request.GET['scenario_id'] model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) scenario = model.scenarios.filter(id=scenario_id).first() runs = model.runs.filter(scenario=scenario) runs = runs.order_by('-created') prev_dates = [] for run in runs: start_date, end_date = run.subset_time.split(' to ') s_date = datetime.strptime(start_date, '%Y-%m-%d') e_date = datetime.strptime(end_date, '%Y-%m-%d') n_days = (e_date - s_date).days + 1 days = ' (' + str(n_days) + ' days)' s_date = '<b>' + s_date.strftime('%b. %-d, %Y') + '</b>' e_date = '<b>' + e_date.strftime('%b. %-d, %Y') + '</b>' formatted = s_date + ' to ' + e_date + days prev_date = (start_date, end_date, mark_safe(formatted)) if prev_date not in prev_dates: prev_dates.append(prev_date) timeseries, missing_timeseries = scenario.timeseries_precheck() context = { "prev_dates": prev_dates[:4], "model": model, "timeseries": timeseries, "missing_timseries": missing_timeseries, "can_edit": can_edit } html = list(render(request, 'add_run_precheck.html', context))[0] payload = {'html': html.decode('utf-8')} return HttpResponse(json.dumps(payload), content_type="application/json")
def map_outputs(request): """ Retrieve the data for rendering the nodal network map Parameters: model_uuid (uuid): required run_id (int): required Returns: JsonResponse Example: POST: /component/map_outputs/ """ model_uuid = request.POST['model_uuid'] run_id = request.POST['run_id'] start_date = pd.to_datetime(request.POST['start_date']) end_date = pd.to_datetime(request.POST['end_date']) + pd.DateOffset(days=1) model = Model.by_uuid(model_uuid) model.handle_view_access(request.user) run = model.runs.filter(id=run_id).first() response = defaultdict(lambda: None) if run is None: response["message"] = "To request data, " \ "post a valid 'model_uuid' and 'run_id'" else: files = [ "inputs_colors", "inputs_names", "inputs_inheritance", "inputs_loc_coordinates", "results_energy_cap" ] ts_files = ["results_carrier_con", "results_carrier_prod"] ts_dt_col = 3 for file in files: with open(os.path.join(run.outputs_path, file + ".csv")) as f: response[file] = f.read() for file in ts_files: df = pd.read_csv(os.path.join(run.outputs_path, file + ".csv"), header=None) df.set_index(ts_dt_col, inplace=True, drop=False) df.index = pd.to_datetime(df.index) df = df[(df.index >= start_date) & (df.index < end_date)] s = io.StringIO() df.to_csv(s, index=False, header=False) response[file] = s.getvalue() return JsonResponse(response)
def optimize(request): """ Optimize a Calliope problem Parameters: model_uuid (uuid): required run_id (int): required Returns (json): Action Confirmation Example: POST: /api/optimize/ """ run_id = request.POST["run_id"] model_uuid = request.POST["model_uuid"] model = Model.by_uuid(model_uuid) model.handle_edit_access(request.user) payload = {"run_id": run_id} # run instance does not exist. try: run = model.runs.get(id=run_id) except ObjectDoesNotExist as e: print(e) payload["message"] = "Run ID {} does not exist.".format(run_id) return HttpResponse(json.dumps(payload, indent=4), content_type="application/json") # model path does not exist model_path = os.path.join(run.inputs_path, "model.yaml") if not os.path.exists(model_path): payload["message"] = "Invalid model config path!" return HttpResponse(json.dumps(payload, indent=4), content_type="application/json") # run celery task async_result = run_model.apply_async(kwargs={ "run_id": run_id, "model_path": model_path, "user_id": request.user.id }) run_task, _ = CeleryTask.objects.get_or_create(task_id=async_result.id) run.run_task = run_task run.status = task_status.QUEUED run.save() payload = {"task_id": async_result.id} return HttpResponse(json.dumps(payload, indent=4), content_type="application/json")
def locations_view(request, model_uuid): """ View the "Locations" page Parameters: model_uuid (uuid): required Returns: HttpResponse Example: http://0.0.0.0:8000/<model_uuid>/locations """ model = Model.by_uuid(model_uuid) try: can_edit = model.handle_view_access(request.user) except Exception: return HttpResponseRedirect(reverse('home')) locations = model.locations.values() location_ids = [loc['id'] for loc in locations] lts = Loc_Tech.objects.filter( Q(location_1_id__in=location_ids) | Q(location_2_id__in=location_ids)) lts = lts.values("id", "technology_id", "location_1_id", "location_2_id", "technology__pretty_name", "technology__pretty_tag") loc_techs = {} for lt in lts: l1, l2 = lt["location_1_id"], lt["location_2_id"] if l1 not in loc_techs.keys(): loc_techs[l1] = [lt] else: loc_techs[l1].append(lt) if l2 is not None and l2 not in loc_techs.keys(): loc_techs[l2] = [lt] elif l2 is not None: loc_techs[l2].append(lt) context = { "nrel_api_key": settings.NREL_API_KEY, "timezones": common_timezones, "model": model, "locations": locations, "loc_techs": loc_techs, "mapbox_token": settings.MAPBOX_TOKEN, "can_edit": can_edit, "help_content": Help_Guide.get_safe_html('locations'), } return render(request, "locations.html", context)
def timeseries_content(request): """ Retrieve the meta data for all timeseries Parameters: model_uuid (uuid): required file_id (int): optional Returns: HttpResponse Example: GET: /component/timeseries_content/ """ model_uuid = request.GET['model_uuid'] file_id = request.GET.get('file_id', None) model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) file_record = User_File.objects.filter(model=model, id=file_id).first() file_data = None file_syspath = None file_size = None if file_record: if '.csv' in str(file_record.filename): file_syspath = os.path.join(settings.DATA_STORAGE, str(file_record.filename)) # optimized to only read first 24 lines of file # (instead of whole file and then get first 24 lines) file_data = pd.read_csv( file_syspath, header=None, nrows=24).to_dict('records') file_size = os.path.getsize(file_syspath) context = { "file_data": file_data, "file_size": file_size, "can_edit": can_edit, "letters": map(lambda x: 'Column ' + x, string.ascii_uppercase[0:len(file_data[0])])} html = list(render(request, 'timeseries_content.html', context))[0] payload = { 'html': html.decode('utf-8')} return HttpResponse(json.dumps(payload), content_type="application/json")
def all_loc_tech_params(request): """ Retrieve the parameters for a node Parameters: model_uuid (uuid): required loc_tech_id (int): required Returns: HttpResponse Example: GET: /component/all_loc_tech_params/ """ model_uuid = request.GET['model_uuid'] loc_tech_id = int(request.GET['loc_tech_id']) request.session['loc_tech_id'] = loc_tech_id model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) loc_tech = model.loc_techs.get(id=loc_tech_id) parameters = ParamsManager.all_loc_tech_params(loc_tech) timeseries = Timeseries_Meta.objects.filter(model=model, failure=False, is_uploading=False) # Parameters Table context = { "loc_tech": loc_tech, "model": model, "parameters": parameters, "carriers": model.carriers, "level": "2_loc_tech", "timeseries": timeseries, "can_edit": can_edit} html_parameters = list(render(request, 'technology_parameters.html', context))[0] payload = { 'loc_tech_id': loc_tech_id, 'html_parameters': html_parameters.decode('utf-8'), 'favorites': model.favorites} return HttpResponse(json.dumps(payload), content_type="application/json")
def all_loc_techs(request): """ Retrieve the nodes for a technology Parameters: model_uuid (uuid): required technology_id (int): required Returns: HttpResponse Example: GET: /component/all_loc_techs/ """ model_uuid = request.GET['model_uuid'] technology_id = int(request.GET['technology_id']) request.session['technology_id'] = technology_id session_loc_tech_id = request.session.get('loc_tech_id', None) model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) technology = model.technologies.filter(id=technology_id).first() loc_techs = model.loc_techs.filter(technology_id=technology_id) context = { "model": model, "locations": model.locations, "technology": technology, "loc_techs": loc_techs, "session_loc_tech_id": session_loc_tech_id, "can_edit": can_edit} html_essentials = list(render(request, 'loc_tech_essentials.html', context))[0] payload = { 'technology_id': technology_id, 'html_essentials': html_essentials.decode('utf-8'), 'loc_techs': list(loc_techs.values()) } return JsonResponse(payload)
def download(request): """ Download files from a path to client machine Parameters: model_uuid (uuid): required run_id (int): required Returns (json): Action Confirmation Example: GET: /api/download/ """ model_uuid = request.GET['model_uuid'] run_id = request.GET['run_id'] download_type = request.GET['type'] model = Model.by_uuid(model_uuid) model.handle_view_access(request.user) try: run = Run.objects.get(id=run_id) except Exception: raise Http404 if download_type == 'inputs': path = run.inputs_path elif download_type == "outputs": path = run.outputs_path else: raise Http404 if os.path.exists(path): file_path = zip_folder(path) with open(file_path, 'rb') as fh: response = HttpResponse(fh.read(), content_type="application/text") response[ 'Content-Disposition'] = 'inline; filename=' + os.path.basename( file_path) return response return HttpResponse(json.dumps({"message": "Not Found!"}, indent=4), content_type="application/json")
def timeseries_new(request): """ Retrieve form for building a new timeseries Parameters: model_uuid (uuid): required file_id (int): optional Returns: HttpResponse Example: GET: /component/timeseries_new/ """ model_uuid = request.GET['model_uuid'] file_id = request.GET.get('file_id', None) model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) columns = None file_record = User_File.objects.filter(model=model, id=file_id).first() if file_record: filename = file_record.filename try: columns = get_cols_from_csv(filename) except Exception as e: print('Doesn\'t exist or could not read columns: ' + filename) print(e) context = { "columns": columns, "filename": os.path.basename(filename.name), "can_edit": can_edit, "letters": map(lambda x: 'Column ' + x, string.ascii_uppercase[0:len(columns)])} html = list(render(request, 'timeseries_new.html', context))[0] payload = { 'html': html.decode('utf-8')} return HttpResponse(json.dumps(payload), content_type="application/json")
def run_dashboard(request): """ Retrieve the runs for a scenario Parameters: model_uuid (uuid): required scenario_id (int): optional Returns: HttpResponse Example: POST: /component/run_dashboard/ """ model_uuid = request.POST['model_uuid'] scenario_id = request.POST.get('scenario_id', None) if scenario_id is not None: request.session['scenario_id'] = scenario_id model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) runs = model.runs.filter(scenario_id=scenario_id) # Check for any publication updates for run in runs.filter(published=None): Cambium.push_run(run) context = { "model": model, "runs": runs, "can_edit": can_edit, "task_status": task_status, "cambium_configured": bool(settings.CAMBIUM_API_KEY) } html = list(render(request, 'run_dashboard.html', context))[0] payload = {'html': html.decode('utf-8')} return HttpResponse(json.dumps(payload), content_type="application/json")
def loc_techs_view(request, model_uuid): """ View the "Nodes" page Parameters: model_uuid (uuid): required Returns: HttpResponse Example: http://0.0.0.0:8000/<model_uuid>/loc_techs """ model = Model.by_uuid(model_uuid) try: can_edit = model.handle_view_access(request.user) except Exception: return HttpResponseRedirect(reverse('home')) technologies = model.technologies.values("id", "pretty_name", "pretty_tag", "abstract_tech__icon") session_technology_id = request.GET.get('tech_id', None) session_loc_tech_id = request.GET.get('loc_tech_id', None) if not session_technology_id: session_technology_id = request.session.get('technology_id', None) if session_technology_id: session_technology_id = int(session_technology_id) if session_loc_tech_id: request.session['loc_tech_id'] = int(session_loc_tech_id) context = { "timezones": common_timezones, "model": model, "technologies": list(technologies), "session_technology_id": session_technology_id, "can_edit": can_edit, "mapbox_token": settings.MAPBOX_TOKEN, "help_content": Help_Guide.get_safe_html('nodes'), } return render(request, "loc_techs.html", context)
def model_view(request, model_uuid): """ View the main model "Activity" page Parameters: model_uuid (uuid): required Returns: HttpResponse Example: http://0.0.0.0:8000/<model_uuid>/ """ model = Model.by_uuid(model_uuid) try: can_edit = model.handle_view_access(request.user) except Exception: return HttpResponseRedirect(reverse('home')) if request.user.is_authenticated: # Update last_access model_user = Model_User.objects.filter(user=request.user, model=model) if len(model_user) > 0: mu = model_user.first() mu.notifications = 0 mu.save() comments = Model_Comment.objects.filter(model=model) context = { "timezones": common_timezones, "user": request.user, "model": model, "comments": comments, "can_edit": can_edit, "help_content": Help_Guide.get_safe_html('model'), } return render(request, "activity.html", context)
def update_run_description(request): """ Update the description for a run Parameters: model_uuid (uuid): required run_id (int): required description (str): required Returns (json): Action Confirmation Example: POST: /api/update_run_description/ """ model_uuid = request.POST["model_uuid"] run_id = int(request.POST["id"]) description = request.POST["value"] model = Model.by_uuid(model_uuid) model.handle_edit_access(request.user) try: run = model.runs.get(id=run_id) except ObjectDoesNotExist as e: print(e) payload = {} payload["message"] = "Run ID {} does not exist.".format(run_id) return HttpResponse(json.dumps(payload, indent=4), content_type="application/json") if description != run.description: run.description = description run.save() payload = description return HttpResponse(payload, content_type="text/plain")
def test_model_query(self): uuid1 = str(self.model.uuid) self.assertEqual(Model.by_uuid(uuid1), self.model)
def location_coordinates(request): """ Retrieve the coordinates of locations in model Parameters: model_uuid (uuid): required scenario_id (int): optional technology_id (int): optional loc_tech_id (int): optional Returns: JsonResponse Example: GET: /component/location_coordinates/ """ model_uuid = request.GET['model_uuid'] scenario_id = request.GET.get('scenario_id', None) technology_id = request.GET.get('technology_id', None) loc_tech_id = request.GET.get('loc_tech_id', None) model = Model.by_uuid(model_uuid) model.handle_view_access(request.user) locations = list(model.locations.values()) # Get Locations included in Scenario scenario_loc_techs = Scenario_Loc_Tech.objects.filter( scenario_id=scenario_id) selected_ids = [] transmissions = [] for slt in scenario_loc_techs: selected_ids.append(slt.loc_tech.location_1_id) selected_ids.append(slt.loc_tech.location_2_id) if slt.loc_tech.location_2_id: trans = { 'id': slt.loc_tech_id, 'name': slt.loc_tech.technology.pretty_name, 'lat1': slt.loc_tech.location_1.latitude, 'lon1': slt.loc_tech.location_1.longitude, 'lat2': slt.loc_tech.location_2.latitude, 'lon2': slt.loc_tech.location_2.longitude, } transmissions.append(trans) # Get unselected Location Technologies unselected_ids = [] loc_techs = model.loc_techs.filter(technology_id=technology_id) for lt in loc_techs: unselected_ids.append(lt.location_1_id) # Get selected Location Technology loc_tech = model.loc_techs.filter(id=loc_tech_id).first() if loc_tech: selected_ids.append(loc_tech.location_1_id) selected_ids.append(loc_tech.location_2_id) selected_ids = list(set(selected_ids)) # Set Location View Type for i in range(len(locations)): if locations[i]['id'] in selected_ids: locations[i]['type'] = 'selected' elif locations[i]['id'] in unselected_ids: locations[i]['type'] = 'unselected' else: locations[i]['type'] = 'reference' response = { 'locations': locations, 'transmissions': transmissions, } return JsonResponse(response, safe=False)
def timeseries_view(request): """ Retrieve timeseries data Parameters: model_uuid (uuid): required timeseries_meta_id (int): required start_date (timestamp): required end_date (timestamp): required Returns: JsonResponse Example: GET: /component/timeseries_view/ """ model_uuid = request.GET.get('model_uuid', None) timeseries_meta_id = request.GET.get('ts_id', None) start_date = request.GET.get('start_date', None) end_date = request.GET.get('end_date', None) model = Model.by_uuid(model_uuid) model.handle_view_access(request.user) timeseries_meta = Timeseries_Meta.objects.get(id=timeseries_meta_id) timeseries = timeseries_meta.get_timeseries() min_date, max_date = timeseries_meta.get_period() # Validate start_date, end_date if start_date is not None: try: start_date = make_aware(datetime.strptime( start_date.strip()[0:10], '%Y-%m-%d')).replace(tzinfo=None) except ValueError: start_date = None if end_date is not None: try: end_date = make_aware(datetime.strptime( end_date.strip()[0:10], '%Y-%m-%d')).replace(tzinfo=None) except ValueError: end_date = None if start_date is not None and end_date is not None: if start_date > end_date: temp_date = start_date start_date = end_date end_date = temp_date if end_date - start_date <= timedelta(days=1): # add one day end_date = start_date + timedelta(days=1) if start_date is not None: if start_date <= min_date or start_date >= max_date: start_date = min_date timeseries = timeseries[timeseries.datetime >= start_date] if end_date is not None: if end_date <= min_date or end_date >= (max_date + timedelta(days=1)): end_date = max_date + timedelta(days=1) timeseries = timeseries[timeseries.datetime < end_date] if len(timeseries) > 8784: # hours in one year # get max value for each day timeseries = timeseries.resample('D').max() timestamps = timeseries.datetime.dt.strftime( '%Y-%m-%d %H:%M:%S').values.tolist() values = timeseries.value.values.tolist() payload = { 'timestamps': timestamps, 'values': values, } return JsonResponse(payload)
def scenario(request): """ Retrieve the parameters and nodes for a scenario Parameters: model_uuid (uuid): required scenario_id (int): required Returns: HttpResponse Example: GET: /component/scenario/ """ model_uuid = request.GET['model_uuid'] scenario_id = request.GET['scenario_id'] request.session['scenario_id'] = scenario_id model = Model.by_uuid(model_uuid) can_edit = model.handle_view_access(request.user) # Scenario Parameters colors = model.color_lookup parameters = Scenario_Param.objects.filter( model_id=model.id, scenario_id=scenario_id, run_parameter__user_visibility=True) # All Loc Techs loc_techs = [] lts = model.loc_techs lts = lts.values('id', 'technology_id', 'technology__pretty_name', 'technology__pretty_tag', 'technology__abstract_tech__icon', 'location_1__pretty_name', 'location_2__pretty_name') for lt in lts: tech_id = lt["technology_id"] color = colors[tech_id] if tech_id in colors.keys() else "#000" loc_techs.append({ "id": lt['id'], "technology_id": lt['technology_id'], "tag": lt["technology__pretty_tag"], "technology": lt["technology__pretty_name"], "location_1": lt["location_1__pretty_name"], "location_2": lt["location_2__pretty_name"], "color": color, "icon": lt["technology__abstract_tech__icon"]}) # Active Loc Techs active_lts = Scenario_Loc_Tech.objects.filter(scenario_id=scenario_id) active_lt_ids = list(active_lts.values_list("loc_tech_id", flat=True)) # Filters Data unique_techs = [v['technology'] for v in loc_techs] unique_tags = [v['tag'] for v in loc_techs] locations = [(v['location_1'], v['location_2']) for v in loc_techs] unique_locations = [item for sublist in locations for item in sublist] context = { "model": model, "parameters": parameters, "can_edit": can_edit} scenario_settings = list(render(request, 'scenario_settings.html', context))[0] context = { "model": model, "colors": colors, "carrier_ins": model.carrier_lookup(True), "carrier_outs": model.carrier_lookup(False), "active_lt_ids": active_lt_ids, "loc_techs": loc_techs, "scenario_id": scenario_id, "unique_techs": sorted(filter(None, set(unique_techs))), "unique_tags": sorted(filter(None, set(unique_tags))), "unique_locations": sorted(filter(None, set(unique_locations))), "can_edit": can_edit} scenario_configuration = list(render(request, 'scenario_configuration.html', context))[0] payload = { 'model_id': model.id, 'scenario_id': scenario_id, 'loc_techs': loc_techs, 'active_lt_ids': active_lt_ids, 'scenario_settings': scenario_settings.decode('utf-8'), 'scenario_configuration': scenario_configuration.decode('utf-8')} return HttpResponse(json.dumps(payload, indent=4), content_type="application/json")
def haven(request): """ Retrieve the data for a run Parameters: model_uuid (uuid): optional scenario_id (int): optional stations_only (bool): optional aggregate (dict): optional, for example, {"solar": [1,2,4]} Returns (json): Requested Data Example: POST: /api/haven/ """ if request.method != "POST": msg = "Method is not allowed." response = HttpResponse(json.dumps({"error": msg}), content_type="application/json") return response user = request.user if not user.is_authenticated: msg = "User is not authenticated." return HttpResponse(json.dumps({"error": msg}), content_type="application/json") # Parse post parameters model_uuid = request.POST.get('model_uuid', None) scenario_id = request.POST.get('scenario_id', None) stations_only = bool(request.POST.get('stations_only', True)) aggregate = request.POST.get('aggregate', None) # Construct initial payload payload = {} payload["inputs"] = { "model_uuid": model_uuid, "scenario_id": scenario_id, "stations_only": stations_only, "aggregage": aggregate } # Ensure model existing and access try: model = Model.by_uuid(model_uuid) model.handle_view_access(user) except ModelNotExistException: payload["message"] = f"To request data, post a valid 'model_uuid'." model_users = Model_User.objects.filter(user=user, model__snapshot_version=None) models = [{ "uuid": model_user.model.get_uuid(), "name": model_user.model.name } for model_user in model_users] payload["models"] = models return HttpResponse(json.dumps(payload), content_type="application/json") # Query user requested data. payload["selected_model_name"] = model.name scenario = model.scenarios.filter(id=scenario_id).first() if scenario is None: payload["message"] = "To request data, post a valid 'scenario_id'." scenarios = list(model.scenarios.values('id', 'name')) payload["scenarios"] = scenarios else: payload["selected_scenario_name"] = scenario.name try: haven_data = Haven(scenario).get_data(aggregate, stations_only) if isinstance(haven_data, str): payload["message"] = haven_data else: payload["message"] = "All data successfully retrieved." payload["scenario_data"] = haven_data except Exception as e: payload["message"] = str(e) return HttpResponse(json.dumps(payload), content_type="application/json")
def build(request): """ Build and save the input files (YAML and CSV) for a Calliope run. Parameters: model_uuid (uuid): required scenario_id (int): required start_date (timestamp): required end_date (timestamp): required Returns (json): Action Confirmation Example: GET: /api/build/ """ # Input parameters model_uuid = request.GET.get("model_uuid", None) scenario_id = request.GET.get("scenario_id", None) start_date = request.GET.get("start_date", None) end_date = request.GET.get("end_date", None) model = Model.by_uuid(model_uuid) model.handle_edit_access(request.user) try: start_date = datetime.strptime(start_date, "%Y-%m-%d") end_date = datetime.strptime(end_date, "%Y-%m-%d") + timedelta(hours=23) subset_time = str(start_date.date()) + " to " + str(end_date.date()) year = start_date.year # model and scenario instances scenario = model.scenarios.get(id=scenario_id) # Create run instance run = Run.objects.create( model=model, scenario=scenario, year=year, subset_time=subset_time, status=task_status.QUEUED, inputs_path="", ) # Generate File Path timestamp = datetime.now().strftime("%Y-%m-%d %H%M%S") model_name = ParamsManager.simplify_name(model.name) scenario_name = ParamsManager.simplify_name(scenario.name) inputs_path = "{}/{}/{}/{}/{}/{}/{}/inputs".format( settings.DATA_STORAGE, model.uuid, model_name, scenario_name, year, subset_time, timestamp, ) inputs_path = inputs_path.lower().replace(" ", "-") os.makedirs(inputs_path, exist_ok=True) # Celery task async_result = build_model.apply_async( kwargs={ "inputs_path": inputs_path, "run_id": run.id, "model_uuid": model_uuid, "scenario_id": scenario_id, "start_date": start_date, "end_date": end_date, }) build_task = CeleryTask.objects.get(task_id=async_result.id) run.build_task = build_task run.save() payload = { "status": "Success", "model_uuid": model_uuid, "scenario_id": scenario_id, "year": start_date.year, } except Exception as e: payload = { "status": "Failed", "message": "Please contact admin at [email protected] ' \ 'regarding this error: {}".format(str(e)), } return HttpResponse(json.dumps(payload, indent=4), content_type="application/json")