Write documentation for sequence API module

This commit is contained in:
Dion Moult
2023-01-03 17:31:48 +11:00
parent 6594445fa3
commit 2805109cef
40 changed files with 1580 additions and 190 deletions
@@ -69,8 +69,10 @@ class Usecase:
project = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcProject")
element = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcSite")
subelement = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBuilding")
# The project contains a site (note that project aggregation is a special case in IFC)
ifcopenshell.api.run("aggregate.assign_object", model, product=element, relating_object=project)
# The site has a building
ifcopenshell.api.run("aggregate.assign_object", model, product=subelement, relating_object=element)
"""
@@ -54,12 +54,12 @@ class Usecase:
parent_resource=crew, ifc_class="IfcLaborResource")
# Labour resource is quantified in terms of time.
ifcopenshell.api.run("resource.add_resource_quantity", model,
quantity = ifcopenshell.api.run("resource.add_resource_quantity", model,
resource=labour, ifc_class="IfcQuantityTime")
# Store the time used in hours
ifcopenshell.api.run("resource.edit_resource_quantity", model,
physical_quantity=time, attributes={"TimeValue": 8.0})
physical_quantity=quantity, attributes={"TimeValue": 8.0})
"""
self.file = file
self.settings = {"resource": resource, "ifc_class": ifc_class}
@@ -43,17 +43,17 @@ class Usecase:
parent_resource=crew, ifc_class="IfcLaborResource")
# Labour resource is quantified in terms of time.
ifcopenshell.api.run("resource.add_resource_quantity", model,
quantity = ifcopenshell.api.run("resource.add_resource_quantity", model,
resource=labour, ifc_class="IfcQuantityTime")
# Store the unit time used in hours
ifcopenshell.api.run("resource.edit_resource_quantity", model,
physical_quantity=time, attributes={"TimeValue": 8.0})
physical_quantity=quantity, attributes={"TimeValue": 8.0})
# Let's imagine we've used the resource for 2 days.
time = ifcopenshell.api.run("resource.add_resource_time", model, resource=labour)
ifcopenshell.api.run("resource.edit_resource_time", model,
resource_time=time, attributes={"ScheduleWork": "P16H"})
resource_time=time, attributes={"ScheduleWork": "PT16H"})
"""
self.file = file
self.settings = {
@@ -21,32 +21,149 @@ import ifcopenshell
class Usecase:
def __init__(self, file, **settings):
def __init__(
self,
file,
work_schedule=None,
parent_task=None,
name=None,
description=None,
identification=None,
predefined_type="NOTDEFINED",
):
"""Adds a new task
Tasks are typically used for two purposes: construction scheduling and
facility management.
In construction scheduling, a task represents a job to be done in a work
schedule. Tasks are organised in a hierarchical manner known as a work
breakdown structure (WBS) and have lots of sequential relationships
(e.g. this task must finish before the next task can start) and date
information (e.g. durations, start dates). This is often represented as
a gantt chart and used to analyse critical paths to try and reduce
project time to stay on-time and within budget.
In facility management, a task represents a maintenance task to maintain
a piece of equipment. Tasks are broken down into a punch list, or simply
a bulleted or ordered sequence of tasks to be performed (e.g. turn off
equipment, check power connection, etc) in order to maintain the
equipment. Tasks will also typically have recurring scheduled dates in
line with the maintenance schedule. These maintenance tasks and
procedures are typically published as part of an operations and
maintenance manual.
All tasks must be grouped in a work schedule, either directly as a root
or top-level task, or indirectly as a child or subtask of a parent task.
In construction scheduling, tasks may be nested many times to create the
work breakdown structure, and the "leaf" tasks (i.e. tasks with no more
subtasks) are considered to be the activities with dates, whereas all
parent tasks are part of the breakdown structure used for categorisation
purposes. In facility management, top-level tasks represent the overall
maintenance job to be performed, and child tasks represent an ordered
list of things to do for that maintenance. These form a 2-level
hierarchy. No further child tasks are recommended.
:param work_schedule: The work schedule to group the task in, if the
task is to be a top-level or root task. This is mutually exclusive
with the parent_task parameter.
:type work_schedule: ifcopenshell.entity_instance.entity_instance
:param parent_task: The parent task, if the task is to be a subtask or
child task. This is mutually exclusive with the work_schedule
parameter.
:type parent_task: ifcopenshell.entity_instance.entity_instance
:param name: The name of the task.
:type name: str,optional
:param description: The description of the task.
:type description: str,optional
:param identification: The identification code of the task.
:type identification: str,optional
:param predefined_type: The predefined type of the task. Common ones
include CONSTRUCTION, DEMOLITION, or MAINTENANCE. Consultant the
IFC documentation for IfcTaskTypeEnum for more information.
:type predefined_type: str
:return: The newly created IfcTask
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Add a root task to represent the design milestones, and major
# project phases.
ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Milestones", identification="A")
ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Design", identification="B")
construction = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
# Let's start creating our work breakdown structure.
ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Early Works", identification="C1")
ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Substructure", identification="C2")
superstructure = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Superstructure", identification="C3")
# Notice how the leaf task is the actual activity
ifcopenshell.api.run("sequence.add_task", model,
parent_task=superstructure, name="Ground Floor FRP", identification="C3.1")
# Let's imagine we are digitising an operations and maintenance
# manual for the mechanical discipline.
maintenance = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Mechanical Maintenance")
# Imagine we have to clean the condenser coils for a chiller every
# month. Like the schedule above, to keep things simple we won't
# show scheduling times and calendars. This root task represents the
# overall maintenance task.
cleaning = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=maintenance, name="Condenser coil cleaning")
# These subtasks represent the punch list of maintenance tasks.
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="1",
description="Prior to work, wear safety shoes, gloves, and goggles.")
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="2",
description="Prepare jet pump, screwdriver, hose clamp, and control panel door key.")
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="3",
description="Switch OFF the chiller unit.")
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="3",
description="Open the isolator switch.")
ifcopenshell.api.run("sequence.add_task", model, parent_task=cleaning, identification="3",
description="Setup the water pressure by tapping to a water supply and connecting to a ...")
"""
self.file = file
self.settings = {
"work_schedule": None,
"parent_task": None,
"work_schedule": work_schedule,
"parent_task": parent_task,
"name": name,
"description": description,
"identification": identification,
"predefined_type": predefined_type,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
task = ifcopenshell.api.run(
"root.create_entity",
self.file,
ifc_class="IfcTask",
name=None,
predefined_type="NOTDEFINED",
name=self.settings["name"],
predefined_type=self.settings["predefined_type"],
)
if self.settings["description"]:
task.Description = self.settings["description"]
if self.settings["identification"]:
task.Identification = self.settings["identification"]
task.IsMilestone = False
if self.settings["work_schedule"]:
self.file.create_entity(
"IfcRelAssignsToControl",
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.run(
"owner.create_owner_history", self.file
),
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
"RelatedObjects": [task],
"RelatingControl": self.settings["work_schedule"],
}
@@ -59,9 +176,5 @@ class Usecase:
relating_object=self.settings["parent_task"],
)
if self.settings["parent_task"].Identification:
task.Identification = (
self.settings["parent_task"].Identification
+ "."
+ str(len(rel.RelatedObjects))
)
task.Identification = self.settings["parent_task"].Identification + "." + str(len(rel.RelatedObjects))
return task
@@ -16,19 +16,54 @@
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import ifcopenshell.util.date
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, task=None, is_recurring=False):
"""Adds a task time to a task
Some tasks, such as activities within a work breakdown structure or
overall maintenance tasks will have time related information. This
includes start dates, durations, end dates, and possible recurring times
(especially for maintenance tasks).
:param task: The task to add time data to.
:type task: ifcopenshell.entity_instance.entity_instance
:param is_recurring: Whether or not the time should recur.
:type is_recurring: bool
:return: The newly created IfcTaskTime.
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's imagine we are creating a construction schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Create a portion of a work breakdown structure.
construction = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
superstructure = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Superstructure", identification="C3")
task = ifcopenshell.api.run("sequence.add_task", model,
parent_task=superstructure, name="Ground Floor FRP", identification="C3.1")
# Add time data. Note that time data is blank by default.
time = ifcopenshell.api.run("sequence.add_task_time", model, task=task)
# Let's say our task starts on the first of January when everybody
# is still drunk from the new years celebration, and lasts for 2
# days. Note we don't need to specify the end date, as that is
# derived from the start plus the duration. In this simple example,
# no calendar has been specified, so we are working 24/7. Yikes!
ifcopenshell.api.run("sequence.edit_task_time", model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
"""
self.file = file
self.settings = {
"task": None,
}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"task": task, "is_recurring": is_recurring}
def execute(self):
task_time = self.file.create_entity("IfcTaskTime")
if self.settings["is_recurring"]:
task_time = self.file.create_entity("IfcTaskTime")
else:
task_time = self.file.create_entity("IfcTaskTimeRecurring")
self.settings["task"].TaskTime = task_time
return task_time
@@ -23,15 +23,62 @@ from datetime import timedelta
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, recurrence_pattern=None, start_time=None, end_time=None):
"""Adds a time period to a recurrence pattern
A recurring time may be an all-day event, or only during certain time
periods of the day. For example, you might say that every 1st of January
recurring is a public holiday, which is an all-day event. Alternatively,
you might say that you work every (i.e. recurringly) Monday to Friday,
from 9am to 5pm. The 9am to 5pm is the time period.
There may also be multiple recurrence patterns, such as from 9am to
12pm, and then another from 1pm to 5pm (to indicate an hour break for
lunch).
:param recurrence_pattern: The IfcRecurrencePattern to add the time
period to. See ifcopenshell.api.sequence.assign_recurrence_pattern.
:type recurrence_pattern: ifcopenshell.entity_instance.entity_instance
:param start_time: The start time of the time period, in a format
compatible with IfcTime, such as an ISO format time string or a
datetime.time object.
:type start_time: str,datetime.time
:param end_time: The end time of the time period, in a format
compatible with IfcTime, such as an ISO format time string or a
datetime.time object.
:type end_time: str,datetime.time
:return: The newly created IfcTimePeriod
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
# Let's start defining the times that we work during the week.
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="WorkingTimes")
# We create a weekly recurrence
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
parent=work_time, recurrence_type="WEEKLY")
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
# The morning work session, lunch, then the afternoon work session.
ifcopenshell.api.run("sequence.add_time_period", model,
recurrence_pattern=pattern, start_time="09:00", end_time="12:00")
ifcopenshell.api.run("sequence.add_time_period", model,
recurrence_pattern=pattern, start_time="13:00", end_time="17:00")
"""
self.file = file
self.settings = {
"recurrence_pattern": None,
"start_time": None,
"end_time": None,
"recurrence_pattern": recurrence_pattern,
"start_time": start_time,
"end_time": end_time,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
time_period = self.file.create_entity("IfcTimePeriod")
@@ -20,11 +20,63 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, name="Unnamed", predefined_type="NOTDEFINED"):
"""Add a work calendar
A work calendar defines when work is allowed to occur and when the
holidays are. This is a fundamental concept in construction planning.
Every task in a work schedule will have an associated calendar. Some
task and resources work 24/7, whereas others work Monday to Friday, or
5.5 day weeks, etc. This is important, as tasks durations may only occur
during working times in a work calendar.
Work calendars can also be used to associate with events, such as
indicating that during certain days and times of the year, motion
sensors should turn on the lights, and other smart building controls.
:param name: The name of the calendar. Typically something like
"5 Day Working Week" or "24/7".
:type name: str, optional
:param predefined_type: The type of calendar, typically used to more
specifically define shifts, such as FIRSTSHIFT, SECONDSHIFT, or
THIRDSHIFT. Leave as NOTDEFINED for basic calendar usage.
:return: The newly created IfcWorkCalendar
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Add a root task to represent the construction tasks.
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model, name="5 Day Week")
# Let's start defining the times that we work during the week.
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="WorkingTimes")
# We create a weekly recurrence
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
parent=work_time, recurrence_type="WEEKLY")
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday), 9am to 5pm
ifcopenshell.api.run("sequence.edit_recurrence_pattern", mdoel,
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
ifcopenshell.api.run("sequence.add_time_period", model,
recurrence_pattern=pattern, start_time="09:00", end_time="17:00")
# We associate the calendar with the construction root task. All
# subtasks underneath the construction work task will also inherit
# this calendar by default (though you can override them).
ifcopenshell.api.run("control.assign_control", model, relating_control=calendar, related_object=task)
"""
self.file = file
self.settings = {"name": "Unnamed", "predefined_type": "NOTDEFINED"}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"name": name, "predefined_type": predefined_type}
def execute(self):
work_calendar = ifcopenshell.api.run(
@@ -22,15 +22,43 @@ from datetime import datetime
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, name=None, predefined_type="NOTDEFINED", start_time=None):
"""Add a new work plan
A work plan is a group of work schedules. Since work schedules may have
different purposes, such as for maintenance or construction scheduling,
baseline comparison, or phasing, work plans can be used to group related
work schedules. At a minimum, it is recommended to use work plans to
indicate whether the work schedules are for facility management or for
construction scheduling.
:param name: The name of the work plan. Recommended to be "Maintenance"
or "Construction" for the two main purposes.
:type name: str, optional
:param predefined_type: The type of work plan, used for baselining.
Leave as "NOTDEFINED" if unsure.
:type predefined_type: str
:param start_time: The earliest start time when the schedules grouped
within the work plan are relevant.
:type start_time: str,datetime.time
:return: The newly created IfcWorkPlan
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# This will hold all our construction schedules
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
# This is one of our schedules in our work plan.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
name="Construction Schedule A", work_plan=work_plan)
"""
self.file = file
self.settings = {
"name": None,
"predefined_type": "NOTDEFINED",
"start_time": datetime.now(),
"name": name,
"predefined_type": predefined_type,
"start_time": start_time or datetime.now(),
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
work_plan = ifcopenshell.api.run(
@@ -22,16 +22,55 @@ from datetime import datetime
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, name="Unnamed", predefined_type="NOTDEFINED", start_time=None, work_plan=None):
"""Add a new work schedule
A work schedule is a group of tasks, where the tasks are typically
either for maintenance or for construction scheduling.
:param name: The name of the work schedule.
:type name: str
:param predefined_type: The type of schedule, chosen from ACTUAL,
BASELINE, and PLANNED. Typically you would start with PLANNED, then
convert to a BASELINE when changes are made with separate schedules,
then have a parallel ACTUAL schedule.
:type predefined_type: str
:param start_time: The earlier start time when the schedule is relevant.
May be represented with an ISO standard string.
:type start_time: str,datetime.time,optional
:param work_plan: The IfcWorkPlan the schedule will be part of. If not
provided, the schedule will not be grouped in a work plan and would
exist as a top level schedule in the project. This is not
recommended.
:type work_plan: ifcopenshell.entity_instance.entity_instance,optional
:return: The newly created IfcWorkSchedule
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# This will hold all our construction schedules
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
# Let's imagine this is one of our schedules in our work plan.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
name="Construction Schedule A", work_plan=work_plan)
# Add a root task to represent the design milestones, and major
# project phases.
ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Milestones", identification="A")
ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Design", identification="B")
construction = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
"""
self.file = file
self.settings = {
"name": "Unnamed",
"predefined_type": "NOTDEFINED",
"start_time": datetime.now(),
"work_plan": None,
"name": name,
"predefined_type": predefined_type,
"start_time": start_time or datetime.now(),
"work_plan": work_plan,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
work_schedule = ifcopenshell.api.run(
@@ -18,11 +18,57 @@
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_calendar=None, time_type="WorkingTimes"):
"""Add either working times or holiday times to a calendar
A calendar defines when work occurs by defining working times and
holiday times. First, the working times are defined, then the holidays
may override the working times. For this reason, holidays are also known
as exception times. For example, you might define the working times as
every Monday to Friday, then define a few holidays in the year, such as
the 1st of January. If the 1st of January is on a weekday, it will
override the work time.
:param work_calendar: The IfcWorkCalendar to add the work or holiday
time definition to.
:type work_calendar: ifcopenshell.entity_instance.entity_instance
:param time_type: Either WorkingTimes or ExceptionTimes, depending on
what you want to define.
:type time_type: str
:return: The newly created IfcWorkTime
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
# Let's start defining the times that we work during the week.
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="WorkingTimes")
# We create a weekly recurrence
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
parent=work_time, recurrence_type="WEEKLY")
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
# Let's set some holidays
holidays = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="ExceptionTimes")
# We create a yearly recurrence
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
parent=work_time, recurrence_type="YEARLY_BY_DAY_OF_MONTH")
# The holiday is every 1st of January
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
recurrence_pattern=pattern, attributes={"DayComponent": [1], "MonthComponent": [1]})
"""
self.file = file
self.settings = {"work_calendar": None, "time_type": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_calendar": work_calendar, "time_type": time_type}
def execute(self):
work_time = self.file.create_entity("IfcWorkTime")
@@ -20,15 +20,73 @@ import ifcopenshell.util.date
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, rel_sequence=None, lag_value=None, duration_type="WORKTIME"):
"""Assign a lag time to a sequence relationship between tasks
A task sequence (e.g. finish to start) may optionally have a lag time
defined. This is a fundamental concept in construction scheduling. The
lag is defined as a duration, and the duration is typically either
calendar based (i.e. follows the working times and holidays of the
calendar) or elapsed time based (i.e. 24/7).
A sequence may only have a single lag time defined. Negative lag times
are allowed.
:param rel_sequence: The IfcRelSequence to assign the lag time to.
:type rel_sequence: ifcopenshell.entity_instance.entity_instance
:param lag_value: An ISO standardised duration string.
:type lag_value: str
:param duration_type: Choose from WORKTIME for the associated
calendar-based lag times (this is the most common scenario and is
recommended as a default), or ELAPSEDTIME to not follow the
calendar. You may also choose NOTDEFINED but the behaviour of this
is unclear.
:type duration_type: str
:return: The newly created IfcLagTime
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's imagine a root construction task
construction = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
# Let's imagine we're doing a typically formwork, reinforcement,
# pour sequence. Let's start with the formwork. It'll take us 2
# days.
formwork = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Formwork", identification="C.1")
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
ifcopenshell.api.run("sequence.edit_task_time", model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
# Now let's do the reinforcement. It'll take us another 2 days.
reinforcement = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Reinforcement", identification="C.2")
time = ifcopenshell.api.run("sequence.add_task_time", model, task=reinforcement)
ifcopenshell.api.run("sequence.edit_task_time", model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
# Now let's say the formwork must finish before the reinforcement
# can start. This is a typical finish to start relationship (FS).
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
relating_process=formwork, related_process=reinforcement)
# Now typically there would be no lag time between formwork and
# reinforcement, but let's pretend that we had to allow 1 day gap
# for whatever reason.
ifcopenshell.api.run("sequence.assign_lag_time", model, rel_sequence=sequence, lag_value="P1D")
"""
self.file = file
self.settings = {
"rel_sequence": None,
"lag_value": None,
"duration_type": "NOTDEFINED",
"rel_sequence": rel_sequence,
"lag_value": lag_value,
"duration_type": duration_type,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
lag_value = self.file.createIfcDuration(
@@ -21,21 +21,82 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, relating_process=None, related_object=None):
"""Assigns an object to be related to a process, typically a construction task
Processes work using the ICOM (Input, Controls, Outputs, Mechanisms)
paradigm in IFC. This process model is commonly used in modeling
manufacturing functions.
For example, processes (such as tasks) consume Inputs and transform them
into Outputs. The process may only occur within the limits of Controls
(e.g. cost items) and may require Mechanisms (ISO9000 calls them
Mechanisms, whereas IFC calls them resources, such as raw materials,
labour, or equipment).
+----------+
| Controls |
+----------+
|
V
+--------+ +---------+ +---------+
| Inputs | --> | Process | --> | Outputs |
+--------+ +---------+ +---------+
^
|
+-----------+
| Resources |
+-----------+
There are three main scenarios where an object may be related to a
task: defining inputs, controls, and resources of a process.
For inputs, a product (i.e. wall) may be defined as an input to a task,
such as when the task is to demolish the wall (i.e. the wall is an
input, and there is no output).
For controls, a cost item may be defined as a control to a task.
For resources, any construction resource may be assigned to a task.
:param relating_process: The IfcProcess (typically IfcTask) that the
input, control, or resource is related to.
:type relating_process: ifcopenshell.entity_instance.entity_instance
:param related_object: The IfcProduct (for input), IfcCostItem (for
control) or IfcConstructionResource (for resource).
:type related_object: ifcopenshell.entity_instance.entity_instance
:return: The newly created IfcRelAssignsToProcess relationship
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's create a construction task. Note that the predefined type is
# important to distinguish types of tasks.
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Demolish existing", identification="A", predefined_type="DEMOLITION")
# Let's say we have a wall somewhere.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# Let's demolish that wall!
ifcopenshell.api.run("sequence.assign_process", model, relating_process=task, related_object=wall)
"""
self.file = file
self.settings = {
"relating_process": None,
"related_object": None,
"relating_process": relating_process,
"related_object": related_object,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
if self.settings["related_object"].HasAssignments:
for assignment in self.settings["related_object"].HasAssignments:
if (
assignment.is_a("IfclRelAssignsToProcess")
assignment.is_a("IfcRelAssignsToProcess")
and assignment.RelatingProcess == self.settings["relating_process"]
):
return
@@ -21,14 +21,51 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, relating_product=None, related_object=None):
"""Assigns a product to be produced as a result of a process
A construction task may result in products (e.g. a wall) being
constructed. These task "Outputs" are defined in IFC through product
relationships.
Not all tasks have Outputs. For example, maintenance tasks will
typically not have any outputs.
See ifcopenshell.api.sequence.assign_process for Inputs and other types
of process relationships that can be described in manufacturing
process modeling.
:param relating_product: The IfcProduct that was constructed as a result
of the task.
:type relating_product: ifcopenshell.entity_instance.entity_instance
:param related_object: The IfcProcess (typically IfcTask) of the
construction task.
:type related_object: ifcopenshell.entity_instance.entity_instance
:return: The newly created IfcRelAssignsToProduct relationship
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's create a construction task. Note that the predefined type is
# important to distinguish types of tasks.
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Build wall", identification="A", predefined_type="CONSTRUCTION")
# Let's say we have a wall somewhere.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# Let's construct that wall!
ifcopenshell.api.run("sequence.assign_product", relating_product=wall, related_object=task)
"""
self.file = file
self.settings = {
"relating_product": None,
"related_object": None,
"relating_product": relating_product,
"related_object": related_object,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
if self.settings["related_object"].HasAssignments:
@@ -18,11 +18,91 @@
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, parent=None, recurrence_type="WEEKLY"):
"""Define a time to recur at a particular interval
There are two scenarios where you might want to define a recurring time
pattern.
You might want a task to be scheduled at a recurring interval,
this is common for maintenance tasks which need to be performed monthly,
every 6 months, every year, etc.
Alternatively, you might be defining a work calendar, which defines
working days or holidays. The working days might be every week from
monday to friday ("every" week means it recurs every week), or the
holidays might be the same every year.
The types of recurrence are:
- DAILY: every Nth (interval) day for up to X (Occurrences) occurrences.
e.g. Every day, every 2 days, every day up to 5 times, etc
- WEEKLY: every Nth (interval) MTWTFSS (WeekdayComponent) for up to X
(Occurrences) occurrences. e.g. Every Monday, every weekday, every
other saturday, etc
- MONTHLY_BY_DAY_OF_MONTH: every Nth (DayComponent) of every Xth
(Interval) Month up to Y (Occurrences) occurrences. e.g. Every 15th of
the Month.
- MONTHLY_BY_POSITION: Every Nth (Position) MTWTFSS (WeekdayComponent)
of every Xth (Interval) Month up to Y (Occurrences) occurrences. e.g.
Every second Tuesday of the Month.
- YEARLY_BY_DAY_OF_MONTH: every Nth (DayComponent) of every JFMAMJJASOND
(MonthComponent) month of every Yth (Interval) Year up to Z
(Occurrences) occurrences. e.g. every 25th of December.
- YEARLY_BY_POSITION: every Nth (Position) MTWTFSS (WeekdayComponent) of
every JFMAMJJASOND (MonthComponent) month of every Yth (Interval)
Year up to Z (Occurrences) occurrences. e.g. every third Wednesday
of January.
These recurrence patterns are fairly standard in all calendar and
scheduling applications.
:param parent: Either an IfcTaskTimeRecurring if you are defining a
recurring schedule for a task, or IfcWorkTime if you are defining a
recurring pattern for a workdays or holidays in a calendar.
:type parent: ifcopenshell.entity_instance.entity_instance
:param recurrence_type: One of the types of recurrences.
:type recurrence_type: str
:return: The newly created IfcRecurrencePattern
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
# Let's start defining the times that we work during the week.
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="WorkingTimes")
# We create a weekly recurrence
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
parent=work_time, recurrence_type="WEEKLY")
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
# Let's imagine we are creating a maintenance schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Equipment Maintenance")
# Now let's imagine we have a task to maintain the chillers
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Chiller maintenance")
# Because it is a maintenance task, we must schedule a recurring time
time = ifcopenshell.api.run("sequence.add_task_time", model, task=task, is_recurring=True)
# We create a monthly recurrence
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
parent=work_time, recurrence_type="MONTHLY_BY_DAY_OF_MONTH")
# Specifically, the maintenance task must occur every 6 months
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
recurrence_pattern=pattern, attributes={"DayComponent": [1], "Interval": 6})
"""
self.file = file
self.settings = {"parent": None, "recurrence_type": "WEEKLY"}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"parent": parent, "recurrence_type": recurrence_type}
def execute(self):
recurrence = self.file.createIfcRecurrencePattern(
@@ -21,14 +21,92 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, relating_process=None, related_process=None, sequence_type="FINISH_START"):
"""Assign a sequential relationship between tasks
Tasks in construction sequencing typically have sequence relationships
between them, indicating that one task must happen after another. This
is used to automatically compute new start and end dates and cascade
changes when dates are changed. This is also used to calculate critical
paths and floats.
There are four types of sequence relationships, known as finish to
start, finish to finish, start to start, and start to finish, sometimes
abbreviated as a (FS, FF, SS, and SF). The most common is the finish to
start relationship, indicating that the previous task must finish before
the next task can start.
You must not create cyclical task sequences. This makes the computer
unhappy.
Note that "previous" or "next" does not necessarily mean the task
chronologically happens before or after. They simply indicate the order
of the sequence relationship. For this reason, they are often called
predecessor and successor tasks in the planning profession.
:param relating_process: The previous / predecessor task.
:type relating_process: ifcopenshell.entity_instance.entity_instance
:param related_process: The next / successor task.
:type related_process: ifcopenshell.entity_instance.entity_instance
:param sequence_type: Choose from FINISH_START, FINISH_FINISH,
START_START, or START_FINISH.
:return: The newly created IfcRelSequence
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's imagine a root construction task
construction = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
# Let's imagine we're doing a typically formwork, reinforcement,
# pour sequence. Let's start with the formwork. It'll take us 2
# days.
formwork = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Formwork", identification="C.1")
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
ifcopenshell.api.run("sequence.edit_task_time", model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
# Now let's do the reinforcement. It'll take us another 2 days.
reinforcement = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Reinforcement", identification="C.2")
time = ifcopenshell.api.run("sequence.add_task_time", model, task=reinforcement)
ifcopenshell.api.run("sequence.edit_task_time", model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
# Now the pour itself. It'll only take 1 day.
pour = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Reinforcement", identification="C.3")
time = ifcopenshell.api.run("sequence.add_task_time", model, task=pour)
ifcopenshell.api.run("sequence.edit_task_time", model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P1D"})
# Now let's say the formwork must finish before the reinforcement
# can start, and the reinforcement must finish before the pour can
# start. This is a typical finish to start relationship (FS).
ifcopenshell.api.run("sequence.assign_sequence", model,
relating_process=formwork, related_process=reinforcement)
ifcopenshell.api.run("sequence.assign_sequence", model,
relating_process=reinforcement, related_process=pour)
# Notice how we set all the scheduled start dates arbitrarily at
# 2000-01-01. This is because we can ask IfcOpenShell to
# automatically cascade the dates, starting from any task. This will
# update the reinforcement date to be 2000-01-03 and the pour date
# to be 2000-01-05.
ifcopenshell.api.run("sequence.cascade_schedule", model, task=formwork)
"""
self.file = file
self.settings = {
"relating_process": None,
"related_process": None,
"relating_process": relating_process,
"related_process": related_process,
"sequence_type": sequence_type,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for rel in self.settings["related_process"].IsSuccessorFrom or []:
@@ -38,11 +116,9 @@ class Usecase:
"IfcRelSequence",
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.run(
"owner.create_owner_history", self.file
),
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
"RelatingProcess": self.settings["relating_process"],
"RelatedProcess": self.settings["related_process"],
"SequenceType": "FINISH_START",
"SequenceType": self.settings["sequence_type"],
}
)
@@ -21,11 +21,33 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_schedule=None, work_plan=None):
"""Assigns a work schedule to a work plan
Typically, work schedules would be assigned to a work plan at creation.
However you may also delay this and do it manually afterwards.
:param work_schedule: The IfcWorkSchedule that will be assigned to the
work plan.
:type work_schedule: ifcopenshell.entity_instance.entity_instance
:param work_plan: The IfcWorkPlan for the schedule to be assigned to.
:type work_plan: ifcopenshell.entity_instance.entity_instance
:return: The IfcRelAggregates relationship
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# This will hold all our construction schedules
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
# Alternatively, if you create a schedule without a work plan ...
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# ... you can assign the work plan afterwards.
ifcopenshell.api.run("sequence.assign_workplan", work_schedule=schedule, work_plan=work_plan)
"""
self.file = file
self.settings = {"work_schedule": None, "work_plan": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_schedule": work_schedule, "work_plan": work_plan}
def execute(self):
# TODO: this is an ambiguity by buildingSMART
@@ -23,11 +23,64 @@ import ifcopenshell.util.element
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, task=None):
"""Calculates the task duration based on resource usage
If a task has labour or equipment resources assigned to it, its duration
may be parametrically derived from the scheduled work of the resource.
For example, a labour resource with scheduled work of 10 working days
and a resource utilisation of 200% (i.e. two labour teams) will imply
that the task duration is 5 working days.
If this data is not available, such as if the task has no resources,
then nothing happens.
:param task: The IfcTask to calculate the duration for.
:type task: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Add our own crew
crew = ifcopenshell.api.run("resource.add_resource", model, ifc_class="IfcCrewResource")
# Add some labour to our crew.
labour = ifcopenshell.api.run("resource.add_resource", model,
parent_resource=crew, ifc_class="IfcLaborResource")
# Labour resource is quantified in terms of time.
quantity = ifcopenshell.api.run("resource.add_resource_quantity", model,
resource=labour, ifc_class="IfcQuantityTime")
# Store the unit time used in hours
ifcopenshell.api.run("resource.edit_resource_quantity", model,
physical_quantity=quantity, attributes={"TimeValue": 8.0})
# Let's imagine we've used the resource for 10 days with a
# utilisation of 200%.
time = ifcopenshell.api.run("resource.add_resource_time", model, resource=labour)
ifcopenshell.api.run("resource.edit_resource_time", model,
resource_time=time, attributes={"ScheduleWork": "PT80H", "ScheduleUsage": 2})
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's create a construction task. Note that the predefined type is
# important to distinguish types of tasks.
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Foundations", identification="A")
# Assign our resource to the task.
ifcopenshell.api.run("sequence.assign_process", model, relating_process=task, related_object=labour)
# Now we can calculate the task duration based on the resource. This
# will set task.TaskTime.ScheduleDuration to be P5D.
ifcopenshell.api.run("sequence.calculate_task_duration", model, task=task)
"""
self.file = file
self.settings = {"task": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"task": task}
def execute(self):
self.seconds_per_workday = self.calculate_seconds_per_workday()
@@ -22,11 +22,86 @@ import ifcopenshell.util.sequence
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, task=None):
"""Cascades start and end dates of tasks based on durations
Given a start task with a start date and duration, the end date, and the
start and end of all successor tasks with durations may be automatically
computed.
Using this automatic computation is recommended is an alternative to
manually specifying dates. It is useful for doing edits and cascading
changes.
Dates can only cascade from predecessor to successors, not backwards.
Cyclical relationships are invalid and will result in a recursion error
being raised.
Note that there may be differences between how different planning
software calculate start and end dates. Some may consider Monday 5pm to
be equivalent to be Tuesday 8am, for instance.
:param task: The start task to begin cascading from.
:type task: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Define a convenience function to add a task chained to a predecessor
def add_task(model, name, predecessor, work_schedule):
# Add a construction task
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=work_schedule, name=name, predefined_type="CONSTRUCTION")
# Give it a time
task_time = ifcopenshell.api.run("sequence.add_task_time", model, task=task)
# Arbitrarily set the task's scheduled time duration to be 1 week
ifcopenshell.api.run("sequence.edit_task_time", model, task_time=task_time,
attributes={"ScheduleStart": datetime.date(2000, 1, 1), "ScheduleDuration": "P1W"})
# If a predecessor exists, create a finish to start relationship
if predecessor:
ifcopenshell.api.run("sequence.assign_sequence", model,
relating_process=predecessor, related_process=task)
return task
# Open an existing IFC4 model you have of a building
model = ifcopenshell.open("/path/to/existing/model.ifc")
# Create a new construction schedule
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction")
# Let's imagine a starting task for site establishment.
task = add_task(model, "Site establishment", None, schedule)
start_task = task
# Get all our storeys sorted by elevation ascending.
storeys = sorted(model.by_type("IfcBuildingStorey"), key=lambda s: get_storey_elevation(s))
# For each storey ...
for storey in storeys:
# Add a construction task to construct that storey, using our convenience function
task = add_task(model, f"Construct {storey.Name}", task, schedule)
# Assign all the products in that storey to the task as construction outputs.
for product in get_decomposition(storey):
ifcopenshell.api.run("sequence.assign_product", model, relating_product=product, related_object=task)
# Ask the computer to calculate all the dates for us from the start task.
# For example, if the first task started on the 1st of January and took a
# week, the next task will start on the 8th of January. This saves us
# manually doing date calculations.
ifcopenshell.api.run("sequence.cascade_schedule", model, task=start_task)
# Calculate the critical path and floats.
ifcopenshell.api.run("sequence.recalculate_schedule", model, work_schedule=schedule)
"""
self.file = file
self.settings = {"task": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"task": task}
def execute(self):
self.calendar_cache = {}
@@ -21,11 +21,60 @@ import ifcopenshell.util.date
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, lag_time=None, attributes=None):
"""Edits the attributes of an IfcLagTime
For more information about the attributes and data types of an
IfcLagTime, consult the IFC documentation.
:param lag_time: The IfcLagTime entity you want to edit
:type lag_time: ifcopenshell.entity_instance.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's imagine a root construction task
construction = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
# Let's imagine we're doing a typically formwork, reinforcement,
# pour sequence. Let's start with the formwork. It'll take us 2
# days.
formwork = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Formwork", identification="C.1")
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
ifcopenshell.api.run("sequence.edit_task_time", model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
# Now let's do the reinforcement. It'll take us another 2 days.
reinforcement = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Reinforcement", identification="C.2")
time = ifcopenshell.api.run("sequence.add_task_time", model, task=reinforcement)
ifcopenshell.api.run("sequence.edit_task_time", model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
# Now let's say the formwork must finish before the reinforcement
# can start. This is a typical finish to start relationship (FS).
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
relating_process=formwork, related_process=reinforcement)
# Now typically there would be no lag time between formwork and
# reinforcement, but let's pretend that we had to allow 1 day gap
# for whatever reason.
lag = ifcopenshell.api.run("sequence.assign_lag_time", model, rel_sequence=sequence, lag_value="P1D")
# Or, let's make it 2 days instead.
ifcopenshell.api.run("sequence.edit_lag_time", model, lag_time=lag, attributes={"LagValue": "P2D"})
"""
self.file = file
self.settings = {"lag_time": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"lag_time": lag_time, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
@@ -18,11 +18,38 @@
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, recurrence_pattern=None, attributes=None):
"""Edits the attributes of an IfcRecurrencePattern
For more information about the attributes and data types of an
IfcRecurrencePattern, consult the IFC documentation.
:param recurrence_pattern: The IfcRecurrencePattern entity you want to edit
:type recurrence_pattern: ifcopenshell.entity_instance.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
# Let's start defining the times that we work during the week.
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="WorkingTimes")
# We create a weekly recurrence
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
parent=work_time, recurrence_type="WEEKLY")
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
"""
self.file = file
self.settings = {"recurrence_pattern": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"recurrence_pattern": recurrence_pattern, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
@@ -21,11 +21,45 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, rel_sequence=None, attributes=None):
"""Edits the attributes of an IfcRelSequence
For more information about the attributes and data types of an
IfcRelSequence, consult the IFC documentation.
:param rel_sequence: The IfcRelSequence entity you want to edit
:type rel_sequence: ifcopenshell.entity_instance.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's imagine a root construction task
construction = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
# Let's imagine we're building 2 zones, one after another.
zone1 = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Zone 1", identification="C.1")
zone2 = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Zone 2", identification="C.2")
# Zone 1 finishes, then zone 2 starts.
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
relating_process=zone1, related_process=zone2)
# What if they both started at the same time?
ifcopenshell.api.run("sequence.edit_sequence", model,
rel_sequence=sequence, attributes={"SequenceType": "START_START"})
"""
self.file = file
self.settings = {"rel_sequence": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"rel_sequence": rel_sequence, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
@@ -18,11 +18,35 @@
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, task=None, attributes=None):
"""Edits the attributes of an IfcTask
For more information about the attributes and data types of an
IfcTask, consult the IFC documentation.
:param task: The IfcTask entity you want to edit
:type task: ifcopenshell.entity_instance.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Add a root task to represent the design milestones, and major
# project phases.
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Milestones", identification="A")
# Change the identification
ifcopenshell.api.run("sequence.edit_task", model, task=task, attributes={"Identification": "M"})
"""
self.file = file
self.settings = {"task": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"task": task, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
@@ -22,11 +22,36 @@ import ifcopenshell.util.sequence
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, task_time=None, attributes=None):
"""Edits the attributes of an IfcTaskTime
For more information about the attributes and data types of an
IfcTaskTime, consult the IFC documentation.
:param task_time: The IfcTaskTime entity you want to edit
:type task_time: ifcopenshell.entity_instance.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Create a task to do formwork
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Formwork", identification="A")
# Let's say it takes 2 days and starts on the 1st of January, 2000
time = ifcopenshell.api.run("sequence.add_task_time", model, task=formwork)
ifcopenshell.api.run("sequence.edit_task_time", model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
"""
self.file = file
self.settings = {"task_time": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"task_time": task_time, "attributes": attributes or {}}
def execute(self):
self.task = self.get_task()
@@ -18,11 +18,30 @@
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_calendar=None, attributes=None):
"""Edits the attributes of an IfcWorkCalendar
For more information about the attributes and data types of an
IfcWorkCalendar, consult the IFC documentation.
:param work_calendar: The IfcWorkCalendar entity you want to edit
:type work_calendar: ifcopenshell.entity_instance.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model, name="5 Day Week")
# Let's give it a description
ifcopenshell.api.run("sequence.edit_work_calendar", model,
work_calendar=calendar, attributes={"Description": "Monday to Friday 8 hour days"})
"""
self.file = file
self.settings = {"work_calendar": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_calendar": work_calendar, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
@@ -20,11 +20,30 @@ import ifcopenshell.util.date
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_plan=None, attributes=None):
"""Edits the attributes of an IfcWorkPlan
For more information about the attributes and data types of an
IfcWorkPlan, consult the IFC documentation.
:param work_plan: The IfcWorkPlan entity you want to edit
:type work_plan: ifcopenshell.entity_instance.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example::
# This will hold all our construction schedules
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
# Let's give it a description
ifcopenshell.api.run("sequence.edit_work_plan", model,
work_plan=work_plan, attributes={"Description": "Construction of phase 1"})
"""
self.file = file
self.settings = {"work_plan": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_plan": work_plan, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
@@ -20,11 +20,34 @@ import ifcopenshell.util.date
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_schedule=None, attributes=None):
"""Edits the attributes of an IfcWorkSchedule
For more information about the attributes and data types of an
IfcWorkSchedule, consult the IFC documentation.
:param work_schedule: The IfcWorkSchedule entity you want to edit
:type work_schedule: ifcopenshell.entity_instance.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example::
# This will hold all our construction schedules
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
# Let's imagine this is one of our schedules in our work plan.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
name="Construction Schedule A", work_plan=work_plan)
# Let's give it a description
ifcopenshell.api.run("sequence.edit_work_schedule", model,
work_schedule=work_schedule, attributes={"Description": "3 crane design option"})
"""
self.file = file
self.settings = {"work_schedule": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_schedule": work_schedule, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
@@ -20,11 +20,35 @@ import ifcopenshell.util.date
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_time=None, attributes=None):
"""Edits the attributes of an IfcWorkTime
For more information about the attributes and data types of an
IfcWorkTime, consult the IFC documentation.
:param work_time: The IfcWorkTime entity you want to edit
:type work_time: ifcopenshell.entity_instance.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
# Let's start defining the times that we work during the week.
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="WorkingTimes")
# Edit our work time to state that the work time only applies after
# a start date.
ifcopenshell.api.run("sequence.edit_work_time", model,
work_time=work_time, attributes={"StartDate": "2000-01-01"})
"""
self.file = file
self.settings = {"work_time": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_time": work_time, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
@@ -20,14 +20,45 @@ import ifcopenshell
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, relating_product=None, related_object=None):
"""Gets the related products being output by a task
This API function will be removed in the future and migrated to a
utility module.
:param relating_product: One of the products already output by the task.
:type relating_product: ifcopenshell.entity_instance.entity_instance
:param related_object: The IfcTask that you want to get all the related
products for.
:type related_object: ifcopenshell.entity_instance.entity_instance
:return: A set of IfcProducts output by the IfcTask.
:rtype: set[ifcopenshell.entity_instance.entity_instance]
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's create a construction task. Note that the predefined type is
# important to distinguish types of tasks.
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Build wall", identification="A", predefined_type="CONSTRUCTION")
# Let's say we have a wall somewhere.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# Let's construct that wall!
ifcopenshell.api.run("sequence.assign_product", relating_product=wall, related_object=task)
# This will give us a set with that wall in it.
products = ifcopenshell.api.run("sequence.get_related_products", model, related_object=task)
"""
self.file = file
self.settings = {
"relating_product": None,
"related_object": None,
"relating_product": relating_product,
"related_object": related_object,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
products = set()
@@ -24,11 +24,31 @@ import ifcopenshell.util.sequence
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_schedule=None):
"""Calculate the critical path and floats for a work schedule
This implements critical path analysis, using the forward pass and
backward pass method. When run, any tasks that have no float will be
marked as critical, and both the total and free floats will be
populated for all task times.
Cyclical relationships are detected and will result in a recursion
error.
:param work_schedule: The IfcWorkSchedule to perform the calculation on.
:type work_schedule: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# See the example for ifcopenshell.api.sequence.cascade_schedule for
# details of how to set up a basic set of tasks and calculate the
# critical path. Typically cascade_schedule is run prior to ensure
# that dates are correct.
"""
self.file = file
self.settings = {"work_schedule": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_schedule": work_schedule}
def execute(self):
# The method implemented is the same as shown here:
@@ -20,11 +20,38 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, task=None):
"""Removes a task
All subtasks are also removed recursively. Any relationships such as
sequences or controls are also removed.
:param task: The IfcTask to remove.
:type task: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Add a root task to represent the design milestones, and major
# project phases.
ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Milestones", identification="A")
design = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Design", identification="B")
ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
# Ah, let's delete the design section, who needs it anyway we'll
# just fix it on site.
ifcopenshell.api.run("sequence.remove_task", model, task=design)
"""
self.file = file
self.settings = {"task": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"task": task}
def execute(self):
# TODO: do a deep purge
@@ -20,11 +20,42 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, time_period=None):
"""Removes a time period
:param time_period: The IfcTimePeriod to remove.
:type time_period: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
# Let's start defining the times that we work during the week.
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="WorkingTimes")
# We create a weekly recurrence
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
parent=work_time, recurrence_type="WEEKLY")
# State that we work from weekdays 1 to 5 (i.e. Monday to Friday)
ifcopenshell.api.run("sequence.edit_recurrence_pattern", model,
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
# The morning work session, lunch, then the afternoon work session.
morning = ifcopenshell.api.run("sequence.add_time_period", model,
recurrence_pattern=pattern, start_time="09:00", end_time="12:00")
afternoon = ifcopenshell.api.run("sequence.add_time_period", model,
recurrence_pattern=pattern, start_time="13:00", end_time="17:00")
# Let's take the afternoon off!
ifcopenshell.api.run("sequence.remove_time_period", model, time_period=afternoon)
"""
self.file = file
self.settings = {"time_period": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"time_period": time_period}
def execute(self):
self.file.remove(self.settings["time_period"])
@@ -20,11 +20,27 @@ import ifcopenshell
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_calendar=None):
"""Removes a work calendar
All relationships are also removed, such as if a task is set to use that
calendar.
:param work_calendar: The IfcWorkCalendar to remove
:type work_calendar: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model, name="5 Day Week")
# And remove it immediately
ifcopenshell.api.run("sequence.remove_work_calendar", model, work_calendar=calendar)
"""
self.file = file
self.settings = {"work_calendar": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_calendar": work_calendar}
def execute(self):
# TODO: do a deep purge
@@ -20,11 +20,27 @@ import ifcopenshell
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_plan=None):
"""Removes a work plan
Note that schedules that are grouped under the work plan are not
removed.
:param work_plan: The IfcWorkPlan to remove.
:type work_plan: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# This will hold all our construction schedules
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
# And remove it immediately
ifcopenshell.api.run("sequence.remove_work_plan", model, work_plan=work_plan)
"""
self.file = file
self.settings = {"work_plan": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_plan": work_plan}
def execute(self):
# TODO: do a deep purge
@@ -20,11 +20,30 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_schedule=None):
"""Removes a work schedule
All tasks in the work schedule are also removed recursively.
:param work_schedule: The IfcWorkSchedule to remove.
:type work_schedule: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# This will hold all our construction schedules
work_plan = ifcopenshell.api.run("sequence.add_work_plan", model, name="Construction")
# Let's imagine this is one of our schedules in our work plan.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model,
name="Construction Schedule A", work_plan=work_plan)
# And remove it immediately
ifcopenshell.api.run("sequence.remove_work_schedule", model, work_schedule=schedule)
"""
self.file = file
self.settings = {"work_schedule": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_schedule": work_schedule}
def execute(self):
# TODO: do a deep purge
@@ -18,11 +18,28 @@
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, work_time=None):
"""Removes a work time
:param work_time: The IfcWorkTime to remove.
:type work_time: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
# Let's start defining the times that we work during the week.
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="WorkingTimes")
# And remove it immediately
ifcopenshell.api.run("sequence.remove_work_time", model, work_time=work_time)
"""
self.file = file
self.settings = {"work_time": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"work_time": work_time}
def execute(self):
self.file.remove(self.settings["work_time"])
@@ -20,13 +20,46 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, rel_sequence=None):
"""Removes any lag time in a sequence
The schedule is cascaded afterwards.
:param rel_sequence: The sequence to remove the lag time from.
:type rel_sequence: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's imagine a root construction task
construction = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
# Let's imagine we're building 2 zones, one after another.
zone1 = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Zone 1", identification="C.1")
zone2 = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Zone 2", identification="C.2")
# Zone 1 finishes, then zone 2 starts.
sequence = ifcopenshell.api.run("sequence.assign_sequence", model,
relating_process=zone1, related_process=zone2)
# What if you had to wait 1 week before you could start zone 2?
ifcopenshell.api.run("sequence.assign_lag_time", model, rel_sequence=sequence, lag_value="P1W")
# What if you didn't?
ifcopenshell.api.run("sequence.unassign_lag_time", model, rel_sequence=sequence)
"""
self.file = file
self.settings = {
"rel_sequence": None,
"rel_sequence": rel_sequence,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
if len(self.file.get_inverse(self.settings["rel_sequence"].TimeLag)) == 1:
@@ -21,14 +21,43 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, relating_process=None, related_object=None):
"""Unassigns a process and object relationship
See ifcopenshell.api.sequence.assign_process for details.
:param relating_process: The IfcTask in the relationship.
:type relating_process: ifcopenshell.entity_instance.entity_instance
:param related_object: The related object.
:type related_object: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's create a construction task. Note that the predefined type is
# important to distinguish types of tasks.
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Demolish existing", identification="A", predefined_type="DEMOLITION")
# Let's say we have a wall somewhere.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# Let's demolish that wall!
ifcopenshell.api.run("sequence.assign_process", model, relating_process=task, related_object=wall)
# Change our mind.
ifcopenshell.api.run("sequence.unassign_process", model, relating_process=task, related_object=wall)
"""
self.file = file
self.settings = {
"relating_process": None,
"related_object": None,
"relating_process": relating_process,
"related_object": related_object,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for rel in self.settings["related_object"].HasAssignments or []:
@@ -21,14 +21,43 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, relating_product=None, related_object=None):
"""Unassigns a product and object relationship
See ifcopenshell.api.sequence.assign_product for details.
:param relating_product: The IfcProduct in the relationship.
:type relating_product: ifcopenshell.entity_instance.entity_instance
:param related_object: The IfcTask in the relationship.
:type related_object: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's create a construction task. Note that the predefined type is
# important to distinguish types of tasks.
task = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Build wall", identification="A", predefined_type="CONSTRUCTION")
# Let's say we have a wall somewhere.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# Let's construct that wall!
ifcopenshell.api.run("sequence.assign_product", relating_product=wall, related_object=task)
# Change our mind.
ifcopenshell.api.run("sequence.unassign_product", relating_product=wall, related_object=task)
"""
self.file = file
self.settings = {
"relating_product": None,
"related_object": None,
"relating_product": relating_product,
"related_object": related_object,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for rel in self.settings["related_object"].HasAssignments or []:
@@ -20,11 +20,35 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, recurrence_pattern=None):
"""Unassigns a recurrence pattern
Note that a recurring task time must have a recurrence pattern, so if
you remove it, be sure to clean up after yourself.
:param recurrence_pattern: The IfcRecurrencePattern to remove.
:type recurrence_pattern: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Let's create a new calendar.
calendar = ifcopenshell.api.run("sequence.add_work_calendar", model)
# Let's start defining the times that we work during the week.
work_time = ifcopenshell.api.run("sequence.add_work_time", model,
work_calendar=calendar, time_type="WorkingTimes")
# We create a weekly recurrence
pattern = ifcopenshell.api.run("sequence.assign_recurrence_pattern", model,
parent=work_time, recurrence_type="WEEKLY")
# Change our mind, let's just maintain it whenever we feel like it.
ifcopenshell.api.run("sequence.unassign_recurrence_pattern", recurrence_pattern=pattern)
"""
self.file = file
self.settings = {"recurrence_pattern": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"recurrence_pattern": recurrence_pattern}
def execute(self):
self.file.remove(self.settings["recurrence_pattern"])
@@ -21,14 +21,44 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, relating_process=None, related_process=None):
"""Removes a sequence relationship between tasks
:param relating_process: The previous / predecessor task.
:type relating_process: ifcopenshell.entity_instance.entity_instance
:param related_process: The next / successor task.
:type related_process: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Let's imagine we are creating a construction schedule. All tasks
# need to be part of a work schedule.
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction Schedule A")
# Let's imagine a root construction task
construction = ifcopenshell.api.run("sequence.add_task", model,
work_schedule=schedule, name="Construction", identification="C")
# Let's imagine we're building 2 zones, one after another.
zone1 = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Zone 1", identification="C.1")
zone2 = ifcopenshell.api.run("sequence.add_task", model,
parent_task=construction, name="Zone 2", identification="C.2")
# Zone 1 finishes, then zone 2 starts.
ifcopenshell.api.run("sequence.assign_sequence", model, relating_process=zone1, related_process=zone2)
# Let's make them unrelated
ifcopenshell.api.run("sequence.unassign_sequence", model,
relating_process=zone1, related_process=zone2)
"""
self.file = file
self.settings = {
"relating_process": None,
"related_process": None,
"relating_process": relating_process,
"related_process": related_process,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for rel in self.settings["related_process"].IsSuccessorFrom or []: