Module: CollectionObject::DwcExtensions

Extended by:
ActiveSupport::Concern
Included in:
CollectionObject, BiologicalCollectionObject
Defined in:
app/models/collection_object/dwc_extensions.rb

Instance Method Summary collapse

Instance Method Details

TODO: likeley a helper



161
162
163
164
165
166
167
168
169
170
# File 'app/models/collection_object/dwc_extensions.rb', line 161

def api_image_link(image)
  s = ENV['SERVER_NAME']
  if s.nil?
    s ||= 'http://127.0.0.1:3000'
  else
    s = 'https://' + s
  end

  s = s + '/api/v1/images/' + image.image_file_fingerprint # An experiment, use md5 as a proxy for id (also unique id)
end

#dwc_associated_mediaObject



156
157
158
# File 'app/models/collection_object/dwc_extensions.rb', line 156

def dwc_associated_media
  images.collect{|i| api_image_link(i) }.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_catalog_numberObject



412
413
414
# File 'app/models/collection_object/dwc_extensions.rb', line 412

def dwc_catalog_number
  catalog_number_cached # via delegation
end

#dwc_collection_codeObject



408
409
410
# File 'app/models/collection_object/dwc_extensions.rb', line 408

def dwc_collection_code
  catalog_number_namespace&.verbatim_short_name || catalog_number_namespace&.short_name
end

#dwc_coordinate_uncertainty_in_metersObject

TODO: extend to Georeferences when we understand how to describe spatial uncertainty



207
208
209
210
211
212
213
# File 'app/models/collection_object/dwc_extensions.rb', line 207

def dwc_coordinate_uncertainty_in_meters
  if georeference_attributes[:coordinateUncertaintyInMeters]
    georeference_attributes[:coordinateUncertaintyInMeters]
  else
    collecting_event&.verbatim_geolocation_uncertainty
  end
end

#dwc_countryObject



421
422
423
424
# File 'app/models/collection_object/dwc_extensions.rb', line 421

def dwc_country
  v = try(:collecting_event).try(:geographic_names)
  v[:country] if v
end

#dwc_countyObject



431
432
433
434
# File 'app/models/collection_object/dwc_extensions.rb', line 431

def dwc_county
  v = try(:collecting_event).try(:geographic_names)
  v[:county] if v
end

#dwc_date_identifiedObject

ISO 8601:2004(E).



333
334
335
# File 'app/models/collection_object/dwc_extensions.rb', line 333

def dwc_date_identified
  current_taxon_determination&.date.presence
end

#dwc_dayObject



496
497
498
499
# File 'app/models/collection_object/dwc_extensions.rb', line 496

def dwc_day
  return unless collecting_event
  collecting_event.start_date_day.presence
end

#dwc_decimal_latitudeObject



440
441
442
# File 'app/models/collection_object/dwc_extensions.rb', line 440

def dwc_decimal_latitude
  georeference_attributes[:decimalLatitude]
end

#dwc_decimal_longitudeObject



444
445
446
# File 'app/models/collection_object/dwc_extensions.rb', line 444

def dwc_decimal_longitude
  georeference_attributes[:decimalLongitude]
end

#dwc_end_day_of_yearObject



506
507
508
509
# File 'app/models/collection_object/dwc_extensions.rb', line 506

def dwc_end_day_of_year
  return unless collecting_event
  collecting_event.end_day_of_year.presence
end

#dwc_event_dateObject



473
474
475
476
477
478
479
480
481
482
483
484
# File 'app/models/collection_object/dwc_extensions.rb', line 473

def dwc_event_date
  return unless collecting_event

  %w{start_date end_date}
    .map { |d| %w{year month day}
    .map { |p| collecting_event["#{d}_#{p}"] }
    .map { |p| "%02d" % p if p } # At least two digits
    }
      .map { |d| d.compact.join('-') }
      .reject(&:blank?)
      .join("/").presence
end

#dwc_event_timeObject



