Skip to content

Commit

Permalink
Merge pull request #4879 from NREL/schedule-file-rel-path
Browse files Browse the repository at this point in the history
Schedule:File relative paths
  • Loading branch information
jmarrec authored Nov 2, 2023
2 parents 4d820d0 + 28a3f30 commit d8026ec
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 11 deletions.
9 changes: 8 additions & 1 deletion resources/model/OpenStudio.idd
Original file line number Diff line number Diff line change
Expand Up @@ -5104,13 +5104,20 @@ OS:Schedule:File,
\key 20
\key 30
\key 60
A7 ; \field Adjust Schedule for Daylight Savings
A7, \field Adjust Schedule for Daylight Savings
\note "No" means do not include Daylight Savings Time in the schedule, instead, use the schedule directly from the Schedule:File csv (default)
\note "Yes" means include Daylight Savings Time to the schedule
\type choice
\key Yes
\key No
\default Yes
A8; \field Translate File With Relative Path
\note "No" means the absolute path of the ExternalFile is resolved and translated to IDF.
\note "Yes" means only the filename (relative) is translated
\type choice
\default No
\key Yes
\key No

\group OpenStudio Geometry

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,8 @@ namespace energyplus {
idfObject.setString(openstudio::Schedule_FileFields::ScheduleTypeLimitsName, idfScheduleTypeLimits->name().get());
}
}

path filePath = modelObject.externalFile().filePath();
if (!exists(filePath)) {
LOG(Warn, "Cannot find file \"" << filePath << "\"");
} else {
// make the path correct for this system
filePath = system_complete(filePath);
}

// DLM: this path is going to be in the temp dir, might want to fix it up when saving model temp dir
idfObject.setString(openstudio::Schedule_FileFields::FileName, toString(filePath));
idfObject.setString(openstudio::Schedule_FileFields::FileName, toString(modelObject.translatedFilePath()));

idfObject.setInt(openstudio::Schedule_FileFields::ColumnNumber, modelObject.columnNumber());
idfObject.setInt(openstudio::Schedule_FileFields::RowstoSkipatTop, modelObject.rowstoSkipatTop());
Expand Down
141 changes: 141 additions & 0 deletions src/energyplus/Test/ScheduleInterval_GTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@
#include "../../model/ScheduleFixedInterval_Impl.hpp"
#include "../../model/ScheduleVariableInterval.hpp"
#include "../../model/ScheduleVariableInterval_Impl.hpp"
#include "../../model/ExternalFile.hpp"
#include "../../model/ExternalFile_Impl.hpp"
#include "../../model/ScheduleFile.hpp"
#include "../../model/ScheduleFile_Impl.hpp"
#include "../../model/YearDescription.hpp"
#include "../../model/YearDescription_Impl.hpp"

#include <utilities/idd/IddEnums.hxx>

#include "../../utilities/core/PathHelpers.hpp"
#include "../../utilities/core/Filesystem.hpp"
#include <resources.hxx>

#include <boost/regex.hpp>

#include <sstream>
Expand Down Expand Up @@ -1850,3 +1856,138 @@ TEST_F(EnergyPlusFixture, DISABLED_ForwardTranslator_ScheduleVariableInterval_Da
// check that there were XX untils
//EXPECT_EQ(864, numUntils);
}

