docs: def build_asset_array(assets_by_site, tagnames=(), time_event=None):
      """
      :param assets_by_site: a list of lists of assets
      :param tagnames: a list of tag names
      :returns: an array `assetcol`
      """
      for assets in assets_by_site:
          if len(assets):
              first_asset = assets[0]
              break
      else:  # no break
          raise ValueError('There are no assets!')
      loss_types = []
      occupancy_periods = []
      for name in sorted(first_asset.values):
          if name.startswith('occupants_'):
              period = name.split('_', 1)[1]
              if period != 'None':
                  # see scenario_risk test_case_2d
                  occupancy_periods.append(period)
              loss_types.append(name)
              # discard occupants for different time periods
          else:
              loss_types.append('value-' + name)
      # loss_types can be ['value-business_interruption', 'value-contents',
      # 'value-nonstructural', 'occupants_None', 'occupants_day',
      # 'occupants_night', 'occupants_transit']
      deductible_d = first_asset.deductibles or {}
      limit_d = first_asset.insurance_limits or {}
      if deductible_d or limit_d:
          logging.warning('Exposures with insuranceLimit/deductible fields are '
                          'deprecated and may be removed in the future')
      retro = ['retrofitted'] if first_asset._retrofitted else []
      float_fields = loss_types + retro
      int_fields = [(str(name), U16) for name in tagnames]
      tagi = {str(name): i for i, name in enumerate(tagnames)}
      asset_dt = numpy.dtype(
          [('ordinal', U32), ('lon', F32), ('lat', F32), ('site_id', U32),
           ('number', F32), ('area', F32)] + [
               (str(name), float) for name in float_fields] + int_fields)
      num_assets = sum(len(assets) for assets in assets_by_site)
      assetcol = numpy.zeros(num_assets, asset_dt)
      asset_ordinal = 0
      fields = set(asset_dt.fields)
      for sid, assets_ in enumerate(assets_by_site):
          for asset in assets_:
              asset.ordinal = asset_ordinal
              record = assetcol[asset_ordinal]
              asset_ordinal += 1
              for field in fields:
                  if field == 'ordinal':
                      value = asset.ordinal
                  elif field == 'number':
                      value = asset.number
                  elif field == 'area':
                      value = asset.area
                  elif field == 'site_id':
                      value = sid
                  elif field == 'lon':
                      value = asset.location[0]
                  elif field == 'lat':
                      value = asset.location[1]
                  elif field.startswith('occupants_'):
                      value = asset.values[field]
                  elif field == 'retrofitted':
                      value = asset.retrofitted()
                  elif field in tagnames:
                      value = asset.tagidxs[tagi[field]]
                  else:
                      name, lt = field.split('-')
                      value = asset.value(lt, time_event)
                  record[field] = value
      return assetcol, ' '.join(occupancy_periods)