456
457
458
459
460
461
462
463
464
465
466
467
# File 'app/models/collection_object/dwc_extensions.rb', line 456

def dwc_event_time
  return unless collecting_event

  %w{start_time end_time}
    .map { |t| %w{hour minute second}
    .map { |p| collecting_event["#{t}_#{p}"] }
    .map { |p| "%02d" % p if p } # At least two digits
    }
      .map { |t| t.compact.join(':') }
      .reject(&:blank?)
      .join("/").presence
end

#dwc_familyObject



342
343
344
# File 'app/models/collection_object/dwc_extensions.rb', line 342

def dwc_family
  taxonomy['family']
end

#dwc_field_numberObject



305
306
307
308
# File 'app/models/collection_object/dwc_extensions.rb', line 305

def dwc_field_number
  return nil unless collecting_event
  collecting_event.identifiers.where(type: 'Identifier::Local::TripCode').first&.cached
end

#dwc_footprint_wktObject



180
181
182
# File 'app/models/collection_object/dwc_extensions.rb', line 180

def dwc_footprint_wkt
  georeference_attributes[:footprintWKT]
end

#dwc_genusObject



347
348
349
# File 'app/models/collection_object/dwc_extensions.rb', line 347

def dwc_genus
  taxonomy['genus'] && taxonomy['genus'].compact.join(' ').presence
end

#dwc_geodetic_datumObject



192
193
194
# File 'app/models/collection_object/dwc_extensions.rb', line 192

def dwc_geodetic_datum
  georeference_attributes[:geodeticDatum]
end

#dwc_georeference_protocolObject



525
526
527
# File 'app/models/collection_object/dwc_extensions.rb', line 525

def dwc_georeference_protocol
  georeference_attributes[:georeferenceProtocol]
end

#dwc_georeference_remarksObject



176
177
178
# File 'app/models/collection_object/dwc_extensions.rb', line 176

def dwc_georeference_remarks
  georeference_attributes[:georeferenceRemarks]
end

#dwc_georeference_sourcesObject



172
173
174
# File 'app/models/collection_object/dwc_extensions.rb', line 172

def dwc_georeference_sources
  georeference_attributes[:georeferenceSources]
end

#dwc_georeferenced_byObject



184
185
186
# File 'app/models/collection_object/dwc_extensions.rb', line 184

def dwc_georeferenced_by
  georeference_attributes[:georeferencedBy]
end

#dwc_georeferenced_dateObject

georeferenceDate technically could look at papertrail to see when geographic_area_id appeared



202
203
204
# File 'app/models/collection_object/dwc_extensions.rb', line 202

def dwc_georeferenced_date
  georeference_attributes[:georeferencedDate]
end

#dwc_identified_byObject



394
395
396
397
# File 'app/models/collection_object/dwc_extensions.rb', line 394

def dwc_identified_by
  # TaxonWorks allows for groups of determiners to collaborate on a single determination if they collectively came to a conclusion.
  current_taxon_determination&.determiners&.map(&:cached)&.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_identified_by_idObject



399
400
401
402
# File 'app/models/collection_object/dwc_extensions.rb', line 399

def dwc_identified_by_id
  # TaxonWorks allows for groups of determiners to collaborate on a single determination if they collectively came to a conclusion.
  current_taxon_determination&.determiners&.map(&:orcid)&.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_individual_countObject

TODO: handle ranged lots



417
418
419
# File 'app/models/collection_object/dwc_extensions.rb', line 417

def dwc_individual_count
  total
end

#dwc_infraspecific_epithetObject



314
315
316
317
318
319
# File 'app/models/collection_object/dwc_extensions.rb', line 314

def dwc_infraspecific_epithet
  %w{variety form subspecies}.each do |n| # add more as observed
    return taxonomy[n].last if taxonomy[n]
  end
  nil
end

#dwc_institution_codeObject

we assert custody, NOT ownership



516
517
518
# File 'app/models/collection_object/dwc_extensions.rb', line 516