TEST_F(EnergyPlusFixture, ScheduleFileRelativePath) {

openstudio::path absoluteScheduleFilePath = resourcesPath() / toPath("model/schedulefile.csv");
ASSERT_TRUE(openstudio::filesystem::is_regular_file(absoluteScheduleFilePath));
ASSERT_TRUE(absoluteScheduleFilePath.is_absolute());

openstudio::path curDirPath = boost::filesystem::current_path();
openstudio::path relativeScheduleFilePath = openstudio::filesystem::relative(absoluteScheduleFilePath, curDirPath);
ASSERT_TRUE(relativeScheduleFilePath.is_relative());

// ScheduleFile(external_file(/abs/path))
{
Model model;
EXPECT_EQ(0u, model.getConcreteModelObjects<ExternalFile>().size());
EXPECT_EQ(0u, model.getConcreteModelObjects<ScheduleFile>().size());

boost::optional<ExternalFile> external_file = ExternalFile::getExternalFile(model, openstudio::toString(absoluteScheduleFilePath));
ASSERT_TRUE(external_file);
ScheduleFile schedule(*external_file);
EXPECT_TRUE(schedule.setTranslateFileWithRelativePath(true));
EXPECT_TRUE(schedule.translateFileWithRelativePath());
EXPECT_EQ(1u, model.getConcreteModelObjects<ScheduleFile>().size());
EXPECT_EQ(1u, model.getConcreteModelObjects<ExternalFile>().size());
ExternalFile externalfile = schedule.externalFile();
EXPECT_EQ(1u, externalfile.scheduleFiles().size());
EXPECT_EQ(openstudio::toString(absoluteScheduleFilePath.filename()), externalfile.fileName());
EXPECT_TRUE(toPath(externalfile.fileName()).is_relative());
EXPECT_FALSE(externalfile.filePath().is_relative());
EXPECT_NE(toPath(externalfile.fileName()), externalfile.filePath());

ForwardTranslator ft;
Workspace workspace = ft.translateModel(model);

std::vector<WorkspaceObject> objects = workspace.getObjectsByType(IddObjectType::Schedule_File);
ASSERT_EQ(1u, objects.size());

boost::optional<std::string> fileName = objects[0].getString(2); // File Name
ASSERT_TRUE(fileName);
EXPECT_TRUE(toPath(fileName.get()).is_relative()); // rel path
EXPECT_NE(externalfile.filePath(), fileName.get());
}

// ScheduleFile(external_file(/rel/path))
{
Model model;
EXPECT_EQ(0u, model.getConcreteModelObjects<ExternalFile>().size());
EXPECT_EQ(0u, model.getConcreteModelObjects<ScheduleFile>().size());

boost::optional<ExternalFile> external_file = ExternalFile::getExternalFile(model, openstudio::toString(relativeScheduleFilePath));
ASSERT_TRUE(external_file);
ScheduleFile schedule(*external_file);
EXPECT_TRUE(schedule.setTranslateFileWithRelativePath(true));
EXPECT_TRUE(schedule.translateFileWithRelativePath());
EXPECT_EQ(1u, model.getConcreteModelObjects<ScheduleFile>().size());
EXPECT_EQ(1u, model.getConcreteModelObjects<ExternalFile>().size());
ExternalFile externalfile = schedule.externalFile();
EXPECT_EQ(1u, externalfile.scheduleFiles().size());
EXPECT_EQ(openstudio::toString(relativeScheduleFilePath.filename()), externalfile.fileName());
EXPECT_TRUE(toPath(externalfile.fileName()).is_relative());
EXPECT_FALSE(externalfile.filePath().is_relative());
EXPECT_NE(toPath(externalfile.fileName()), externalfile.filePath());

ForwardTranslator ft;
Workspace workspace = ft.translateModel(model);

std::vector<WorkspaceObject> objects = workspace.getObjectsByType(IddObjectType::Schedule_File);
ASSERT_EQ(1u, objects.size());

boost::optional<std::string> fileName = objects[0].getString(2); // File Name
ASSERT_TRUE(fileName);
EXPECT_TRUE(toPath(fileName.get()).is_relative()); // rel path
EXPECT_NE(externalfile.filePath(), fileName.get());
}

// ScheduleFile(model, /abs/path)
{
Model model;
EXPECT_EQ(0u, model.getConcreteModelObjects<ExternalFile>().size());
EXPECT_EQ(0u, model.getConcreteModelObjects<ScheduleFile>().size());

ScheduleFile schedule(model, openstudio::toString(absoluteScheduleFilePath));
EXPECT_TRUE(schedule.setTranslateFileWithRelativePath(true));
EXPECT_TRUE(schedule.translateFileWithRelativePath());
EXPECT_EQ(1u, model.getConcreteModelObjects<ScheduleFile>().size());
EXPECT_EQ(1u, model.getConcreteModelObjects<ExternalFile>().size());
ExternalFile externalfile = schedule.externalFile();
EXPECT_EQ(1u, externalfile.scheduleFiles().size());
EXPECT_EQ(openstudio::toString(absoluteScheduleFilePath), externalfile.fileName());
EXPECT_FALSE(toPath(externalfile.fileName()).is_relative());
EXPECT_FALSE(externalfile.filePath().is_relative());
EXPECT_EQ(toPath(externalfile.fileName()), externalfile.filePath());

ForwardTranslator ft;
Workspace workspace = ft.translateModel(model);

std::vector<WorkspaceObject> objects = workspace.getObjectsByType(IddObjectType::Schedule_File);
ASSERT_EQ(1u, objects.size());

boost::optional<std::string> fileName = objects[0].getString(2); // File Name
ASSERT_TRUE(fileName);
EXPECT_FALSE(toPath(fileName.get()).is_relative()); // abs path
EXPECT_EQ(externalfile.filePath(), fileName.get());
}

// ScheduleFile(model, /rel/path)
{
Model model;
EXPECT_EQ(0u, model.getConcreteModelObjects<ExternalFile>().size());
EXPECT_EQ(0u, model.getConcreteModelObjects<ScheduleFile>().size());

ScheduleFile schedule(model, openstudio::toString(relativeScheduleFilePath));
EXPECT_TRUE(schedule.setTranslateFileWithRelativePath(true));
EXPECT_TRUE(schedule.translateFileWithRelativePath());
EXPECT_EQ(1u, model.getConcreteModelObjects<ScheduleFile>().size());
EXPECT_EQ(1u, model.getConcreteModelObjects<ExternalFile>().size());
ExternalFile externalfile = schedule.externalFile();
EXPECT_EQ(1u, externalfile.scheduleFiles().size());
EXPECT_EQ(openstudio::toString(relativeScheduleFilePath), externalfile.fileName());
EXPECT_TRUE(toPath(externalfile.fileName()).is_relative());
EXPECT_TRUE(externalfile.filePath().is_relative()) << externalfile.filePath();
EXPECT_EQ(toPath(externalfile.fileName()), externalfile.filePath());

ForwardTranslator ft;
Workspace workspace = ft.translateModel(model);

std::vector<WorkspaceObject> objects = workspace.getObjectsByType(IddObjectType::Schedule_File);
ASSERT_EQ(1u, objects.size());

boost::optional<std::string> fileName = objects[0].getString(2); // File Name
ASSERT_TRUE(fileName);
EXPECT_TRUE(toPath(fileName.get()).is_relative()); // rel path
EXPECT_EQ(externalfile.filePath(), fileName.get());
}
}
60 changes: 60 additions & 0 deletions src/model/ScheduleFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,16 @@ namespace model {
return csvFile;
}