def dwc_institution_code
  repository.try(:acronym)
end

#dwc_institution_idObject

we assert custody, NOT ownership



521
522
523
# File 'app/models/collection_object/dwc_extensions.rb', line 521

def dwc_institution_id
  repository_url
end

#dwc_internal_attribute_for(target = :collection_object, dwc_term_name) ⇒ Object



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'app/models/collection_object/dwc_extensions.rb', line 235

def dwc_internal_attribute_for(target = :collection_object, dwc_term_name)
  return nil if dwc_term_name.nil?

  case target
  when  :collecting_event
    return nil unless collecting_event
    collecting_event.internal_attributes.includes(:predicate)
      .where(
        controlled_vocabulary_terms: {uri: ::DWC_ATTRIBUTE_URIS[dwc_term_name.to_sym] })
      .pluck(:value)&.join(', ').presence
  when :collection_object
    internal_attributes.includes(:predicate)
      .where(
        controlled_vocabulary_terms: {uri: ::DWC_ATTRIBUTE_URIS[dwc_term_name.to_sym] })
      .pluck(:value)&.join(', ').presence
  else
    nil
  end
end

#dwc_kingdomObject



337
338
339
# File 'app/models/collection_object/dwc_extensions.rb', line 337

def dwc_kingdom
  taxonomy['kingdom']
end

#dwc_life_stageObject

TODO: consider CVT attributes with Predicates linked to URIs



272
273
274
275
# File 'app/models/collection_object/dwc_extensions.rb', line 272

def dwc_life_stage
  biocuration_classes.tagged_with_uri(::DWC_ATTRIBUTE_URIS[:lifeStage])
    .pluck(:name)&.join(', ').presence # `.presence` is a Rails extension
end

#dwc_localityObject



436
437
438
# File 'app/models/collection_object/dwc_extensions.rb', line 436

def dwc_locality
  collecting_event.try(:verbatim_locality)
end

#dwc_maximum_depth_in_metersObject



263
264
265
# File 'app/models/collection_object/dwc_extensions.rb', line 263

def dwc_maximum_depth_in_meters
  dwc_internal_attribute_for(:collecting_event, :maximumDepthInMeters)
end

#dwc_maximum_elevation_in_metersObject



292
293
294
# File 'app/models/collection_object/dwc_extensions.rb', line 292

def dwc_maximum_elevation_in_meters
  collecting_event&.maximum_elevation
end

#dwc_minimum_depth_in_metersObject



259
260
261
# File 'app/models/collection_object/dwc_extensions.rb', line 259

def dwc_minimum_depth_in_meters
  dwc_internal_attribute_for(:collecting_event, :minimumDepthInMeters)
end

#dwc_minimum_elevation_in_metersObject



296
297
298
# File 'app/models/collection_object/dwc_extensions.rb', line 296

def dwc_minimum_elevation_in_meters
  collecting_event&.minimum_elevation
end

#dwc_monthObject



491
492
493
494
# File 'app/models/collection_object/dwc_extensions.rb', line 491

def dwc_month
  return unless collecting_event
  collecting_event.start_date_month.presence
end

#dwc_nomenclatural_codeObject



452
453
454
# File 'app/models/collection_object/dwc_extensions.rb', line 452

def dwc_nomenclatural_code
  current_otu.try(:taxon_name).try(:nomenclatural_code)
end

#dwc_occurrence_remarksObject



151
152
153
# File 'app/models/collection_object/dwc_extensions.rb', line 151

def dwc_occurrence_remarks
  notes.collect{|n| n.text}.join('|')
end

#dwc_occurrence_statusObject



146
147
148
# File 'app/models/collection_object/dwc_extensions.rb', line 146

def dwc_occurrence_status
  'present'
end

#dwc_other_catalog_numbersObject



223
224
225
226
227
# File 'app/models/collection_object/dwc_extensions.rb', line 223

def dwc_other_catalog_numbers
  i = identifiers.where.not('type ilike ?', 'Identifier::Global::Uuid%').order(:position).to_a
  i.shift
  i.map(&:cached).join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_preparationsObject



511
512
513
# File 'app/models/collection_object/dwc_extensions.rb', line 511

def dwc_preparations
  preparation_type_name
end

#dwc_previous_identificationsObject



229
230
231
232
233
# File 'app/models/collection_object/dwc_extensions.rb', line 229

def dwc_previous_identifications
  a = taxon_determinations.order(:position).to_a
  a.shift
  a.collect{|d| ApplicationController.helpers.label_for_taxon_determination(d)}.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_recorded_byObject

Definition: A list (concatenated and separated) of names of people, groups, or organizations responsible for recording the original Occurrence. The primary collector or observer, especially one who applies a personal identifier (recordNumber), should be listed first.

This was interpreted as collectors (in the field in this context), not those who recorded other aspectes of the data.



367
368
369
370
371
372
373
374
375
376
377
378
# File 'app/models/collection_object/dwc_extensions.rb', line 367

def dwc_recorded_by
  v = nil
  if collecting_event
    v = collecting_event.collectors
      .order('roles.position')
      .pluck(:cached)
      .join(CollectionObject::DWC_DELIMITER)
      .presence
    v = collecting_event.verbatim_collectors.presence if v.blank?
  end
  v
end

#dwc_recorded_by_idObject

See dwc_recorded_by



381
382
383
384
385
386
387
388
389
390
391
392
# File 'app/models/collection_object/dwc_extensions.rb', line 381

def dwc_recorded_by_id

  if collecting_event
    collecting_event.collectors
      .order('roles.position')
      .map(&:orcid)
      .compact
      .join(CollectionObject::DWC_DELIMITER)
      .presence
  end

end

#dwc_sampling_protocolObject

TODO: Reconcile with Protocol (capital P) assignments



301
302
303
# File 'app/models/collection_object/dwc_extensions.rb', line 301

def dwc_sampling_protocol
  collecting_event&.verbatim_method
end

#dwc_scientific_nameObject



356
357
358
# File 'app/models/collection_object/dwc_extensions.rb', line 356

def dwc_scientific_name
  current_taxon_name.try(:cached_name_and_author_year)
end

#dwc_sexObject

TODO: consider CVT attributes with Predicates linked to URIs



278
279
280
281
# File 'app/models/collection_object/dwc_extensions.rb', line 278

def dwc_sex
  biocuration_classes.tagged_with_uri(::DWC_ATTRIBUTE_URIS[:sex])
    .pluck(:name)&.join(', ').presence
end

#dwc_specific_epithetObject



352
353
354
# File 'app/models/collection_object/dwc_extensions.rb', line 352

def dwc_specific_epithet
  taxonomy['species'] && taxonomy['species'].compact.join(' ').presence
end

#dwc_start_day_of_yearObject



501
502
503
504
# File 'app/models/collection_object/dwc_extensions.rb', line 501

def dwc_start_day_of_year
  return unless collecting_event
  collecting_event.start_day_of_year.presence
end

#dwc_state_provinceObject



426
427
428
429
# File 'app/models/collection_object/dwc_extensions.rb', line 426

def dwc_state_province
  v = try(:collecting_event).try(:geographic_names)
  v[:state] if v
end

#dwc_taxon_name_authorshipObject



360
361
362
# File 'app/models/collection_object/dwc_extensions.rb', line 360

def dwc_taxon_name_authorship
  current_taxon_name.try(:cached_author_year)
end

#dwc_taxon_rankObject



321
322
323
# File 'app/models/collection_object/dwc_extensions.rb', line 321

def dwc_taxon_rank
  current_taxon_name&.rank
end

#dwc_type_statusObject

holotype of Ctenomys sociabilis. Pearson O. P., and M. I. Christie. 1985. Historia Natural, 5(37):388, holotype of Pinus abies | holotype of Picea abies