bool ScheduleFile_Impl::translateFileWithRelativePath() const {
boost::optional<std::string> value = getString(OS_Schedule_FileFields::TranslateFileWithRelativePath, true);
OS_ASSERT(value);
return openstudio::istringEqual(value.get(), "Yes");
}

bool ScheduleFile_Impl::isTranslateFileWithRelativePathDefaulted() const {
return isEmpty(OS_Schedule_FileFields::TranslateFileWithRelativePath);
}

/* FIXME!
openstudio::TimeSeries ScheduleFile_Impl::timeSeries(unsigned columnIndex) const
{
Expand Down Expand Up @@ -376,6 +386,36 @@ namespace model {
}*/
}

bool ScheduleFile_Impl::setTranslateFileWithRelativePath(bool translateFileWithRelativePath) {
bool result = false;
if (translateFileWithRelativePath) {
result = setString(OS_Schedule_FileFields::TranslateFileWithRelativePath, "Yes");
} else {
result = setString(OS_Schedule_FileFields::TranslateFileWithRelativePath, "No");
}
OS_ASSERT(result);
return result;
}

void ScheduleFile_Impl::resetTranslateFileWithRelativePath() {
const bool result = setString(OS_Schedule_FileFields::TranslateFileWithRelativePath, "");
OS_ASSERT(result);
}

openstudio::path ScheduleFile_Impl::translatedFilePath() const {
if (translateFileWithRelativePath()) {
return toPath(externalFile().fileName());
}
openstudio::path filePath = externalFile().filePath();
if (!exists(filePath)) {
LOG(Warn, "Cannot find file \"" << filePath << "\"");
} else {
// make the path correct for this system
filePath = system_complete(filePath);
}
return filePath;
}

} // namespace detail

ScheduleFile::ScheduleFile(const ExternalFile& externalfile, int column, int rowsToSkip)
Expand Down Expand Up @@ -477,6 +517,14 @@ namespace model {
return getImpl<detail::ScheduleFile_Impl>()->csvFile();
}

bool ScheduleFile::translateFileWithRelativePath() const {
return getImpl<detail::ScheduleFile_Impl>()->translateFileWithRelativePath();
}