326
327
328
329
330
# File 'app/models/collection_object/dwc_extensions.rb', line 326

def dwc_type_status
  type_materials.all.collect{|t|
    ApplicationController.helpers.label_for_type_material(t)
  }.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_verbatim_coordinatesObject



283
284
285
286
# File 'app/models/collection_object/dwc_extensions.rb', line 283

def dwc_verbatim_coordinates
  return nil unless collecting_event
  [collecting_event.verbatim_latitude, collecting_event.verbatim_longitude].compact.join(' ').presence
end

#dwc_verbatim_depthObject



267
268
269
# File 'app/models/collection_object/dwc_extensions.rb', line 267

def dwc_verbatim_depth
  dwc_internal_attribute_for(:collecting_event, :verbatimDepth)
end

#dwc_verbatim_elevationObject



288
289
290
# File 'app/models/collection_object/dwc_extensions.rb', line 288

def dwc_verbatim_elevation
  collecting_event&.verbatim_elevation
end

#dwc_verbatim_event_dateObject



469
470
471
# File 'app/models/collection_object/dwc_extensions.rb', line 469

def dwc_verbatim_event_date
  collecting_event&.verbatim_date
end

#dwc_verbatim_habitatObject



310
311
312
# File 'app/models/collection_object/dwc_extensions.rb', line 310

def dwc_verbatim_habitat
  collecting_event&.verbatim_habitat
end

#dwc_verbatim_latitudeObject



215
216
217
# File 'app/models/collection_object/dwc_extensions.rb', line 215

def dwc_verbatim_latitude
  collecting_event&.verbatim_latitude
end

#dwc_verbatim_localityObject



448
449
450
# File 'app/models/collection_object/dwc_extensions.rb', line 448

def dwc_verbatim_locality
  collecting_event.try(:verbatim_locality)
end

#dwc_verbatim_longitudeObject



219
220
221
# File 'app/models/collection_object/dwc_extensions.rb', line 219

def dwc_verbatim_longitude
  collecting_event&.verbatim_longitude
end

#dwc_verbatim_srsObject



196
197
198
# File 'app/models/collection_object/dwc_extensions.rb', line 196

def dwc_verbatim_srs
  georeference_attributes[:dwcVerbatimSrs]
end

#dwc_water_bodyObject



255
256
257
# File 'app/models/collection_object/dwc_extensions.rb', line 255

def dwc_water_body
  dwc_internal_attribute_for(:collecting_event, :waterBody)
end

#dwc_yearObject



486
487
488
489
# File 'app/models/collection_object/dwc_extensions.rb', line 486

def dwc_year
  return unless collecting_event
  collecting_event.start_date_year.presence
end

#is_fossil?Boolean

Returns:

  • (Boolean)


142
143
144
# File 'app/models/collection_object/dwc_extensions.rb', line 142

def is_fossil?
  biocuration_classes.where(uri: DWC_FOSSIL_URI).any?
end

#set_georeference_attributesHash

Returns:

  • (Hash)


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'app/models/collection_object/dwc_extensions.rb', line 112

def set_georeference_attributes
  case collecting_event&.dwc_georeference_source
  when :georeference
    collecting_event.preferred_georeference.dwc_georeference_attributes
  when :verbatim
    h = collecting_event.dwc_georeference_attributes

    if a = collecting_event&.attribute_updater(:verbatim_latitude)
      h[:georeferencedBy] = User.find(a).name
    end

    # verbatim_longitude could technically be different, but...
    h[:georeferencedDate] = collecting_event&.attribute_updated(:verbatim_latitude)

    h

  when :geographic_area
    h = collecting_event.geographic_area.dwc_georeference_attributes
    if a = collecting_event&.attribute_updater(:geographic_area_id)
      h[:georeferencedBy] = User.find(a).name
    end

    h[:georeferencedDate] = collecting_event&.attribute_updated(:geographic_area_id)

    h
  else
    {}
  end
end