bool ScheduleFile::isTranslateFileWithRelativePathDefaulted() const {
return getImpl<detail::ScheduleFile_Impl>()->isTranslateFileWithRelativePathDefaulted();
}

/* FIXME!
openstudio::TimeSeries ScheduleFile::timeSeries(unsigned columnIndex) const {
return getImpl<detail::ScheduleFile_Impl>()->timeSeries(columnIndex);
Expand Down Expand Up @@ -551,6 +599,18 @@ unsigned ScheduleFile::addTimeSeries(const openstudio::TimeSeries& timeSeries) {
getImpl<detail::ScheduleFile_Impl>()->resetAdjustScheduleforDaylightSavings();
}

bool ScheduleFile::setTranslateFileWithRelativePath(bool translateFileWithRelativePath) {
return getImpl<detail::ScheduleFile_Impl>()->setTranslateFileWithRelativePath(translateFileWithRelativePath);
}

void ScheduleFile::resetTranslateFileWithRelativePath() {
getImpl<detail::ScheduleFile_Impl>()->resetTranslateFileWithRelativePath();
}

openstudio::path ScheduleFile::translatedFilePath() const {
return getImpl<detail::ScheduleFile_Impl>()->translatedFilePath();
}

/// @cond
ScheduleFile::ScheduleFile(std::shared_ptr<detail::ScheduleFile_Impl> impl) : ScheduleInterval(std::move(impl)) {}
/// @endcond
Expand Down
11 changes: 11 additions & 0 deletions src/model/ScheduleFile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ namespace model {

boost::optional<CSVFile> csvFile() const;

bool translateFileWithRelativePath() const;

bool isTranslateFileWithRelativePathDefaulted() const;

//@}
/** @name Setters */
//@{
Expand Down Expand Up @@ -120,10 +124,17 @@ namespace model {

/* FIXME! unsigned addTimeSeries(const openstudio::TimeSeries& timeSeries); */

bool setTranslateFileWithRelativePath(bool translateFileWithRelativePath);

void resetTranslateFileWithRelativePath();

//@}
/** @name Other */
//@{

// Depending on the value of 'Translate File With Relative Path', returns an absolute or a relative path
openstudio::path translatedFilePath() const;

//@}
protected:
/// @cond
Expand Down
10 changes: 10 additions & 0 deletions src/model/ScheduleFile_Impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ namespace model {

boost::optional<CSVFile> csvFile() const;

bool translateFileWithRelativePath() const;

bool isTranslateFileWithRelativePathDefaulted() const;

//@}
/** @name Setters */
//@{
Expand Down Expand Up @@ -121,10 +125,16 @@ namespace model {
// ensure that this object does not contain the date 2/29
virtual void ensureNoLeapDays() override;

bool setTranslateFileWithRelativePath(bool translateFileWithRelativePath);

void resetTranslateFileWithRelativePath();

//@}
/** @name Other */
//@{

openstudio::path translatedFilePath() const;

//@}
protected:
private:
Expand Down
13 changes: 13 additions & 0 deletions src/model/test/ScheduleInterval_GTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,19 @@ TEST_F(ModelFixture, ScheduleFile) {
schedule3.resetAdjustScheduleforDaylightSavings();
EXPECT_TRUE(schedule3.isAdjustScheduleforDaylightSavingsDefaulted());

EXPECT_FALSE(schedule3.translateFileWithRelativePath());
EXPECT_TRUE(schedule3.isTranslateFileWithRelativePathDefaulted());
EXPECT_EQ(externalfile->filePath(), schedule3.translatedFilePath());

EXPECT_TRUE(schedule3.setTranslateFileWithRelativePath(true));
EXPECT_TRUE(schedule3.translateFileWithRelativePath());
EXPECT_FALSE(schedule3.isTranslateFileWithRelativePathDefaulted());
EXPECT_EQ(toPath(externalfile->fileName()), schedule3.translatedFilePath());

schedule3.resetTranslateFileWithRelativePath();
EXPECT_FALSE(schedule3.translateFileWithRelativePath());
EXPECT_TRUE(schedule3.isTranslateFileWithRelativePathDefaulted());

// shouldn't create a new object
boost::optional<ExternalFile> externalfile2 = ExternalFile::getExternalFile(model, openstudio::toString(p));
ASSERT_TRUE(externalfile2);
Expand Down

0 comments on commit d8026ec

Please sign in to comment.